Put a Python Boundary Around the Database · practice
Translate Only a Known Catalog Conflict
The same duplicate loan ID currently reaches a database-specific failure:
checkout_item(connection, 501, 4, 17, '2026-08-26') -> IntegrityError: UNIQUE constraint failed: loans.id
That detail is useful inside the database
ValueError: The checkout conflicts with a catalog rule.
Open catalog_db.py. Wrap the existing connection context in try, then catch exactly sqlite3.IntegrityError after the context has exited:
try:
with connection:
# Keep both checks and the insert here.
...
except sqlite3.IntegrityError:
raise ValueError("The checkout conflicts with a catalog rule.")
return loan_id
Placement matters. When an integrity failure leaves with connection:, the connection context rolls back the
Width matters too. Do not catch Exception or even every sqlite3.Error. An unavailable table is an OperationalError; using a closed connection is a ProgrammingError. Those are defects or operating problems, not evidence that a checkout violated a catalog constraint. They must keep their original
The two earlier IntegrityError:
That item is already checked out.
That member has reached the loan limit.
Press Run. It repeats the exact success and duplicate-ID calls you just saw. The successful return and durable row stay the same. Only the conflict line changes to the documented ValueError, and a fresh connection still finds no loan for item 4. The supplied connection remains usable.
Submit also causes a missing
Task
Update checkout_item so one outer handler catches exactly sqlite3.IntegrityError after it leaves with connection: and raises ValueError("The checkout conflicts with a catalog rule.").
Keep both rule-specific loan_id after a successful commit, and leave the supplied connection open.