Safe Paws Project — Round 4/5
Lassie is doing better. Time to find her a new home — and build the procedure for it.
Two things need to happen when an animal is adopted. Its status in our shelter file changes from "available" to "adopted". And a record of the adoption gets written to a second file — who adopted it, when, and how to reach them if the animal is ever lost.
The function is similar to edit_health() — but simpler. We don't ask for a new status. We already know it.
def paw_adopted():
available_paws = {}
adopted_paws = {}
for key in paws_dict:
if paws_dict[key][5] == "available":
available_paws[key] = paws_dict[key]
else:
adopted_paws[key] = paws_dict[key]
while True:
try:
id = int(input("Adopted paw id: "))
if id in available_paws.keys():
owner_name = ""
while not owner_name:
owner_name = input("New owner name: ")
owner_contact = ""
while not owner_contact:
owner_contact = input("New owner contact: ")
adoption_date = datetime.date.today().strftime("%Y-%m-%d")
with open("adopted_paws.txt", "a", encoding="utf-8") as f:
f.write(f"{id};{owner_name};{owner_contact};{adoption_date}\n")
paws_dict[id][5] = "adopted"
print(f"Great! {paws_dict[id][0].upper()} has a new home.")
with open("safe_paws.txt", "w", encoding="utf-8") as f:
for key in paws_dict:
f.write(f"{key};{paws_dict[key][0]};{paws_dict[key][1]};{paws_dict[key][2]};{paws_dict[key][3]};{paws_dict[key][4]};{paws_dict[key][5]}\n")
print("safe_paws.txt was updated!")
load_from_txt()
break
elif id in adopted_paws.keys():
print(f"{paws_dict[id][0].upper()} was already adopted.")
break
except ValueError:
print("Invalid ID. Enter a number.")
The structure will look familiar. Two dictionaries for filtering — available and adopted. The loop asks for an ID and routes accordingly.
If the animal is available: we collect the owner's name, contact, and today's date — automated with datetime.date.today(). We write the adoption record to adopted_paws.txt with "a" — append, never overwrite, every adoption stays on record. Then we update the status in paws_dict and rewrite safe_paws.txt with "w". Both files stay in sync.
The two with open() blocks use the same variable name f — and that's fine. They're separate blocks for separate files, executed one after the other. Python closes the first file when the first block ends, then opens the second. f is just a local alias — it can be reused freely.
If the animal is already adopted: a personalized message, nothing written.
One more thing worth noting. We update paws_dict[id][5] — the main dictionary — not available_paws. That's intentional. available_paws was only used for filtering. When we rewrite the file, we need every animal — adopted and available — and paws_dict has them all.
A side note for those curious: try replacing "adopted" with other statuses — "recovered", "escaped", "deceased". You'll quickly see whether a single flexible function with a status input makes more sense than a dedicated function for each case. Both approaches are valid. The choice depends on how the shelter actually operates.
Into the menu:
while True:
print("\nSafe Paws Menu")
option = input("1-Add paw\n2-Adv search\n3-Edit paw health\n4-Register adoption\nq-Quit\nChoose your option: ")
if option == "1":
add_paw()
print("Paw added successfully!")
elif option == "2":
if len(adv_search()) > 0:
print_adv_search()
else:
print("No data match your search.")
elif option == "3":
edit_health()
elif option == "4":
paw_adopted()
elif option == "q":
break
else:
print("Invalid option!")
Here's what the interaction looks like in practice.
Registering an adoption:
Adopted paw id: 1
New owner name: Jon Snow
New owner contact: 0123456789
Great! LASSIE has a new home.
safe_paws.txt was updated!
Trying to adopt an animal that's already gone:
Adopted paw id: 1
LASSIE was already adopted.
adopted_paws.txt after the first adoption:
1;Jon Snow;0123456789;2025-04-07
safe_paws.txt — Lassie's entry, updated:
1;Lassie;dog;medium;healthy;4;adopted
Two files now. Next — a report that pulls from both and presents something worth sharing.
Congratulations, Lassie. You got a second chance.