From 7171b268b77715d086da742a997d22dfbd1e351e Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Wed, 14 May 2025 16:07:39 +0200 Subject: [PATCH] Remove internal constants --- CHANGELOG.md | 14 +++++ src/neo4j/_api.py | 15 ++++++ src/neo4j/_async/driver.py | 8 +-- src/neo4j/_sync/driver.py | 8 +-- src/neo4j/api.py | 54 +++++++------------ src/neo4j/exceptions.py | 78 +++++++--------------------- tests/unit/common/test_api.py | 29 ++++++----- tests/unit/common/test_exceptions.py | 22 ++++---- 8 files changed, 100 insertions(+), 128 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9bacec83..d8ce7bcb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,20 @@ See also https://github.com/neo4j/neo4j-python-driver/wiki for a full changelog. - `connection_acquisition_timeout` configuration option - `ValueError` on invalid values (instead of `ClientError`) - Consistently restrict the value to be strictly positive +- Make undocumented internal constants private: + - `neo4j.api` + - `DRIVER_BOLT` + - `DRIVER_NEO4J` + - `SECURITY_TYPE_NOT_SECURE` + - `SECURITY_TYPE_SECURE` + - `SECURITY_TYPE_SELF_SIGNED_CERTIFICATE` + - `neo4j.exceptions` + - `CLASSIFICATION_CLIENT` + - `CLASSIFICATION_DATABASE` + - `CLASSIFICATION_TRANSIENT` + - `ERROR_REWRITE_MAP` + - `client_errors` + - `transient_errors` ## Version 5.28 diff --git a/src/neo4j/_api.py b/src/neo4j/_api.py index c87e7424e..81da85123 100644 --- a/src/neo4j/_api.py +++ b/src/neo4j/_api.py @@ -25,6 +25,11 @@ __all__ = [ + "DRIVER_BOLT", + "DRIVER_NEO4J", + "SECURITY_TYPE_NOT_SECURE", + "SECURITY_TYPE_SECURE", + "SECURITY_TYPE_SELF_SIGNED_CERTIFICATE", "NotificationCategory", "NotificationClassification", "NotificationDisabledCategory", @@ -36,6 +41,16 @@ ] +DRIVER_BOLT: te.Final[str] = "DRIVER_BOLT" +DRIVER_NEO4J: te.Final[str] = "DRIVER_NEO4J" + +SECURITY_TYPE_NOT_SECURE: te.Final[str] = "SECURITY_TYPE_NOT_SECURE" +SECURITY_TYPE_SELF_SIGNED_CERTIFICATE: te.Final[str] = ( + "SECURITY_TYPE_SELF_SIGNED_CERTIFICATE" +) +SECURITY_TYPE_SECURE: te.Final[str] = "SECURITY_TYPE_SECURE" + + class NotificationMinimumSeverity(str, Enum): """ Filter notifications returned by the server by minimum severity. diff --git a/src/neo4j/_async/driver.py b/src/neo4j/_async/driver.py index a202fc590..c6f19316e 100644 --- a/src/neo4j/_async/driver.py +++ b/src/neo4j/_async/driver.py @@ -30,8 +30,12 @@ ) from .._api import ( + DRIVER_BOLT, + DRIVER_NEO4J, NotificationMinimumSeverity, RoutingControl, + SECURITY_TYPE_SECURE, + SECURITY_TYPE_SELF_SIGNED_CERTIFICATE, TelemetryAPI, ) from .._async_compat.util import AsyncUtil @@ -61,13 +65,9 @@ Auth, BookmarkManager, Bookmarks, - DRIVER_BOLT, - DRIVER_NEO4J, parse_neo4j_uri, parse_routing_context, READ_ACCESS, - SECURITY_TYPE_SECURE, - SECURITY_TYPE_SELF_SIGNED_CERTIFICATE, ServerInfo, TRUST_ALL_CERTIFICATES, TRUST_SYSTEM_CA_SIGNED_CERTIFICATES, diff --git a/src/neo4j/_sync/driver.py b/src/neo4j/_sync/driver.py index 24a61b5c8..99e1442e2 100644 --- a/src/neo4j/_sync/driver.py +++ b/src/neo4j/_sync/driver.py @@ -30,8 +30,12 @@ ) from .._api import ( + DRIVER_BOLT, + DRIVER_NEO4J, NotificationMinimumSeverity, RoutingControl, + SECURITY_TYPE_SECURE, + SECURITY_TYPE_SELF_SIGNED_CERTIFICATE, TelemetryAPI, ) from .._async_compat.util import Util @@ -60,13 +64,9 @@ Auth, BookmarkManager, Bookmarks, - DRIVER_BOLT, - DRIVER_NEO4J, parse_neo4j_uri, parse_routing_context, READ_ACCESS, - SECURITY_TYPE_SECURE, - SECURITY_TYPE_SELF_SIGNED_CERTIFICATE, ServerInfo, TRUST_ALL_CERTIFICATES, TRUST_SYSTEM_CA_SIGNED_CERTIFICATES, diff --git a/src/neo4j/api.py b/src/neo4j/api.py index b652a5b6b..1f98363e9 100644 --- a/src/neo4j/api.py +++ b/src/neo4j/api.py @@ -25,32 +25,27 @@ urlparse, ) - -if t.TYPE_CHECKING: - from typing_extensions import deprecated -else: - from ._meta import deprecated - +from . import _api from .exceptions import ConfigurationError if t.TYPE_CHECKING: import typing_extensions as te - from typing_extensions import Protocol as _Protocol + from typing_extensions import ( + deprecated, + Protocol as _Protocol, + ) from .addressing import Address else: + from ._meta import deprecated + _Protocol = object __all__ = [ "DEFAULT_DATABASE", - "DRIVER_BOLT", - "DRIVER_NEO4J", "READ_ACCESS", - "SECURITY_TYPE_NOT_SECURE", - "SECURITY_TYPE_SECURE", - "SECURITY_TYPE_SELF_SIGNED_CERTIFICATE", "SYSTEM_DATABASE", "TRUST_ALL_CERTIFICATES", "TRUST_SYSTEM_CA_SIGNED_CERTIFICATES", @@ -82,17 +77,6 @@ READ_ACCESS: te.Final[str] = "READ" WRITE_ACCESS: te.Final[str] = "WRITE" -# TODO: 6.0 - make these 2 constants private -DRIVER_BOLT: te.Final[str] = "DRIVER_BOLT" -DRIVER_NEO4J: te.Final[str] = "DRIVER_NEO4J" - -# TODO: 6.0 - make these 3 constants private -SECURITY_TYPE_NOT_SECURE: te.Final[str] = "SECURITY_TYPE_NOT_SECURE" -SECURITY_TYPE_SELF_SIGNED_CERTIFICATE: te.Final[str] = ( - "SECURITY_TYPE_SELF_SIGNED_CERTIFICATE" -) -SECURITY_TYPE_SECURE: te.Final[str] = "SECURITY_TYPE_SECURE" - URI_SCHEME_BOLT: te.Final[str] = "bolt" URI_SCHEME_BOLT_SELF_SIGNED_CERTIFICATE: te.Final[str] = "bolt+ssc" URI_SCHEME_BOLT_SECURE: te.Final[str] = "bolt+s" @@ -523,23 +507,23 @@ def parse_neo4j_uri(uri): f"Use {URI_SCHEME_NEO4J!r}" ) elif parsed.scheme == URI_SCHEME_BOLT: - driver_type = DRIVER_BOLT - security_type = SECURITY_TYPE_NOT_SECURE + driver_type = _api.DRIVER_BOLT + security_type = _api.SECURITY_TYPE_NOT_SECURE elif parsed.scheme == URI_SCHEME_BOLT_SELF_SIGNED_CERTIFICATE: - driver_type = DRIVER_BOLT - security_type = SECURITY_TYPE_SELF_SIGNED_CERTIFICATE + driver_type = _api.DRIVER_BOLT + security_type = _api.SECURITY_TYPE_SELF_SIGNED_CERTIFICATE elif parsed.scheme == URI_SCHEME_BOLT_SECURE: - driver_type = DRIVER_BOLT - security_type = SECURITY_TYPE_SECURE + driver_type = _api.DRIVER_BOLT + security_type = _api.SECURITY_TYPE_SECURE elif parsed.scheme == URI_SCHEME_NEO4J: - driver_type = DRIVER_NEO4J - security_type = SECURITY_TYPE_NOT_SECURE + driver_type = _api.DRIVER_NEO4J + security_type = _api.SECURITY_TYPE_NOT_SECURE elif parsed.scheme == URI_SCHEME_NEO4J_SELF_SIGNED_CERTIFICATE: - driver_type = DRIVER_NEO4J - security_type = SECURITY_TYPE_SELF_SIGNED_CERTIFICATE + driver_type = _api.DRIVER_NEO4J + security_type = _api.SECURITY_TYPE_SELF_SIGNED_CERTIFICATE elif parsed.scheme == URI_SCHEME_NEO4J_SECURE: - driver_type = DRIVER_NEO4J - security_type = SECURITY_TYPE_SECURE + driver_type = _api.DRIVER_NEO4J + security_type = _api.SECURITY_TYPE_SECURE else: supported_schemes = [ URI_SCHEME_BOLT, diff --git a/src/neo4j/exceptions.py b/src/neo4j/exceptions.py index e74275748..d26aa2475 100644 --- a/src/neo4j/exceptions.py +++ b/src/neo4j/exceptions.py @@ -70,44 +70,6 @@ ) -__all__ = [ - "AuthConfigurationError", - "AuthError", - "BrokenRecordError", - "CertificateConfigurationError", - "ClientError", - "ConfigurationError", - "ConstraintError", - "CypherSyntaxError", - "CypherTypeError", - "DatabaseError", - "DatabaseUnavailable", - "DriverError", - "Forbidden", - "ForbiddenOnReadOnlyDatabase", - "GqlError", - "GqlErrorClassification", - "IncompleteCommit", - "Neo4jError", - "NotALeader", - "ReadServiceUnavailable", - "ResultConsumedError", - "ResultError", - "ResultFailedError", - "ResultNotSingleError", - "RoutingServiceUnavailable", - "ServiceUnavailable", - "SessionError", - "SessionExpired", - "TokenExpired", - "TransactionError", - "TransactionNestingError", - "TransientError", - "UnsupportedServerProduct", - "WriteServiceUnavailable", -] - - if t.TYPE_CHECKING: from collections.abc import Mapping @@ -138,10 +100,6 @@ __all__ = [ - "CLASSIFICATION_CLIENT", # TODO: 6.0 - make constant private - "CLASSIFICATION_DATABASE", # TODO: 6.0 - make constant private - "CLASSIFICATION_TRANSIENT", # TODO: 6.0 - make constant private - "ERROR_REWRITE_MAP", # TODO: 6.0 - make constant private "AuthConfigurationError", "AuthError", "BrokenRecordError", @@ -156,6 +114,8 @@ "DriverError", "Forbidden", "ForbiddenOnReadOnlyDatabase", + "GqlError", + "GqlErrorClassification", "IncompleteCommit", "Neo4jError", "NotALeader", @@ -177,30 +137,30 @@ ] -CLASSIFICATION_CLIENT: te.Final[str] = "ClientError" -CLASSIFICATION_TRANSIENT: te.Final[str] = "TransientError" -CLASSIFICATION_DATABASE: te.Final[str] = "DatabaseError" +_CLASSIFICATION_CLIENT: te.Final[str] = "ClientError" +_CLASSIFICATION_TRANSIENT: te.Final[str] = "TransientError" +_CLASSIFICATION_DATABASE: te.Final[str] = "DatabaseError" -ERROR_REWRITE_MAP: dict[str, tuple[str, str | None]] = { +_ERROR_REWRITE_MAP: dict[str, tuple[str, str | None]] = { # This error can be retried ed. The driver just needs to re-authenticate # with the same credentials. "Neo.ClientError.Security.AuthorizationExpired": ( - CLASSIFICATION_TRANSIENT, + _CLASSIFICATION_TRANSIENT, None, ), # In 5.0, this error has been re-classified as ClientError. # For backwards compatibility with Neo4j 4.4 and earlier, we re-map it in # the driver, too. "Neo.TransientError.Transaction.Terminated": ( - CLASSIFICATION_CLIENT, + _CLASSIFICATION_CLIENT, "Neo.ClientError.Transaction.Terminated", ), # In 5.0, this error has been re-classified as ClientError. # For backwards compatibility with Neo4j 4.4 and earlier, we re-map it in # the driver, too. "Neo.TransientError.Transaction.LockClientStopped": ( - CLASSIFICATION_CLIENT, + _CLASSIFICATION_CLIENT, "Neo.ClientError.Transaction.LockClientStopped", ), } @@ -631,11 +591,11 @@ def _basic_hydrate(cls, *, neo4j_code: str, message: str) -> Neo4jError: try: _, classification, category, title = neo4j_code.split(".") except ValueError: - classification = CLASSIFICATION_DATABASE + classification = _CLASSIFICATION_DATABASE category = "General" title = "UnknownError" else: - classification_override, code_override = ERROR_REWRITE_MAP.get( + classification_override, code_override = _ERROR_REWRITE_MAP.get( neo4j_code, (None, None) ) if classification_override is not None: @@ -658,19 +618,19 @@ def _basic_hydrate(cls, *, neo4j_code: str, message: str) -> Neo4jError: @classmethod def _extract_error_class(cls, classification, code) -> type[Neo4jError]: - if classification == CLASSIFICATION_CLIENT: + if classification == _CLASSIFICATION_CLIENT: try: - return client_errors[code] + return _client_errors[code] except KeyError: return ClientError - elif classification == CLASSIFICATION_TRANSIENT: + elif classification == _CLASSIFICATION_TRANSIENT: try: - return transient_errors[code] + return _transient_errors[code] except KeyError: return TransientError - elif classification == CLASSIFICATION_DATABASE: + elif classification == _CLASSIFICATION_DATABASE: return DatabaseError else: @@ -951,8 +911,7 @@ class ForbiddenOnReadOnlyDatabase(TransientError): pass -# TODO: 6.0 - Make map private -client_errors: dict[str, type[Neo4jError]] = { +_client_errors: dict[str, type[Neo4jError]] = { # ConstraintError "Neo.ClientError.Schema.ConstraintValidationFailed": ConstraintError, "Neo.ClientError.Schema.ConstraintViolation": ConstraintError, @@ -981,8 +940,7 @@ class ForbiddenOnReadOnlyDatabase(TransientError): "Neo.ClientError.Cluster.NotALeader": NotALeader, } -# TODO: 6.0 - Make map private -transient_errors: dict[str, type[Neo4jError]] = { +_transient_errors: dict[str, type[Neo4jError]] = { # DatabaseUnavailableError "Neo.TransientError.General.DatabaseUnavailable": DatabaseUnavailable } diff --git a/tests/unit/common/test_api.py b/tests/unit/common/test_api.py index 4ec0a20ed..693dba669 100644 --- a/tests/unit/common/test_api.py +++ b/tests/unit/common/test_api.py @@ -20,6 +20,7 @@ import pytest +import neo4j._api import neo4j.api from neo4j.addressing import Address from neo4j.exceptions import ConfigurationError @@ -319,38 +320,38 @@ def test_serverinfo_with_metadata( [ ( "bolt://localhost:7676", - neo4j.api.DRIVER_BOLT, - neo4j.api.SECURITY_TYPE_NOT_SECURE, + neo4j._api.DRIVER_BOLT, + neo4j._api.SECURITY_TYPE_NOT_SECURE, None, ), ( "bolt+ssc://localhost:7676", - neo4j.api.DRIVER_BOLT, - neo4j.api.SECURITY_TYPE_SELF_SIGNED_CERTIFICATE, + neo4j._api.DRIVER_BOLT, + neo4j._api.SECURITY_TYPE_SELF_SIGNED_CERTIFICATE, None, ), ( "bolt+s://localhost:7676", - neo4j.api.DRIVER_BOLT, - neo4j.api.SECURITY_TYPE_SECURE, + neo4j._api.DRIVER_BOLT, + neo4j._api.SECURITY_TYPE_SECURE, None, ), ( "neo4j://localhost:7676", - neo4j.api.DRIVER_NEO4J, - neo4j.api.SECURITY_TYPE_NOT_SECURE, + neo4j._api.DRIVER_NEO4J, + neo4j._api.SECURITY_TYPE_NOT_SECURE, None, ), ( "neo4j+ssc://localhost:7676", - neo4j.api.DRIVER_NEO4J, - neo4j.api.SECURITY_TYPE_SELF_SIGNED_CERTIFICATE, + neo4j._api.DRIVER_NEO4J, + neo4j._api.SECURITY_TYPE_SELF_SIGNED_CERTIFICATE, None, ), ( "neo4j+s://localhost:7676", - neo4j.api.DRIVER_NEO4J, - neo4j.api.SECURITY_TYPE_SECURE, + neo4j._api.DRIVER_NEO4J, + neo4j._api.SECURITY_TYPE_SECURE, None, ), ("undefined://localhost:7676", None, None, ConfigurationError), @@ -358,8 +359,8 @@ def test_serverinfo_with_metadata( ("://localhost:7676", None, None, ConfigurationError), ( "bolt+routing://localhost:7676", - neo4j.api.DRIVER_NEO4J, - neo4j.api.SECURITY_TYPE_NOT_SECURE, + neo4j._api.DRIVER_NEO4J, + neo4j._api.SECURITY_TYPE_NOT_SECURE, ConfigurationError, ), ("bolt://username@localhost:7676", None, None, ConfigurationError), diff --git a/tests/unit/common/test_exceptions.py b/tests/unit/common/test_exceptions.py index fc880bbb5..3e215e924 100644 --- a/tests/unit/common/test_exceptions.py +++ b/tests/unit/common/test_exceptions.py @@ -31,9 +31,9 @@ ) from neo4j._sync.io import Bolt from neo4j.exceptions import ( - CLASSIFICATION_CLIENT, - CLASSIFICATION_DATABASE, - CLASSIFICATION_TRANSIENT, + _CLASSIFICATION_CLIENT, + _CLASSIFICATION_DATABASE, + _CLASSIFICATION_TRANSIENT, ClientError, DatabaseError, GqlError, @@ -191,7 +191,7 @@ def test_neo4jerror_hydrate_with_no_args(): error = Neo4jError._hydrate_neo4j() assert isinstance(error, DatabaseError) - assert error.classification == CLASSIFICATION_DATABASE + assert error.classification == _CLASSIFICATION_DATABASE assert error.category == "General" assert error.title == "UnknownError" assert error.metadata == {} @@ -206,7 +206,7 @@ def test_neo4jerror_hydrate_with_message_and_code_rubbish(): ) assert isinstance(error, DatabaseError) - assert error.classification == CLASSIFICATION_DATABASE + assert error.classification == _CLASSIFICATION_DATABASE assert error.category == "General" assert error.title == "UnknownError" assert error.metadata == {} @@ -222,7 +222,7 @@ def test_neo4jerror_hydrate_with_message_and_code_database(): ) assert isinstance(error, DatabaseError) - assert error.classification == CLASSIFICATION_DATABASE + assert error.classification == _CLASSIFICATION_DATABASE assert error.category == "General" assert error.title == "UnknownError" assert error.metadata == {} @@ -238,28 +238,28 @@ def test_neo4jerror_hydrate_with_message_and_code_transient(): ) assert isinstance(error, TransientError) - assert error.classification == CLASSIFICATION_TRANSIENT + assert error.classification == _CLASSIFICATION_TRANSIENT assert error.category == "General" assert error.title == "TestError" assert error.metadata == {} assert error.message == "Test error message" - assert error.code == f"Neo.{CLASSIFICATION_TRANSIENT}.General.TestError" + assert error.code == f"Neo.{_CLASSIFICATION_TRANSIENT}.General.TestError" _assert_default_gql_error_attrs_from_neo4j_error(error) def test_neo4jerror_hydrate_with_message_and_code_client(): error = Neo4jError._hydrate_neo4j( message="Test error message", - code=f"Neo.{CLASSIFICATION_CLIENT}.General.TestError", + code=f"Neo.{_CLASSIFICATION_CLIENT}.General.TestError", ) assert isinstance(error, ClientError) - assert error.classification == CLASSIFICATION_CLIENT + assert error.classification == _CLASSIFICATION_CLIENT assert error.category == "General" assert error.title == "TestError" assert error.metadata == {} assert error.message == "Test error message" - assert error.code == f"Neo.{CLASSIFICATION_CLIENT}.General.TestError" + assert error.code == f"Neo.{_CLASSIFICATION_CLIENT}.General.TestError" _assert_default_gql_error_attrs_from_neo4j_error(error)