Skip to content
Merged
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
16 changes: 16 additions & 0 deletions mssql_python/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,22 @@ def autocommit(self, value: bool) -> None:
self.setautocommit(value)
logger.info("Autocommit mode set to %s.", value)

@property
def closed(self) -> bool:
"""
Returns True if the connection is closed, False otherwise.

This property indicates whether close() was explicitly called on
the connection. Note that this does not indicate whether the
connection is healthy/alive - if a timeout or network issue breaks
the connection, closed would still be False until close() is
explicitly called.

Returns:
bool: True if the connection is closed, False otherwise.
"""
return self._closed

def setautocommit(self, value: bool = False) -> None:
"""
Set the autocommit mode of the connection.
Expand Down
65 changes: 65 additions & 0 deletions tests/test_003_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,71 @@ def test_connection_close(conn_str):
temp_conn.close()


def test_connection_closed_property_reflects_state(conn_str):
"""
Test that the closed property correctly reflects the connection state.

This test verifies that:
1. A new connection has closed=False
2. After calling close(), closed=True
"""
temp_conn = connect(conn_str)
# New connection should not be closed
assert temp_conn.closed is False, "New connection should have closed=False"

# Close the connection
temp_conn.close()

# After close(), closed should be True
assert temp_conn.closed is True, "After close(), connection should have closed=True"


def test_connection_closed_property_after_multiple_close_calls(conn_str):
"""
Test that calling close() multiple times is safe and closed remains True.

This test verifies idempotent behavior of close() and the closed property.
"""
temp_conn = connect(conn_str)
assert temp_conn.closed is False

# First close
temp_conn.close()
assert temp_conn.closed is True

# Second close should not raise and closed should still be True
temp_conn.close() # Should not raise
assert temp_conn.closed is True


def test_connection_closed_property_with_context_manager(conn_str):
"""
Test that closed property is True after exiting context manager.
"""
with connect(conn_str) as temp_conn:
assert temp_conn.closed is False, "Connection should be open inside context manager"

# After exiting context manager, connection should be closed
assert temp_conn.closed is True, "Connection should be closed after exiting context manager"


def test_connection_closed_property_operations_after_close(conn_str):
"""
Test that operations on a closed connection raise appropriate exceptions.

This test verifies that attempting to use a closed connection raises
an InterfaceError, and the closed property correctly reflects the state.
"""
temp_conn = connect(conn_str)
temp_conn.close()

assert temp_conn.closed is True

# Attempting to create a cursor on a closed connection should raise InterfaceError
with pytest.raises(InterfaceError):
temp_conn.cursor()


def test_connection_timeout_invalid_password(conn_str):
"""Test that connecting with an invalid password raises an exception quickly (timeout)."""
# Modify the connection string to use an invalid password
Expand Down
Loading