diff --git a/CHANGELOG.md b/CHANGELOG.md index b6de0b896..f02fc29e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,6 +91,8 @@ See also https://github.com/neo4j/neo4j-python-driver/wiki for a full changelog. - Change behavior of closed drivers: - Raise `DriverError` on using the closed driver. - Calling `driver.close()` again is now a no-op. +- No longer implicitly closing drivers and sessions in `__del__()` (finalizer/destructor). + Make sure to call `.close()` on them explicitly or use them in a `with` statement. ## Version 5.28 diff --git a/src/neo4j/_async/driver.py b/src/neo4j/_async/driver.py index 1d515d68b..1ea1c84fa 100644 --- a/src/neo4j/_async/driver.py +++ b/src/neo4j/_async/driver.py @@ -39,7 +39,6 @@ SECURITY_TYPE_SELF_SIGNED_CERTIFICATE, TelemetryAPI, ) -from .._async_compat.util import AsyncUtil from .._conf import ( Config, ConfigurationError, @@ -509,23 +508,9 @@ async def __aexit__(self, exc_type, exc_value, traceback): def __del__( self, _unclosed_resource_warn=unclosed_resource_warn, - _is_async_code=AsyncUtil.is_async_code, - _deprecation_warn=deprecation_warn, ): if not self._closed: _unclosed_resource_warn(self) - # TODO: 6.0 - remove this - if _is_async_code: - return - if not self._closed: - _deprecation_warn( - "Relying on AsyncDriver's destructor to close the session " - "is deprecated. Please make sure to close the session. " - "Use it as a context (`with` statement) or make sure to " - "call `.close()` explicitly. Future versions of the " - "driver will not close drivers automatically." - ) - self.close() def _check_state(self): if self._closed: diff --git a/src/neo4j/_async/work/workspace.py b/src/neo4j/_async/work/workspace.py index e015acb4e..ab740f4ee 100644 --- a/src/neo4j/_async/work/workspace.py +++ b/src/neo4j/_async/work/workspace.py @@ -22,15 +22,11 @@ from ..._async_compat.util import AsyncUtil from ..._auth_management import to_auth_dict from ..._conf import WorkspaceConfig -from ..._warnings import ( - deprecation_warn, - unclosed_resource_warn, -) +from ..._warnings import unclosed_resource_warn from ...api import Bookmarks from ...exceptions import ( ServiceUnavailable, SessionError, - SessionExpired, ) from .._debug import AsyncNonConcurrentMethodChecker from ..io import ( @@ -74,29 +70,15 @@ def __init__(self, pool, config): self._closed = False super().__init__() + # Copy globals as function locals to make sure that they are available + # during Python shutdown when the Session is destroyed. def __del__( self, _unclosed_resource_warn=unclosed_resource_warn, - _is_async_code=AsyncUtil.is_async_code, - _deprecation_warn=deprecation_warn, ): if self._closed: return _unclosed_resource_warn(self) - # TODO: 6.0 - remove this - if _is_async_code: - return - try: - _deprecation_warn( - "Relying on AsyncSession's destructor to close the session " - "is deprecated. Please make sure to close the session. Use it " - "as a context (`with` statement) or make sure to call " - "`.close()` explicitly. Future versions of the driver will " - "not close sessions automatically." - ) - self.close() - except (OSError, ServiceUnavailable, SessionExpired): - pass async def __aenter__(self) -> AsyncWorkspace: return self diff --git a/src/neo4j/_sync/driver.py b/src/neo4j/_sync/driver.py index 810f6948e..fa8074258 100644 --- a/src/neo4j/_sync/driver.py +++ b/src/neo4j/_sync/driver.py @@ -39,7 +39,6 @@ SECURITY_TYPE_SELF_SIGNED_CERTIFICATE, TelemetryAPI, ) -from .._async_compat.util import Util from .._conf import ( Config, ConfigurationError, @@ -508,23 +507,9 @@ def __exit__(self, exc_type, exc_value, traceback): def __del__( self, _unclosed_resource_warn=unclosed_resource_warn, - _is_async_code=Util.is_async_code, - _deprecation_warn=deprecation_warn, ): if not self._closed: _unclosed_resource_warn(self) - # TODO: 6.0 - remove this - if _is_async_code: - return - if not self._closed: - _deprecation_warn( - "Relying on Driver's destructor to close the session " - "is deprecated. Please make sure to close the session. " - "Use it as a context (`with` statement) or make sure to " - "call `.close()` explicitly. Future versions of the " - "driver will not close drivers automatically." - ) - self.close() def _check_state(self): if self._closed: diff --git a/src/neo4j/_sync/work/workspace.py b/src/neo4j/_sync/work/workspace.py index 0d5607a81..bca6a0a8b 100644 --- a/src/neo4j/_sync/work/workspace.py +++ b/src/neo4j/_sync/work/workspace.py @@ -22,15 +22,11 @@ from ..._async_compat.util import Util from ..._auth_management import to_auth_dict from ..._conf import WorkspaceConfig -from ..._warnings import ( - deprecation_warn, - unclosed_resource_warn, -) +from ..._warnings import unclosed_resource_warn from ...api import Bookmarks from ...exceptions import ( ServiceUnavailable, SessionError, - SessionExpired, ) from .._debug import NonConcurrentMethodChecker from ..io import ( @@ -71,29 +67,15 @@ def __init__(self, pool, config): self._closed = False super().__init__() + # Copy globals as function locals to make sure that they are available + # during Python shutdown when the Session is destroyed. def __del__( self, _unclosed_resource_warn=unclosed_resource_warn, - _is_async_code=Util.is_async_code, - _deprecation_warn=deprecation_warn, ): if self._closed: return _unclosed_resource_warn(self) - # TODO: 6.0 - remove this - if _is_async_code: - return - try: - _deprecation_warn( - "Relying on Session's destructor to close the session " - "is deprecated. Please make sure to close the session. Use it " - "as a context (`with` statement) or make sure to call " - "`.close()` explicitly. Future versions of the driver will " - "not close sessions automatically." - ) - self.close() - except (OSError, ServiceUnavailable, SessionExpired): - pass def __enter__(self) -> Workspace: return self