From 91b6e2377f194130bae34028dc025444b7325f80 Mon Sep 17 00:00:00 2001 From: Trysdyn Black Date: Thu, 28 Dec 2023 18:01:11 -0800 Subject: [PATCH] Update setup script using new lint rules No functional changes, I just wanted to tidy things up. --- setup_dotfiles.py | 58 +++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/setup_dotfiles.py b/setup_dotfiles.py index 26af1ea..468bfd2 100755 --- a/setup_dotfiles.py +++ b/setup_dotfiles.py @@ -1,25 +1,24 @@ #!/usr/bin/env python3 """ +Dotfile setup utility. + Syncronizes dotfiles from a source dir that mimics a homedir tree to a homedir, removing old symlinks as necessary as well as optionally files. """ -import os -import pathlib +import inspect +import os # Needed for os.walk til Py3.12 +from pathlib import Path FORCE = False -HOMEDIR = os.path.expanduser("~") -SOURCEDIR = os.path.dirname(os.path.join(os.path.realpath(__file__))) +HOMEDIR = Path("~").expanduser() +SOURCEDIR = Path(str(inspect.getsourcefile(lambda: False))).parent +EXCLUSIONS = [".git", "setup_dotfiles.py", "README.md"] -EXCLUSIONS = [ - ".git", - "setup_dotfiles.py", - "README.md" - ] -def check_and_remove(source, destination, force=False): +def check_and_remove(source: Path, destination: Path, *, force: bool = False) -> bool: """ - Checks if a file exists and removes it if appropriate. + Check if a file exists and remove it if appropriate. If it's a symlink we check it points the right place and remove it if not. @@ -27,38 +26,37 @@ def check_and_remove(source, destination, force=False): If we need to re-deploy the symlink, return True, else return False. """ - pathlib.Path(os.path.dirname(destination)).mkdir(parents=True, exist_ok=True) + Path(destination).parent.mkdir(parents=True, exist_ok=True) # Destination exists as a symlink - if os.path.islink(destination): + if Path(destination).is_symlink(): # Symlink is correct, return - if os.readlink(destination) == source: + if Path(destination).readlink() == source: return False # Symlink is incorrect, remove it - os.unlink(destination) + Path(destination).unlink() # Destination exists as a file - elif os.path.exists(destination): + elif Path(destination).exists(): # Force mode enabled, remove it (Data loss risk!!) if force: - os.remove(destination) + Path(destination).unlink() # Force mode disabled, error out else: - raise OSError(destination + " exists as a file and --force not provided") + msg = f"{destination!s} exists as a file and --force not provided" + raise OSError(msg) # File doesn't exist or undefined "thing" happened, return True to try to # write, and if something goes wrong, we'll see the OSError return True -def install_dotfiles(source_dir, dest_dir, exclusions, force=False): +def install_dotfiles(source_dir: Path, dest_dir: Path, exclusions: list, *, force: bool = False) -> None: """ - Iterates the files present in source_dir, excluding EXCLUSIONS, and symlinks - them in dest_dir, overwriting files that exist if force is true. - """ - # source_dir needs to end in an / to make replacements work - if not source_dir.endswith("/"): - source_dir = source_dir + "/" + Iterate files in SOURCEDIR and create symlinks to them in HOMEDIR. + We also exclude files noted in exclusions, and will remove files in the way + if "force" is true. + """ for root, dir_names, file_names in os.walk(source_dir): # Remove exclusions from the walk list so we don't touch them for exclusion in exclusions: @@ -69,18 +67,18 @@ def install_dotfiles(source_dir, dest_dir, exclusions, force=False): for file_name in file_names: # Get the full path for the source file - source = os.path.join(root, file_name) + source = Path(root) / file_name # Get the full path for where the symlink should go # We remove the source_dir to get a dotfile dir relative path - destination = os.path.join(dest_dir, source.replace(source_dir, '')) + destination = dest_dir / source.relative_to(source_dir) # Check for and remove the destination file if it exists # If a removal occurs, catch True and deploy the symlink - if check_and_remove(source, destination, force): - print("Symlinking " + source + " => " + destination) + if check_and_remove(source, destination, force=force): + print(f"Symlinking {source} => {destination}") os.symlink(source, destination) if __name__ == "__main__": - install_dotfiles(SOURCEDIR, HOMEDIR, EXCLUSIONS, False) + install_dotfiles(SOURCEDIR, HOMEDIR, EXCLUSIONS, force=False)