# Don't repeat yourself

```python
    def run_non_essentials(self):
        """ Run the installation processes. """
        result = True
        print("Installing Google Chrome...")
        if not self.install_google_chrome():
            self.failure_log.append("Install Google Chrome")
            result = False
        print("Installing HMSS...")
        if not self.install_hmss():
            self.failure_log.append("Install HMSS")
        print("Installing Kingdom of Cyprus...")
        if not self.install_kingdom_of_cyprus():
            self.failure_log.append("Install Kingdom of Cyprus")
            result = False
        print("Installing Chancery repos...")
        if not self.install_chancery():
            self.failure_log.append("Install Chancery repos")
            result = False
        print("Installing HGMJ...")
        if not self.install_hgmj():
            self.failure_log.append("Install HGMJ")
            result = False
        print("Installing other third party...")
        if not self.install_other_third_party():
            self.failure_log.append("Install other third party")
            result = False
        print("Changing wallpaper...")
        if not self.change_wallpaper():
            self.failure_log.append("Change wallpaper")
            # It doesn't matter too much if this fails.
        return result
```
Can be generalized into:

```python
OPTIONAL_PROGRAMS = {
    "Google Chrome": install_google_chrome,
    "HMSS": install_hmss,
    "Kingdom of Cyprus": install_kingdom_of_cyprus,
    ...
}

[...]

class HMSoftwareInstaller:
    [...]
    
    def install(name: str, function: Callable[[], bool]) -> bool:
        print(f"Installing {name}...")
        
        if not (result := function()):
            self.failure_log.append(f"Install {name}")
        
        return result

    def run_non_essentials(self) -> bool:
        """ Run the installation processes. """
        
        return all(self.install(*program) for program in OPTIONAL_PROGRAMS.items())
```

The functions invoked do not use `self` anyway, so they should be redefined as pure functions.

The same applies to `run_essentials()`.


# Consider using `pathlib.Path`
...to manage paths, rather than the `os.*` functions.