Some time back I wrote an introduction to my newest application available on GitHub at the time: Easy Home Directory Backup. Excitement gripped me as I celebrated the release here on my website and on my social media accounts. Later, when I wanted to add a new feature to the program I discovered something terrible: Some parts of the application didn’t work at all. That meant I couldn’t add the new feature until I refactored Easy Home Directory Backup.
Why I Refactored Easy Home Directory Backup
In the first version of the application I gave users the options to perform two types of partial backups:
- All files except dot (.) files
- Only dot (.) files
Well, the first option worked, but not the second. Looking back I didn’t test the second option enough to realize my code was incorrect. Where I messed up was the option I passed into the rsync command:
subprocess.run(["rsync", "-az", "--exclude=* --include=.*",
f"--log-file={path}/easy_home_directory_backup_{formatted_today_date}_log_file",
home_dir_path, backup_device_path])
I incorrectly thought the –exclude=* –include=.* code would exclude all the files in the user’s Home Directory, and then back up only the dot (.) files. That didn’t happen when I ran the program on my computer. Thus, I worked to fix my mistake. However, I couldn’t.
I tried all different combinations, but I couldn’t get this partial type of backup to work. Every time the application would back up both the non-dot (.) and dot (.) files.
At an impasse I actually thought about this part of my program. I asked myself these questions:
- Is this type of partial backup actually useful?
- Would the end user choose this option?
- Does anyone really want to back up all their dot (.) files?
After determining this use case was too small I knew it was time for a change. Thus, I refactored Easy Home Directory.
What Did I Change?
In total I changed ten files. The file seeing the biggest change was src/partial_backup.py as I removed 81 lines.
The determine_partial_backup_type function disappeared completely because there wasn’t two different partial backup options anymore. That accounted for 76 lines of code I deleted. This made the partial_backup function shorter in length, and easier to read and understand. The main code runs in these 26 lines:
else:
# If the user-supplied backup device path is invalid
if not validate_backup_path(device_path):
partial_backup()
else:
check_free_space_for_backup(path, home_dir_path)
today_date: datetime = datetime.today()
formatted_today_date_and_time: str = today_date.strftime("%b-%d-%Y_%I:%M%p")
# Create a directory on the backup device named after the formatted today's date of the backup
backup_device_path: str = f"{path}/{formatted_today_date_and_time}"
make_log_file_directory()
console.print()
console.print("Preparing to start the partial backup in a minute or so.", justify="center")
console.print()
# Progress bar from tqdm
for _ in tqdm(range(100), desc="Backup Progress", unit="GB"):
"""rsync options
a = Archive
"""
subprocess.run(["rsync", "-a", "--exclude=.*",
f"--log-file={home_dir_path}/.easy_home_directory_backup/{formatted_today_date_and_time}_log_file",
home_dir_path, backup_device_path])
console.print()
console.print(f"A log of this backup can be found in {path}/.easy_home_directory_backup",
justify="center")
console.print()
sys.exit()
I made other changes to the additional nine files in the project. Much of it was changing the text in the comments to make the language more uniform. Or I added missing type annotations. Oh, and I added a new file (src/log_file_directory.py) to create the hidden directory containing the application’s log file.
To review these changes and more, please check out the project’s GitHub repo. That’s where one can download the application too.