Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions mssql_python/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1698,16 +1698,43 @@ def __enter__(self) -> "Connection":
logger.info("Entering connection context manager.")
return self

def __exit__(self, *args: Any) -> None:
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why *argsexc_type, exc_val, exc_tb:

the old __exit__ didn't inspect its arguments at all (just called close()), so *args was fine. now we branch on exc_type to decide commit vs rollback, so we use the canonical __exit__(self, exc_type, exc_val, exc_tb) signature from the Python data model.

this is what sqlite3, psycopg2, and every other DB-API driver uses. no behavioral change from the rename itself - just makes the branching logic readable.

"""
Exit the context manager.

Closes the connection when exiting the context, ensuring proper
resource cleanup. This follows the modern standard used by most
database libraries.
Implements commit-on-success / rollback-on-exception semantics:
- If the block exits cleanly and autocommit is off, the transaction
is committed.
- If an exception is raised and autocommit is off, the transaction
is rolled back.
- The connection is always closed when leaving the block.

If commit() fails on clean exit, the connection is closed and the
commit exception is raised. On exception exit, cleanup failures
(rollback or close) are suppressed so the original user exception
propagates unchanged.
"""
if not self._closed:
if self._closed:
return
try:
if not self.autocommit:
if exc_type is None:
self.commit()
else:
self.rollback()
except Exception:
try:
self.close()
except Exception:
pass
if exc_type is None:
raise
return
try:
self.close()
except Exception:
if exc_type is None:
raise

def __del__(self) -> None:
"""
Expand Down
Loading
Loading