From bc1b9b4f19a8fca13a57524738f5168edb48517e Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Tue, 8 Nov 2022 13:17:40 +0100 Subject: [PATCH] Make code compatible with mypy 0.990 * remove implicit optional parameters (PEP 484 received an update) * mute metaclass inference limitations of mypy * fix mypy rightfully complaining about empty method bodies * fixed bug in (deprecated) `session.last_bookmark` that mypy uncovered --- neo4j/_async/bookmark_manager.py | 8 ++++---- neo4j/_async/driver.py | 10 ++++++---- neo4j/_async/work/result.py | 4 +++- neo4j/_async/work/session.py | 10 ++++++---- neo4j/_async/work/transaction.py | 2 +- neo4j/_data.py | 6 ++++-- neo4j/_spatial/__init__.py | 16 +++++++--------- neo4j/_sync/bookmark_manager.py | 8 ++++---- neo4j/_sync/driver.py | 8 ++++---- neo4j/_sync/work/result.py | 4 +++- neo4j/_sync/work/session.py | 10 ++++++---- neo4j/_sync/work/transaction.py | 2 +- neo4j/addressing.py | 13 +++++-------- neo4j/api.py | 8 ++++++-- neo4j/debug.py | 4 +++- neo4j/exceptions.py | 7 ++++++- neo4j/graph/__init__.py | 6 +++--- neo4j/time/__init__.py | 28 +++++++++++++++++----------- neo4j/work/query.py | 7 ++++--- tests/unit/async_/test_driver.py | 16 ++++++++-------- tests/unit/sync/test_driver.py | 16 ++++++++-------- 21 files changed, 109 insertions(+), 84 deletions(-) diff --git a/neo4j/_async/bookmark_manager.py b/neo4j/_async/bookmark_manager.py index 41c098cc7..8fc5d0930 100644 --- a/neo4j/_async/bookmark_manager.py +++ b/neo4j/_async/bookmark_manager.py @@ -45,10 +45,10 @@ def _bookmarks_to_set( class AsyncNeo4jBookmarkManager(AsyncBookmarkManager): def __init__( self, - initial_bookmarks: t.Mapping[str, t.Union[Bookmarks, - t.Iterable[str]]] = None, - bookmarks_supplier: T_BmSupplier = None, - bookmarks_consumer: T_BmConsumer = None + initial_bookmarks: t.Optional[t.Mapping[str, t.Union[Bookmarks, + t.Iterable[str]]]] = None, + bookmarks_supplier: t.Optional[T_BmSupplier] = None, + bookmarks_consumer: t.Optional[T_BmConsumer] = None ) -> None: super().__init__() self._bookmarks_supplier = bookmarks_supplier diff --git a/neo4j/_async/driver.py b/neo4j/_async/driver.py index a8d4514c7..d838c956d 100644 --- a/neo4j/_async/driver.py +++ b/neo4j/_async/driver.py @@ -26,6 +26,8 @@ import ssl + + from .._async_compat.util import AsyncUtil from .._conf import ( Config, @@ -218,10 +220,10 @@ def driver(cls, uri, *, auth=None, **config) -> AsyncDriver: ) def bookmark_manager( cls, - initial_bookmarks: t.Mapping[str, t.Union[Bookmarks, - t.Iterable[str]]] = None, - bookmarks_supplier: _T_BmSupplier = None, - bookmarks_consumer: _T_BmConsumer = None + initial_bookmarks: t.Optional[t.Mapping[str, t.Union[Bookmarks, + t.Iterable[str]]]] = None, + bookmarks_supplier: t.Optional[_T_BmSupplier] = None, + bookmarks_consumer: t.Optional[_T_BmConsumer] = None ) -> AsyncBookmarkManager: """Create a :class:`.AsyncBookmarkManager` with default implementation. diff --git a/neo4j/_async/work/result.py b/neo4j/_async/work/result.py index 95b53abe8..0a9f2ef46 100644 --- a/neo4j/_async/work/result.py +++ b/neo4j/_async/work/result.py @@ -26,6 +26,8 @@ if t.TYPE_CHECKING: import typing_extensions as te + + from ..._async_compat.util import AsyncUtil from ..._codec.hydration import BrokenHydrationObject from ..._data import ( @@ -517,7 +519,7 @@ async def graph(self) -> Graph: return self._hydration_scope.get_graph() async def value( - self, key: _T_ResultKey = 0, default: object = None + self, key: _T_ResultKey = 0, default: t.Optional[object] = None ) -> t.List[t.Any]: """Helper function that return the remainder of the result as a list of values. diff --git a/neo4j/_async/work/session.py b/neo4j/_async/work/session.py index 4cb609b33..8c7b1c7f1 100644 --- a/neo4j/_async/work/session.py +++ b/neo4j/_async/work/session.py @@ -33,6 +33,8 @@ _R = t.TypeVar("_R") _P = te.ParamSpec("_P") + + from ..._async_compat import async_sleep from ..._async_compat.util import AsyncUtil from ..._conf import SessionConfig @@ -236,7 +238,7 @@ def cancel(self) -> None: async def run( self, query: t.Union[str, Query], - parameters: t.Dict[str, t.Any] = None, + parameters: t.Optional[t.Dict[str, t.Any]] = None, **kwargs: t.Any ) -> AsyncResult: """Run a Cypher query within an auto-commit transaction. @@ -321,7 +323,7 @@ async def last_bookmark(self) -> t.Optional[str]: if self._auto_result: await self._auto_result.consume() - if self._transaction and self._transaction._closed: + if self._transaction and self._transaction._closed(): await self._update_bookmark(self._transaction._database, self._transaction._bookmark) self._transaction = None @@ -405,8 +407,8 @@ async def _open_transaction( async def begin_transaction( self, - metadata: t.Dict[str, t.Any] = None, - timeout: float = None + metadata: t.Optional[t.Dict[str, t.Any]] = None, + timeout: t.Optional[float] = None ) -> AsyncTransaction: """ Begin a new unmanaged transaction. Creates a new :class:`.AsyncTransaction` within this session. At most one transaction may exist in a session at any point in time. diff --git a/neo4j/_async/work/transaction.py b/neo4j/_async/work/transaction.py index 7ec5d24e8..49c86a662 100644 --- a/neo4j/_async/work/transaction.py +++ b/neo4j/_async/work/transaction.py @@ -96,7 +96,7 @@ async def _consume_results(self): async def run( self, query: str, - parameters: t.Dict[str, t.Any] = None, + parameters: t.Optional[t.Dict[str, t.Any]] = None, **kwparameters: t.Any ) -> AsyncResult: """ Run a Cypher query within the context of this transaction. diff --git a/neo4j/_data.py b/neo4j/_data.py index fe679ce02..1fe702cd9 100644 --- a/neo4j/_data.py +++ b/neo4j/_data.py @@ -140,7 +140,7 @@ def __getslice__(self, start, stop): values = tuple(self)[key] return self.__class__(zip(keys, values)) - def get(self, key: str, default: object = None) -> t.Any: + def get(self, key: str, default: t.Optional[object] = None) -> t.Any: """ Obtain a value from the record by key, returning a default value if the key does not exist. @@ -177,7 +177,9 @@ def index(self, key: _T_K) -> int: # type: ignore[override] else: raise TypeError(key) - def value(self, key: _T_K = 0, default: object = None) -> t.Any: + def value( + self, key: _T_K = 0, default: t.Optional[object] = None + ) -> t.Any: """ Obtain a single value from the record by index or key. If no index or key is specified, the first value is returned. If the specified item does not exist, the default value is returned. diff --git a/neo4j/_spatial/__init__.py b/neo4j/_spatial/__init__.py index e95cda2f7..0dd91ba75 100644 --- a/neo4j/_spatial/__init__.py +++ b/neo4j/_spatial/__init__.py @@ -49,17 +49,15 @@ class Point(t.Tuple[float, ...]): #: be interpreted in. srid: t.Optional[int] - @property - def x(self) -> float: - ... + if t.TYPE_CHECKING: + @property + def x(self) -> float: ... - @property - def y(self) -> float: - ... + @property + def y(self) -> float: ... - @property - def z(self) -> float: - ... + @property + def z(self) -> float: ... def __new__(cls, iterable: t.Iterable[float]) -> Point: return tuple.__new__(cls, map(float, iterable)) diff --git a/neo4j/_sync/bookmark_manager.py b/neo4j/_sync/bookmark_manager.py index 85cb13bfe..49212d531 100644 --- a/neo4j/_sync/bookmark_manager.py +++ b/neo4j/_sync/bookmark_manager.py @@ -45,10 +45,10 @@ def _bookmarks_to_set( class Neo4jBookmarkManager(BookmarkManager): def __init__( self, - initial_bookmarks: t.Mapping[str, t.Union[Bookmarks, - t.Iterable[str]]] = None, - bookmarks_supplier: T_BmSupplier = None, - bookmarks_consumer: T_BmConsumer = None + initial_bookmarks: t.Optional[t.Mapping[str, t.Union[Bookmarks, + t.Iterable[str]]]] = None, + bookmarks_supplier: t.Optional[T_BmSupplier] = None, + bookmarks_consumer: t.Optional[T_BmConsumer] = None ) -> None: super().__init__() self._bookmarks_supplier = bookmarks_supplier diff --git a/neo4j/_sync/driver.py b/neo4j/_sync/driver.py index baa7a5934..f8018ac59 100644 --- a/neo4j/_sync/driver.py +++ b/neo4j/_sync/driver.py @@ -217,10 +217,10 @@ def driver(cls, uri, *, auth=None, **config) -> Driver: ) def bookmark_manager( cls, - initial_bookmarks: t.Mapping[str, t.Union[Bookmarks, - t.Iterable[str]]] = None, - bookmarks_supplier: _T_BmSupplier = None, - bookmarks_consumer: _T_BmConsumer = None + initial_bookmarks: t.Optional[t.Mapping[str, t.Union[Bookmarks, + t.Iterable[str]]]] = None, + bookmarks_supplier: t.Optional[_T_BmSupplier] = None, + bookmarks_consumer: t.Optional[_T_BmConsumer] = None ) -> BookmarkManager: """Create a :class:`.BookmarkManager` with default implementation. diff --git a/neo4j/_sync/work/result.py b/neo4j/_sync/work/result.py index ed6514cf9..13883a0d0 100644 --- a/neo4j/_sync/work/result.py +++ b/neo4j/_sync/work/result.py @@ -26,6 +26,8 @@ if t.TYPE_CHECKING: import typing_extensions as te + + from ..._async_compat.util import Util from ..._codec.hydration import BrokenHydrationObject from ..._data import ( @@ -517,7 +519,7 @@ def graph(self) -> Graph: return self._hydration_scope.get_graph() def value( - self, key: _T_ResultKey = 0, default: object = None + self, key: _T_ResultKey = 0, default: t.Optional[object] = None ) -> t.List[t.Any]: """Helper function that return the remainder of the result as a list of values. diff --git a/neo4j/_sync/work/session.py b/neo4j/_sync/work/session.py index c42783b85..b5046a8c3 100644 --- a/neo4j/_sync/work/session.py +++ b/neo4j/_sync/work/session.py @@ -33,6 +33,8 @@ _R = t.TypeVar("_R") _P = te.ParamSpec("_P") + + from ..._async_compat import sleep from ..._async_compat.util import Util from ..._conf import SessionConfig @@ -236,7 +238,7 @@ def cancel(self) -> None: def run( self, query: t.Union[str, Query], - parameters: t.Dict[str, t.Any] = None, + parameters: t.Optional[t.Dict[str, t.Any]] = None, **kwargs: t.Any ) -> Result: """Run a Cypher query within an auto-commit transaction. @@ -321,7 +323,7 @@ def last_bookmark(self) -> t.Optional[str]: if self._auto_result: self._auto_result.consume() - if self._transaction and self._transaction._closed: + if self._transaction and self._transaction._closed(): self._update_bookmark(self._transaction._database, self._transaction._bookmark) self._transaction = None @@ -405,8 +407,8 @@ def _open_transaction( def begin_transaction( self, - metadata: t.Dict[str, t.Any] = None, - timeout: float = None + metadata: t.Optional[t.Dict[str, t.Any]] = None, + timeout: t.Optional[float] = None ) -> Transaction: """ Begin a new unmanaged transaction. Creates a new :class:`.Transaction` within this session. At most one transaction may exist in a session at any point in time. diff --git a/neo4j/_sync/work/transaction.py b/neo4j/_sync/work/transaction.py index a6f3fd39f..12a551c45 100644 --- a/neo4j/_sync/work/transaction.py +++ b/neo4j/_sync/work/transaction.py @@ -96,7 +96,7 @@ def _consume_results(self): def run( self, query: str, - parameters: t.Dict[str, t.Any] = None, + parameters: t.Optional[t.Dict[str, t.Any]] = None, **kwparameters: t.Any ) -> Result: """ Run a Cypher query within the context of this transaction. diff --git a/neo4j/addressing.py b/neo4j/addressing.py index 6cebf798c..21257df2f 100644 --- a/neo4j/addressing.py +++ b/neo4j/addressing.py @@ -44,10 +44,7 @@ class _WithPeerName(te.Protocol): def getpeername(self) -> tuple: ... -assert type(tuple) is type - - -class _AddressMeta(type): +class _AddressMeta(type(tuple)): # type: ignore[misc] def __init__(cls, *args, **kwargs): super().__init__(*args, **kwargs) @@ -95,8 +92,8 @@ def from_socket( def parse( cls: t.Type[_T_Address], s: str, - default_host: str = None, - default_port: int = None + default_host: t.Optional[str] = None, + default_port: t.Optional[int] = None ) -> _T_Address: if not isinstance(s, str): raise TypeError("Address.parse requires a string argument") @@ -125,8 +122,8 @@ def parse( def parse_list( cls: t.Type[_T_Address], *s: str, - default_host: str = None, - default_port: int = None + default_host: t.Optional[str] = None, + default_port: t.Optional[int] = None ) -> t.List[_T_Address]: """ Parse a string containing one or more socket addresses, each separated by whitespace. diff --git a/neo4j/api.py b/neo4j/api.py index 6f441520f..7f428e084 100644 --- a/neo4j/api.py +++ b/neo4j/api.py @@ -32,6 +32,8 @@ import typing_extensions as te from .addressing import Address + + from ._meta import deprecated from .exceptions import ConfigurationError @@ -90,7 +92,7 @@ def __init__( scheme: t.Optional[str], principal: t.Optional[str], credentials: t.Optional[str], - realm: str = None, + realm: t.Optional[str] = None, **parameters: t.Any ) -> None: self.scheme = scheme @@ -110,7 +112,9 @@ def __init__( AuthToken = Auth -def basic_auth(user: str, password: str, realm: str = None) -> Auth: +def basic_auth( + user: str, password: str, realm: t.Optional[str] = None +) -> Auth: """Generate a basic auth token for a given user and password. This will set the scheme to "basic" for the auth token. diff --git a/neo4j/debug.py b/neo4j/debug.py index 8934e69a8..50863ff0c 100644 --- a/neo4j/debug.py +++ b/neo4j/debug.py @@ -113,7 +113,9 @@ def __exit__(self, exc_type, exc_val, exc_tb): """Disable logging for all loggers.""" self.stop() - def watch(self, level: int = None, out: t.TextIO = None): + def watch( + self, level: t.Optional[int] = None, out: t.Optional[t.TextIO] = None + ) -> None: """Enable logging for all loggers. :param level: Minimum log level to show. diff --git a/neo4j/exceptions.py b/neo4j/exceptions.py index 4d0c3f34c..dcf250cf6 100644 --- a/neo4j/exceptions.py +++ b/neo4j/exceptions.py @@ -100,6 +100,8 @@ _T_Session = t.Union["AsyncSession", "Session"] + + from ._meta import deprecated @@ -148,7 +150,10 @@ class Neo4jError(Exception): @classmethod def hydrate( - cls, message: str = None, code: str = None, **metadata: t.Any + cls, + message: t.Optional[str] = None, + code: t.Optional[str] = None, + **metadata: t.Any ) -> Neo4jError: message = message or "An unknown error occurred" code = code or "Neo.DatabaseError.General.UnknownError" diff --git a/neo4j/graph/__init__.py b/neo4j/graph/__init__.py index 7409165b0..77f08d951 100644 --- a/neo4j/graph/__init__.py +++ b/neo4j/graph/__init__.py @@ -166,7 +166,7 @@ def element_id(self) -> str: """ return self._element_id - def get(self, name: str, default: object = None) -> t.Any: + def get(self, name: str, default: t.Optional[object] = None) -> t.Any: """ Get a property value by name, optionally with a default. """ return self._properties.get(name, default) @@ -225,8 +225,8 @@ def __init__( graph: Graph, element_id: str, id_: int, - n_labels: t.Iterable[str] = None, - properties: t.Dict[str, t.Any] = None + n_labels: t.Optional[t.Iterable[str]] = None, + properties: t.Optional[t.Dict[str, t.Any]] = None ) -> None: Entity.__init__(self, graph, element_id, id_, properties) self._labels = frozenset(n_labels or ()) diff --git a/neo4j/time/__init__.py b/neo4j/time/__init__.py index ebca1d7f9..3e5730f26 100644 --- a/neo4j/time/__init__.py +++ b/neo4j/time/__init__.py @@ -782,7 +782,7 @@ def __new(cls, ordinal: int, year: int, month: int, day: int) -> Date: # CLASS METHODS # @classmethod - def today(cls, tz: _tzinfo = None) -> Date: + def today(cls, tz: t.Optional[_tzinfo] = None) -> Date: """Get the current date. :param tz: timezone or None to get the local :class:`.Date`. @@ -806,7 +806,9 @@ def utc_today(cls) -> Date: return cls.from_clock_time(Clock().utc_time(), UnixEpoch) @classmethod - def from_timestamp(cls, timestamp: float, tz: _tzinfo = None) -> Date: + def from_timestamp( + cls, timestamp: float, tz: t.Optional[_tzinfo] = None + ) -> Date: """:class:`.Date` from a time stamp (seconds since unix epoch). :param timestamp: the unix timestamp (seconds since unix epoch). @@ -1003,7 +1005,9 @@ def fromordinal(cls, ordinal: int) -> Date: ... @classmethod - def fromtimestamp(cls, timestamp: float, tz: _tzinfo = None) -> Date: + def fromtimestamp( + cls, timestamp: float, tz: t.Optional[_tzinfo] = None + ) -> Date: ... @classmethod @@ -1399,7 +1403,7 @@ def __new__( minute: int = 0, second: int = 0, nanosecond: int = 0, - tzinfo: _tzinfo = None + tzinfo: t.Optional[_tzinfo] = None ) -> Time: hour, minute, second, nanosecond = cls.__normalize_nanosecond( hour, minute, second, nanosecond @@ -1424,7 +1428,7 @@ def __new(cls, ticks, hour, minute, second, nanosecond, tzinfo): # CLASS METHODS # @classmethod - def now(cls, tz: _tzinfo = None) -> Time: + def now(cls, tz: t.Optional[_tzinfo] = None) -> Time: """Get the current time. :param tz: optional timezone @@ -1498,7 +1502,7 @@ def from_iso_format(cls, s: str) -> Time: raise ValueError("Time string is not in ISO format") @classmethod - def from_ticks(cls, ticks: int, tz: _tzinfo = None) -> Time: + def from_ticks(cls, ticks: int, tz: t.Optional[_tzinfo] = None) -> Time: """Create a time from ticks (nanoseconds since midnight). :param ticks: nanoseconds since midnight @@ -2010,7 +2014,7 @@ def __new__( minute: int = 0, second: int = 0, nanosecond: int = 0, - tzinfo: _tzinfo = None + tzinfo: t.Optional[_tzinfo] = None ) -> DateTime: return cls.combine(Date(year, month, day), Time(hour, minute, second, nanosecond, tzinfo)) @@ -2018,7 +2022,7 @@ def __new__( # CLASS METHODS # @classmethod - def now(cls, tz: _tzinfo = None) -> DateTime: + def now(cls, tz: t.Optional[_tzinfo] = None) -> DateTime: """Get the current date and time. :param tz: timezone. Set to None to create a local :class:`.DateTime`. @@ -2071,7 +2075,9 @@ def from_iso_format(cls, s) -> DateTime: raise ValueError("DateTime string is not in ISO format") @classmethod - def from_timestamp(cls, timestamp: float, tz: _tzinfo = None) -> DateTime: + def from_timestamp( + cls, timestamp: float, tz: t.Optional[_tzinfo] = None + ) -> DateTime: """:class:`.DateTime` from a time stamp (seconds since unix epoch). :param timestamp: the unix timestamp (seconds since unix epoch). @@ -2179,7 +2185,7 @@ def fromordinal(cls, ordinal: int) -> DateTime: @classmethod def fromtimestamp( - cls, timestamp: float, tz: _tzinfo = None + cls, timestamp: float, tz: t.Optional[_tzinfo] = None ) -> DateTime: ... @@ -2190,7 +2196,7 @@ def strptime(cls, date_string, format): # alias of now @classmethod - def today(cls, tz: _tzinfo = None) -> DateTime: + def today(cls, tz: t.Optional[_tzinfo] = None) -> DateTime: ... @classmethod diff --git a/neo4j/work/query.py b/neo4j/work/query.py index 8065ba2b8..a16fb5cc9 100644 --- a/neo4j/work/query.py +++ b/neo4j/work/query.py @@ -35,8 +35,8 @@ class Query: def __init__( self, text: str, - metadata: t.Dict[str, t.Any] = None, - timeout: float = None + metadata: t.Optional[t.Dict[str, t.Any]] = None, + timeout: t.Optional[float] = None ) -> None: self.text = text @@ -48,7 +48,8 @@ def __str__(self) -> str: def unit_of_work( - metadata: t.Dict[str, t.Any] = None, timeout: float = None + metadata: t.Optional[t.Dict[str, t.Any]] = None, + timeout: t.Optional[float] = None ) -> t.Callable[[_T], _T]: """Decorator giving extra control over transaction function configuration. diff --git a/tests/unit/async_/test_driver.py b/tests/unit/async_/test_driver.py index 2a5acf7b9..693adf94a 100644 --- a/tests/unit/async_/test_driver.py +++ b/tests/unit/async_/test_driver.py @@ -304,10 +304,10 @@ async def update_bookmarks( ... async def get_bookmarks(self, database: str) -> t.Collection[str]: - ... + return [] async def get_all_bookmarks(self) -> t.Collection[str]: - ... + return [] async def forget(self, databases: t.Iterable[str]) -> None: ... @@ -335,10 +335,10 @@ def update_bookmarks( ... def get_bookmarks(self, database: str) -> t.Collection[str]: - ... + return [] def get_all_bookmarks(self) -> t.Collection[str]: - ... + return [] def forget(self, databases: t.Iterable[str]) -> None: ... @@ -366,10 +366,10 @@ async def update_bookmarks( ... async def get_bookmarks(self, database: str) -> t.Collection[str]: - ... + return [] async def get_all_bookmarks(self) -> t.Collection[str]: - ... + return [] async def forget(self, databases: t.Iterable[str]) -> None: ... @@ -397,10 +397,10 @@ def update_bookmarks( ... def get_bookmarks(self, database: str) -> t.Collection[str]: - ... + return [] def get_all_bookmarks(self) -> t.Collection[str]: - ... + return [] def forget(self, databases: t.Iterable[str]) -> None: ... diff --git a/tests/unit/sync/test_driver.py b/tests/unit/sync/test_driver.py index 34e38d80b..8009b5bd2 100644 --- a/tests/unit/sync/test_driver.py +++ b/tests/unit/sync/test_driver.py @@ -303,10 +303,10 @@ def update_bookmarks( ... def get_bookmarks(self, database: str) -> t.Collection[str]: - ... + return [] def get_all_bookmarks(self) -> t.Collection[str]: - ... + return [] def forget(self, databases: t.Iterable[str]) -> None: ... @@ -334,10 +334,10 @@ def update_bookmarks( ... def get_bookmarks(self, database: str) -> t.Collection[str]: - ... + return [] def get_all_bookmarks(self) -> t.Collection[str]: - ... + return [] def forget(self, databases: t.Iterable[str]) -> None: ... @@ -365,10 +365,10 @@ def update_bookmarks( ... def get_bookmarks(self, database: str) -> t.Collection[str]: - ... + return [] def get_all_bookmarks(self) -> t.Collection[str]: - ... + return [] def forget(self, databases: t.Iterable[str]) -> None: ... @@ -396,10 +396,10 @@ def update_bookmarks( ... def get_bookmarks(self, database: str) -> t.Collection[str]: - ... + return [] def get_all_bookmarks(self) -> t.Collection[str]: - ... + return [] def forget(self, databases: t.Iterable[str]) -> None: ...