0%

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 . A caller needs the smaller promise that the checkout conflicts with a catalog rule. Translate only this known boundary:

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 . Only then does the outer handler replace the low-level error. Catching inside the context would make the block appear to finish normally, which can commit work that should have been rolled back.

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 messages also pass through unchanged because this handler catches only 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 , both application refusals, an unavailable table, a closed connection, and unrelated Python failures. Translate the two integrity conflicts; let everything else tell the truth.

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 messages unchanged. Let all unrelated exception propagate, return loan_id after a successful commit, and leave the supplied connection open.