Update setup script using new lint rules

No functional changes, I just wanted to tidy things up.
This commit is contained in:
Trysdyn Black 2023-12-28 18:01:11 -08:00
parent ff2faf4e4c
commit 91b6e2377f

View file

@ -1,25 +1,24 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Dotfile setup utility.
Syncronizes dotfiles from a source dir that mimics a homedir tree to a homedir, Syncronizes dotfiles from a source dir that mimics a homedir tree to a homedir,
removing old symlinks as necessary as well as optionally files. removing old symlinks as necessary as well as optionally files.
""" """
import os import inspect
import pathlib import os # Needed for os.walk til Py3.12
from pathlib import Path
FORCE = False FORCE = False
HOMEDIR = os.path.expanduser("~") HOMEDIR = Path("~").expanduser()
SOURCEDIR = os.path.dirname(os.path.join(os.path.realpath(__file__))) 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. 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. 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 # Destination exists as a symlink
if os.path.islink(destination): if Path(destination).is_symlink():
# Symlink is correct, return # Symlink is correct, return
if os.readlink(destination) == source: if Path(destination).readlink() == source:
return False return False
# Symlink is incorrect, remove it # Symlink is incorrect, remove it
os.unlink(destination) Path(destination).unlink()
# Destination exists as a file # Destination exists as a file
elif os.path.exists(destination): elif Path(destination).exists():
# Force mode enabled, remove it (Data loss risk!!) # Force mode enabled, remove it (Data loss risk!!)
if force: if force:
os.remove(destination) Path(destination).unlink()
# Force mode disabled, error out # Force mode disabled, error out
else: 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 # File doesn't exist or undefined "thing" happened, return True to try to
# write, and if something goes wrong, we'll see the OSError # write, and if something goes wrong, we'll see the OSError
return True 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 Iterate files in SOURCEDIR and create symlinks to them in HOMEDIR.
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 + "/"
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): for root, dir_names, file_names in os.walk(source_dir):
# Remove exclusions from the walk list so we don't touch them # Remove exclusions from the walk list so we don't touch them
for exclusion in exclusions: for exclusion in exclusions:
@ -69,18 +67,18 @@ def install_dotfiles(source_dir, dest_dir, exclusions, force=False):
for file_name in file_names: for file_name in file_names:
# Get the full path for the source file # 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 # Get the full path for where the symlink should go
# We remove the source_dir to get a dotfile dir relative path # 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 # Check for and remove the destination file if it exists
# If a removal occurs, catch True and deploy the symlink # If a removal occurs, catch True and deploy the symlink
if check_and_remove(source, destination, force): if check_and_remove(source, destination, force=force):
print("Symlinking " + source + " => " + destination) print(f"Symlinking {source} => {destination}")
os.symlink(source, destination) os.symlink(source, destination)
if __name__ == "__main__": if __name__ == "__main__":
install_dotfiles(SOURCEDIR, HOMEDIR, EXCLUSIONS, False) install_dotfiles(SOURCEDIR, HOMEDIR, EXCLUSIONS, force=False)