From d5ff23f084951f229d72d1da174249e5e92239e2 Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Wed, 5 Apr 2023 13:30:28 +0200 Subject: [PATCH 1/2] Mature execute_query API * Renaming `neo4j.RoutingControl.WRITERS` to `WRITE` and `READERS` to `READ`. * Renaming `driver.query_bookmark_manager()` to `execute_query_bookmark_manager()`. * Remove experimental tag from execute_query and its related APIs * `driver.execute_query` * `driver.execute_query_bookmark_manager` * `AsyncBookmarkManager`, `BookmarkManager`, the corresponding config option (session's `bookmark_manager`) and factory method (`driver.bookmark_manager()`) * `RoutingControl` enum * `EagerResult` and `result.to_eager_result()` --- CHANGELOG.md | 3 +- docs/source/api.rst | 22 +-- docs/source/async_api.rst | 22 +-- src/neo4j/_api.py | 15 +- src/neo4j/_async/driver.py | 74 +++----- src/neo4j/_async/work/result.py | 10 +- src/neo4j/_async_compat/util.py | 2 - src/neo4j/_conf.py | 2 +- src/neo4j/_sync/driver.py | 74 +++----- src/neo4j/_sync/work/result.py | 10 +- src/neo4j/_work/eager_result.py | 5 +- src/neo4j/api.py | 10 +- testkitbackend/_async/requests.py | 26 +-- testkitbackend/_sync/requests.py | 26 +-- tests/unit/async_/test_bookmark_manager.py | 3 +- tests/unit/async_/test_driver.py | 200 +++++++++------------ tests/unit/async_/work/test_result.py | 13 +- tests/unit/common/test_conf.py | 16 +- tests/unit/sync/test_bookmark_manager.py | 3 +- tests/unit/sync/test_driver.py | 200 +++++++++------------ tests/unit/sync/work/test_result.py | 13 +- 21 files changed, 260 insertions(+), 489 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 993b0788..02062640 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ See also https://github.com/neo4j/neo4j-python-driver/wiki for more details. ## NEXT RELEASE -- ... +- Renamed experimental `neo4j.RoutingControl.READERS` to `READ` and `WRITERS` to `WRITE`. +- Renamed experimental `driver.query_bookmark_manager` to `execute_query_bookmark_manager`. ## Version 5.7 diff --git a/docs/source/api.rst b/docs/source/api.rst index 46008581..e03c5cdc 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -156,7 +156,7 @@ Closing a driver will immediately shut down all connections in the pool. :members: session, query_bookmark_manager, encrypted, close, verify_connectivity, get_server_info - .. method:: execute_query(query, parameters_=None,routing_=neo4j.RoutingControl.WRITERS, database_=None, impersonated_user_=None, bookmark_manager_=self.query_bookmark_manager, result_transformer_=Result.to_eager_result, **kwargs) + .. method:: execute_query(query, parameters_=None,routing_=neo4j.RoutingControl.WRITE, database_=None, impersonated_user_=None, bookmark_manager_=self.query_bookmark_manager, result_transformer_=Result.to_eager_result, **kwargs) Execute a query in a transaction function and return all results. @@ -185,9 +185,9 @@ Closing a driver will immediately shut down all connections in the pool. impersonated_user=impersonated_user_, bookmark_manager=bookmark_manager_, ) as session: - if routing_ == RoutingControl.WRITERS: + if routing_ == RoutingControl.WRITE: return session.execute_write(work) - elif routing_ == RoutingControl.READERS: + elif routing_ == RoutingControl.READ: return session.execute_read(work) Usage example:: @@ -202,7 +202,7 @@ Closing a driver will immediately shut down all connections in the pool. records, summary, keys = driver.execute_query( "MATCH (p:Person {age: $age}) RETURN p.name", {"age": 42}, - routing_=neo4j.RoutingControl.READERS, # or just "r" + routing_=neo4j.RoutingControl.READ, # or just "r" database_="neo4j", ) assert keys == ["p.name"] # not needed, just for illustration @@ -223,7 +223,7 @@ Closing a driver will immediately shut down all connections in the pool. "SET p.nickname = 'My dear' " "RETURN count(*)", # optional routing parameter, as write is default - # routing_=neo4j.RoutingControl.WRITERS, # or just "w", + # routing_=neo4j.RoutingControl.WRITE, # or just "w", database_="neo4j", result_transformer_=neo4j.Result.single, age=15, @@ -348,15 +348,10 @@ Closing a driver will immediately shut down all connections in the pool. :returns: the result of the ``result_transformer`` :rtype: T - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - - We are looking for feedback on this feature. Please let us know what - you think about it here: - https://github.com/neo4j/neo4j-python-driver/discussions/896 - .. versionadded:: 5.5 + .. versionchanged:: 5.8 stabilized from experimental + .. _driver-configuration-ref: @@ -995,8 +990,7 @@ See :class:`.BookmarkManager` for more information. .. versionadded:: 5.0 -**This is experimental.** (See :ref:`filter-warnings-ref`) -It might be changed or removed any time even without prior notice. +.. versionchanged:: 5.8 stabilized from experimental .. _session-notifications-min-severity-ref: diff --git a/docs/source/async_api.rst b/docs/source/async_api.rst index 5fdcd8e8..3a1c9141 100644 --- a/docs/source/async_api.rst +++ b/docs/source/async_api.rst @@ -138,7 +138,7 @@ Closing a driver will immediately shut down all connections in the pool. :members: session, query_bookmark_manager, encrypted, close, verify_connectivity, get_server_info - .. method:: execute_query(query, parameters_=None, routing_=neo4j.RoutingControl.WRITERS, database_=None, impersonated_user_=None, bookmark_manager_=self.query_bookmark_manager, result_transformer_=AsyncResult.to_eager_result, **kwargs) + .. method:: execute_query(query, parameters_=None, routing_=neo4j.RoutingControl.WRITE, database_=None, impersonated_user_=None, bookmark_manager_=self.query_bookmark_manager, result_transformer_=AsyncResult.to_eager_result, **kwargs) :async: Execute a query in a transaction function and return all results. @@ -168,9 +168,9 @@ Closing a driver will immediately shut down all connections in the pool. impersonated_user=impersonated_user_, bookmark_manager=bookmark_manager_, ) as session: - if routing_ == RoutingControl.WRITERS: + if routing_ == RoutingControl.WRITE: return await session.execute_write(work) - elif routing_ == RoutingControl.READERS: + elif routing_ == RoutingControl.READ: return await session.execute_read(work) Usage example:: @@ -185,7 +185,7 @@ Closing a driver will immediately shut down all connections in the pool. records, summary, keys = await driver.execute_query( "MATCH (p:Person {age: $age}) RETURN p.name", {"age": 42}, - routing_=neo4j.RoutingControl.READERS, # or just "r" + routing_=neo4j.RoutingControl.READ, # or just "r" database_="neo4j", ) assert keys == ["p.name"] # not needed, just for illustration @@ -206,7 +206,7 @@ Closing a driver will immediately shut down all connections in the pool. "SET p.nickname = 'My dear' " "RETURN count(*)", # optional routing parameter, as write is default - # routing_=neo4j.RoutingControl.WRITERS, # or just "w", + # routing_=neo4j.RoutingControl.WRITE, # or just "w", database_="neo4j", result_transformer_=neo4j.AsyncResult.single, ) @@ -329,15 +329,10 @@ Closing a driver will immediately shut down all connections in the pool. :returns: the result of the ``result_transformer`` :rtype: T - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - - We are looking for feedback on this feature. Please let us know what - you think about it here: - https://github.com/neo4j/neo4j-python-driver/discussions/896 - .. versionadded:: 5.5 + .. versionchanged:: 5.8 stabilized from experimental + .. _async-driver-configuration-ref: @@ -622,8 +617,7 @@ See :class:`BookmarkManager` for more information. :Type: :data:`None`, :class:`BookmarkManager`, or :class:`AsyncBookmarkManager` :Default: :data:`None` -**This is experimental.** (See :ref:`filter-warnings-ref`) -It might be changed or removed any time even without prior notice. +.. versionchanged:: 5.8 stabilized from experimental diff --git a/src/neo4j/_api.py b/src/neo4j/_api.py index f42c189d..c833c0b3 100644 --- a/src/neo4j/_api.py +++ b/src/neo4j/_api.py @@ -208,21 +208,22 @@ class RoutingControl(str, Enum): Inherits from :class:`str` and :class:`Enum`. Every driver API accepting a :class:`.RoutingControl` value will also accept a string - >>> RoutingControl.READERS == "r" + >>> RoutingControl.READ == "r" True - >>> RoutingControl.WRITERS == "w" + >>> RoutingControl.WRITE == "w" True - **This is experimental.** - It might be changed or removed any time even without prior notice. - .. seealso:: :attr:`.AsyncDriver.execute_query`, :attr:`.Driver.execute_query` .. versionadded:: 5.5 + + .. versionchanged:: 5.8 + * renamed ``READERS`` to ``READ`` and ``WRITERS`` to ``WRITE`` + * stabilized from experimental """ - READERS = "r" - WRITERS = "w" + READ = "r" + WRITE = "w" if t.TYPE_CHECKING: diff --git a/src/neo4j/_async/driver.py b/src/neo4j/_async/driver.py index b9a5110c..5616fac1 100644 --- a/src/neo4j/_async/driver.py +++ b/src/neo4j/_async/driver.py @@ -47,7 +47,6 @@ deprecation_warn, experimental, experimental_warn, - ExperimentalWarning, unclosed_resource_warn, ) from .._work import EagerResult @@ -261,10 +260,6 @@ def driver( routing_context=routing_context, **config) @classmethod - @experimental( - "The bookmark manager feature is experimental. " - "It might be changed or removed any time even without prior notice." - ) def bookmark_manager( cls, initial_bookmarks: t.Union[None, Bookmarks, t.Iterable[str]] = None, @@ -325,9 +320,6 @@ def bookmark_manager( :returns: A default implementation of :class:`AsyncBookmarkManager`. - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - .. versionadded:: 5.0 .. versionchanged:: 5.3 @@ -341,6 +333,8 @@ def bookmark_manager( an argument. * ``bookmarks_consumer`` no longer receives the database name as an argument. + + .. versionchanged:: 5.8 stabilized from experimental """ return AsyncNeo4jBookmarkManager( initial_bookmarks=initial_bookmarks, @@ -448,12 +442,7 @@ def __init__(self, pool, default_workspace_config): assert default_workspace_config is not None self._pool = pool self._default_workspace_config = default_workspace_config - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", - message=r".*\bbookmark manager\b.*", - category=ExperimentalWarning) - self._query_bookmark_manager = \ - AsyncGraphDatabase.bookmark_manager() + self._query_bookmark_manager = AsyncGraphDatabase.bookmark_manager() async def __aenter__(self) -> AsyncDriver: return self @@ -543,7 +532,7 @@ async def execute_query( self, query_: str, parameters_: t.Optional[t.Dict[str, t.Any]] = None, - routing_: T_RoutingControl = RoutingControl.WRITERS, + routing_: T_RoutingControl = RoutingControl.WRITE, database_: t.Optional[str] = None, impersonated_user_: t.Optional[str] = None, bookmark_manager_: t.Union[ @@ -561,7 +550,7 @@ async def execute_query( self, query_: str, parameters_: t.Optional[t.Dict[str, t.Any]] = None, - routing_: T_RoutingControl = RoutingControl.WRITERS, + routing_: T_RoutingControl = RoutingControl.WRITE, database_: t.Optional[str] = None, impersonated_user_: t.Optional[str] = None, bookmark_manager_: t.Union[ @@ -574,15 +563,11 @@ async def execute_query( ) -> _T: ... - @experimental( - "Driver.execute_query is experimental. " - "It might be changed or removed any time even without prior notice." - ) async def execute_query( self, query_: str, parameters_: t.Optional[t.Dict[str, t.Any]] = None, - routing_: T_RoutingControl = RoutingControl.WRITERS, + routing_: T_RoutingControl = RoutingControl.WRITE, database_: t.Optional[str] = None, impersonated_user_: t.Optional[str] = None, bookmark_manager_: t.Union[ @@ -621,9 +606,9 @@ async def work(tx): impersonated_user=impersonated_user_, bookmark_manager=bookmark_manager_, ) as session: - if routing_ == RoutingControl.WRITERS: + if routing_ == RoutingControl.WRITE: return await session.execute_write(work) - elif routing_ == RoutingControl.READERS: + elif routing_ == RoutingControl.READ: return await session.execute_read(work) Usage example:: @@ -638,7 +623,7 @@ async def example(driver: neo4j.AsyncDriver) -> List[str]: records, summary, keys = await driver.execute_query( "MATCH (p:Person {age: $age}) RETURN p.name", {"age": 42}, - routing_=neo4j.RoutingControl.READERS, # or just "r" + routing_=neo4j.RoutingControl.READ, # or just "r" database_="neo4j", ) assert keys == ["p.name"] # not needed, just for illustration @@ -659,7 +644,7 @@ async def example(driver: neo4j.AsyncDriver) -> int: "SET p.nickname = 'My dear' " "RETURN count(*)", # optional routing parameter, as write is default - # routing_=neo4j.RoutingControl.WRITERS, # or just "w", + # routing_=neo4j.RoutingControl.WRITE, # or just "w", database_="neo4j", result_transformer_=neo4j.AsyncResult.single, ) @@ -782,10 +767,9 @@ async def example(driver: neo4j.AsyncDriver) -> neo4j.Record:: :returns: the result of the ``result_transformer`` :rtype: T - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - .. versionadded:: 5.5 + + .. versionchanged:: 5.8 stabilized from experimental """ invalid_kwargs = [k for k in kwargs if k[-2:-1] != "_" and k[-1:] == "_"] @@ -803,17 +787,13 @@ async def example(driver: neo4j.AsyncDriver) -> neo4j.Record:: bookmark_manager_ = self._query_bookmark_manager assert bookmark_manager_ is not _default - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", - message=r".*\bbookmark_manager\b.*", - category=ExperimentalWarning) - session = self.session(database=database_, - impersonated_user=impersonated_user_, - bookmark_manager=bookmark_manager_) + session = self.session(database=database_, + impersonated_user=impersonated_user_, + bookmark_manager=bookmark_manager_) async with session: - if routing_ == RoutingControl.WRITERS: + if routing_ == RoutingControl.WRITE: executor = session.execute_write - elif routing_ == RoutingControl.READERS: + elif routing_ == RoutingControl.READ: executor = session.execute_read else: raise ValueError("Invalid routing control value: %r" @@ -823,11 +803,7 @@ async def example(driver: neo4j.AsyncDriver) -> neo4j.Record:: ) @property - @experimental( - "Driver.query_bookmark_manager is experimental. " - "It might be changed or removed any time even without prior notice." - ) - def query_bookmark_manager(self) -> AsyncBookmarkManager: + def execute_query_bookmark_manager(self) -> AsyncBookmarkManager: """The driver's default query bookmark manager. This is the default :class:`AsyncBookmarkManager` used by @@ -846,10 +822,12 @@ async def example(driver: neo4j.AsyncDriver) -> None: # (i.e., can read what was written by ) await driver.execute_query("") - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - .. versionadded:: 5.5 + + .. versionchanged:: 5.8 + * renamed from ``query_bookmark_manager`` to + ``execute_query_bookmark_manager`` + * stabilized from experimental """ return self._query_bookmark_manager @@ -1020,11 +998,7 @@ async def _work( ) -> _T: res = await tx.run(query, parameters) if transformer is AsyncResult.to_eager_result: - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", - message=r".*\bto_eager_result\b.*", - category=ExperimentalWarning) - return await transformer(res) + return await transformer(res) return await transformer(res) diff --git a/src/neo4j/_async/work/result.py b/src/neo4j/_async/work/result.py index 6743556c..b01fd555 100644 --- a/src/neo4j/_async/work/result.py +++ b/src/neo4j/_async/work/result.py @@ -35,7 +35,6 @@ Record, RecordTableRowExporter, ) -from ..._meta import experimental from ..._work import ( EagerResult, ResultSummary, @@ -608,10 +607,6 @@ async def data(self, *keys: _TResultKey) -> t.List[t.Dict[str, t.Any]]: """ return [record.data(*keys) async for record in self] - @experimental( - "Result.to_eager_result is experimental. " - "It might be changed or removed any time even without prior notice." - ) async def to_eager_result(self) -> EagerResult: """Convert this result to an :class:`.EagerResult`. @@ -624,10 +619,9 @@ async def to_eager_result(self) -> EagerResult: was obtained has been closed or the Result has been explicitly consumed. - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - .. versionadded:: 5.5 + + .. versionchanged:: 5.8 stabilized from experimental """ await self._buffer_all() diff --git a/src/neo4j/_async_compat/util.py b/src/neo4j/_async_compat/util.py index 53771edf..f7027926 100644 --- a/src/neo4j/_async_compat/util.py +++ b/src/neo4j/_async_compat/util.py @@ -23,8 +23,6 @@ import typing as t from functools import wraps -from .._meta import experimental - if t.TYPE_CHECKING: import typing_extensions as te diff --git a/src/neo4j/_conf.py b/src/neo4j/_conf.py index b3a4d0b0..a5f087dd 100644 --- a/src/neo4j/_conf.py +++ b/src/neo4j/_conf.py @@ -497,7 +497,7 @@ class WorkspaceConfig(Config): # Note that you need appropriate permissions to do so. #: Bookmark Manager - bookmark_manager = ExperimentalOption(None) + bookmark_manager = None # Specify the bookmark manager to be used for sessions by default. diff --git a/src/neo4j/_sync/driver.py b/src/neo4j/_sync/driver.py index 5118cc00..b80f084f 100644 --- a/src/neo4j/_sync/driver.py +++ b/src/neo4j/_sync/driver.py @@ -46,7 +46,6 @@ deprecation_warn, experimental, experimental_warn, - ExperimentalWarning, unclosed_resource_warn, ) from .._work import EagerResult @@ -259,10 +258,6 @@ def driver( routing_context=routing_context, **config) @classmethod - @experimental( - "The bookmark manager feature is experimental. " - "It might be changed or removed any time even without prior notice." - ) def bookmark_manager( cls, initial_bookmarks: t.Union[None, Bookmarks, t.Iterable[str]] = None, @@ -323,9 +318,6 @@ def bookmark_manager( :returns: A default implementation of :class:`BookmarkManager`. - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - .. versionadded:: 5.0 .. versionchanged:: 5.3 @@ -339,6 +331,8 @@ def bookmark_manager( an argument. * ``bookmarks_consumer`` no longer receives the database name as an argument. + + .. versionchanged:: 5.8 stabilized from experimental """ return Neo4jBookmarkManager( initial_bookmarks=initial_bookmarks, @@ -446,12 +440,7 @@ def __init__(self, pool, default_workspace_config): assert default_workspace_config is not None self._pool = pool self._default_workspace_config = default_workspace_config - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", - message=r".*\bbookmark manager\b.*", - category=ExperimentalWarning) - self._query_bookmark_manager = \ - GraphDatabase.bookmark_manager() + self._query_bookmark_manager = GraphDatabase.bookmark_manager() def __enter__(self) -> Driver: return self @@ -541,7 +530,7 @@ def execute_query( self, query_: str, parameters_: t.Optional[t.Dict[str, t.Any]] = None, - routing_: T_RoutingControl = RoutingControl.WRITERS, + routing_: T_RoutingControl = RoutingControl.WRITE, database_: t.Optional[str] = None, impersonated_user_: t.Optional[str] = None, bookmark_manager_: t.Union[ @@ -559,7 +548,7 @@ def execute_query( self, query_: str, parameters_: t.Optional[t.Dict[str, t.Any]] = None, - routing_: T_RoutingControl = RoutingControl.WRITERS, + routing_: T_RoutingControl = RoutingControl.WRITE, database_: t.Optional[str] = None, impersonated_user_: t.Optional[str] = None, bookmark_manager_: t.Union[ @@ -572,15 +561,11 @@ def execute_query( ) -> _T: ... - @experimental( - "Driver.execute_query is experimental. " - "It might be changed or removed any time even without prior notice." - ) def execute_query( self, query_: str, parameters_: t.Optional[t.Dict[str, t.Any]] = None, - routing_: T_RoutingControl = RoutingControl.WRITERS, + routing_: T_RoutingControl = RoutingControl.WRITE, database_: t.Optional[str] = None, impersonated_user_: t.Optional[str] = None, bookmark_manager_: t.Union[ @@ -619,9 +604,9 @@ def work(tx): impersonated_user=impersonated_user_, bookmark_manager=bookmark_manager_, ) as session: - if routing_ == RoutingControl.WRITERS: + if routing_ == RoutingControl.WRITE: return session.execute_write(work) - elif routing_ == RoutingControl.READERS: + elif routing_ == RoutingControl.READ: return session.execute_read(work) Usage example:: @@ -636,7 +621,7 @@ def example(driver: neo4j.Driver) -> List[str]: records, summary, keys = driver.execute_query( "MATCH (p:Person {age: $age}) RETURN p.name", {"age": 42}, - routing_=neo4j.RoutingControl.READERS, # or just "r" + routing_=neo4j.RoutingControl.READ, # or just "r" database_="neo4j", ) assert keys == ["p.name"] # not needed, just for illustration @@ -657,7 +642,7 @@ def example(driver: neo4j.Driver) -> int: "SET p.nickname = 'My dear' " "RETURN count(*)", # optional routing parameter, as write is default - # routing_=neo4j.RoutingControl.WRITERS, # or just "w", + # routing_=neo4j.RoutingControl.WRITE, # or just "w", database_="neo4j", result_transformer_=neo4j.Result.single, ) @@ -780,10 +765,9 @@ def example(driver: neo4j.Driver) -> neo4j.Record:: :returns: the result of the ``result_transformer`` :rtype: T - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - .. versionadded:: 5.5 + + .. versionchanged:: 5.8 stabilized from experimental """ invalid_kwargs = [k for k in kwargs if k[-2:-1] != "_" and k[-1:] == "_"] @@ -801,17 +785,13 @@ def example(driver: neo4j.Driver) -> neo4j.Record:: bookmark_manager_ = self._query_bookmark_manager assert bookmark_manager_ is not _default - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", - message=r".*\bbookmark_manager\b.*", - category=ExperimentalWarning) - session = self.session(database=database_, - impersonated_user=impersonated_user_, - bookmark_manager=bookmark_manager_) + session = self.session(database=database_, + impersonated_user=impersonated_user_, + bookmark_manager=bookmark_manager_) with session: - if routing_ == RoutingControl.WRITERS: + if routing_ == RoutingControl.WRITE: executor = session.execute_write - elif routing_ == RoutingControl.READERS: + elif routing_ == RoutingControl.READ: executor = session.execute_read else: raise ValueError("Invalid routing control value: %r" @@ -821,11 +801,7 @@ def example(driver: neo4j.Driver) -> neo4j.Record:: ) @property - @experimental( - "Driver.query_bookmark_manager is experimental. " - "It might be changed or removed any time even without prior notice." - ) - def query_bookmark_manager(self) -> BookmarkManager: + def execute_query_bookmark_manager(self) -> BookmarkManager: """The driver's default query bookmark manager. This is the default :class:`BookmarkManager` used by @@ -844,10 +820,12 @@ def example(driver: neo4j.Driver) -> None: # (i.e., can read what was written by ) driver.execute_query("") - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - .. versionadded:: 5.5 + + .. versionchanged:: 5.8 + * renamed from ``query_bookmark_manager`` to + ``execute_query_bookmark_manager`` + * stabilized from experimental """ return self._query_bookmark_manager @@ -1018,11 +996,7 @@ def _work( ) -> _T: res = tx.run(query, parameters) if transformer is Result.to_eager_result: - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", - message=r".*\bto_eager_result\b.*", - category=ExperimentalWarning) - return transformer(res) + return transformer(res) return transformer(res) diff --git a/src/neo4j/_sync/work/result.py b/src/neo4j/_sync/work/result.py index 86255e5f..4a0ed37f 100644 --- a/src/neo4j/_sync/work/result.py +++ b/src/neo4j/_sync/work/result.py @@ -35,7 +35,6 @@ Record, RecordTableRowExporter, ) -from ..._meta import experimental from ..._work import ( EagerResult, ResultSummary, @@ -608,10 +607,6 @@ def data(self, *keys: _TResultKey) -> t.List[t.Dict[str, t.Any]]: """ return [record.data(*keys) for record in self] - @experimental( - "Result.to_eager_result is experimental. " - "It might be changed or removed any time even without prior notice." - ) def to_eager_result(self) -> EagerResult: """Convert this result to an :class:`.EagerResult`. @@ -624,10 +619,9 @@ def to_eager_result(self) -> EagerResult: was obtained has been closed or the Result has been explicitly consumed. - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - .. versionadded:: 5.5 + + .. versionchanged:: 5.8 stabilized from experimental """ self._buffer_all() diff --git a/src/neo4j/_work/eager_result.py b/src/neo4j/_work/eager_result.py index 87abb410..5e7aaa24 100644 --- a/src/neo4j/_work/eager_result.py +++ b/src/neo4j/_work/eager_result.py @@ -33,9 +33,6 @@ class EagerResult(t.NamedTuple): * keys - the list of keys returned by the query (see :attr:`AsyncResult.keys` and :attr:`.Result.keys`) - **This is experimental.** (See :ref:`filter-warnings-ref`) - It might be changed or removed any time even without prior notice. - .. seealso:: :attr:`.AsyncDriver.execute_query`, :attr:`.Driver.execute_query` Which by default return an instance of this class. @@ -44,6 +41,8 @@ class EagerResult(t.NamedTuple): Which can be used to convert to instance of this class. .. versionadded:: 5.5 + + .. versionchanged:: 5.8 stabilized from experimental """ #: Alias for field 0 (``eager_result[0]``) records: t.List[Record] diff --git a/src/neo4j/api.py b/src/neo4j/api.py index e91aed6e..cf4d39ac 100644 --- a/src/neo4j/api.py +++ b/src/neo4j/api.py @@ -397,9 +397,6 @@ class BookmarkManager(_Protocol, metaclass=abc.ABCMeta): .. note:: All methods must be concurrency safe. - **This is experimental.** - It might be changed or removed any time even without prior notice. - .. versionadded:: 5.0 .. versionchanged:: 5.3 @@ -411,6 +408,8 @@ class BookmarkManager(_Protocol, metaclass=abc.ABCMeta): * :meth:`.get_bookmarks` has no longer a ``database`` argument. * The ``get_all_bookmarks`` method was removed. * The ``forget`` method was removed. + + .. versionchanged:: 5.8 stabilized from experimental """ @abc.abstractmethod @@ -442,13 +441,12 @@ class AsyncBookmarkManager(_Protocol, metaclass=abc.ABCMeta): The driver comes with a default implementation of the async bookmark manager accessible through :attr:`.AsyncGraphDatabase.bookmark_manager()`. - **This is experimental.** - It might be changed or removed any time even without prior notice. - .. versionadded:: 5.0 .. versionchanged:: 5.3 See :class:`.BookmarkManager` for changes. + + .. versionchanged:: 5.8 stabilized from experimental """ @abc.abstractmethod diff --git a/testkitbackend/_async/requests.py b/testkitbackend/_async/requests.py index ce5b92d2..a4daba20 100644 --- a/testkitbackend/_async/requests.py +++ b/testkitbackend/_async/requests.py @@ -210,12 +210,7 @@ async def ExecuteQuery(backend, data): bookmark_manager = backend.bookmark_managers[bookmark_manager_id] kwargs["bookmark_manager_"] = bookmark_manager - with warning_check( - neo4j.ExperimentalWarning, - "Driver.execute_query is experimental. " - "It might be changed or removed any time even without prior notice." - ): - eager_result = await driver.execute_query(cypher, params, **kwargs) + eager_result = await driver.execute_query(cypher, params, **kwargs) await backend.send_response("EagerResult", { "keys": eager_result.keys, "records": list(map(totestkit.record, eager_result.records)), @@ -300,14 +295,7 @@ async def NewBookmarkManager(backend, data): backend, bookmark_manager_id ) - with warning_check( - neo4j.ExperimentalWarning, - "The bookmark manager feature is experimental. It might be changed or " - "removed any time even without prior notice." - ): - bookmark_manager = neo4j.AsyncGraphDatabase.bookmark_manager( - **bmm_kwargs - ) + bookmark_manager = neo4j.AsyncGraphDatabase.bookmark_manager(**bmm_kwargs) backend.bookmark_managers[bookmark_manager_id] = bookmark_manager await backend.send_response("BookmarkManager", {"id": bookmark_manager_id}) @@ -421,15 +409,7 @@ async def NewSession(backend, data): if data_name in data: config[conf_name] = data[data_name] fromtestkit.set_notifications_config(config, data) - if "bookmark_manager" in config: - with warning_check( - neo4j.ExperimentalWarning, - "The 'bookmark_manager' config key is experimental. It might be " - "changed or removed any time even without prior notice." - ): - session = driver.session(**config) - else: - session = driver.session(**config) + session = driver.session(**config) key = backend.next_key() backend.sessions[key] = SessionTracker(session) await backend.send_response("Session", {"id": key}) diff --git a/testkitbackend/_sync/requests.py b/testkitbackend/_sync/requests.py index 07a44673..c4f7aff4 100644 --- a/testkitbackend/_sync/requests.py +++ b/testkitbackend/_sync/requests.py @@ -210,12 +210,7 @@ def ExecuteQuery(backend, data): bookmark_manager = backend.bookmark_managers[bookmark_manager_id] kwargs["bookmark_manager_"] = bookmark_manager - with warning_check( - neo4j.ExperimentalWarning, - "Driver.execute_query is experimental. " - "It might be changed or removed any time even without prior notice." - ): - eager_result = driver.execute_query(cypher, params, **kwargs) + eager_result = driver.execute_query(cypher, params, **kwargs) backend.send_response("EagerResult", { "keys": eager_result.keys, "records": list(map(totestkit.record, eager_result.records)), @@ -300,14 +295,7 @@ def NewBookmarkManager(backend, data): backend, bookmark_manager_id ) - with warning_check( - neo4j.ExperimentalWarning, - "The bookmark manager feature is experimental. It might be changed or " - "removed any time even without prior notice." - ): - bookmark_manager = neo4j.GraphDatabase.bookmark_manager( - **bmm_kwargs - ) + bookmark_manager = neo4j.GraphDatabase.bookmark_manager(**bmm_kwargs) backend.bookmark_managers[bookmark_manager_id] = bookmark_manager backend.send_response("BookmarkManager", {"id": bookmark_manager_id}) @@ -421,15 +409,7 @@ def NewSession(backend, data): if data_name in data: config[conf_name] = data[data_name] fromtestkit.set_notifications_config(config, data) - if "bookmark_manager" in config: - with warning_check( - neo4j.ExperimentalWarning, - "The 'bookmark_manager' config key is experimental. It might be " - "changed or removed any time even without prior notice." - ): - session = driver.session(**config) - else: - session = driver.session(**config) + session = driver.session(**config) key = backend.next_key() backend.sessions[key] = SessionTracker(session) backend.send_response("Session", {"id": key}) diff --git a/tests/unit/async_/test_bookmark_manager.py b/tests/unit/async_/test_bookmark_manager.py index a24ac253..c5800d8d 100644 --- a/tests/unit/async_/test_bookmark_manager.py +++ b/tests/unit/async_/test_bookmark_manager.py @@ -36,8 +36,7 @@ @copy_signature(neo4j.AsyncGraphDatabase.bookmark_manager) def bookmark_manager(*args, **kwargs): - with pytest.warns(neo4j.ExperimentalWarning, match="bookmark manager"): - return neo4j.AsyncGraphDatabase.bookmark_manager(*args, **kwargs) + return neo4j.AsyncGraphDatabase.bookmark_manager(*args, **kwargs) @mark_async_test diff --git a/tests/unit/async_/test_driver.py b/tests/unit/async_/test_driver.py index 04ef4e97..a2c349d9 100644 --- a/tests/unit/async_/test_driver.py +++ b/tests/unit/async_/test_driver.py @@ -63,25 +63,6 @@ ) -@contextmanager -def assert_warns_execute_query_experimental(): - with pytest.warns( - ExperimentalWarning, - match=r"^Driver\.execute_query is experimental\." - ): - yield - - -@contextmanager -def assert_warns_execute_query_bmm_experimental(): - with pytest.warns( - ExperimentalWarning, - match=r"^Driver\.query_bookmark_manager is experimental\." - ): - yield - - - @pytest.mark.parametrize("protocol", ("bolt://", "bolt+s://", "bolt+ssc://")) @pytest.mark.parametrize("host", ("localhost", "127.0.0.1", "[::1]", "[0:0:0:0:0:0:0:1]")) @@ -316,16 +297,14 @@ async def test_get_server_info_parameters_are_experimental( @mark_async_test async def test_with_builtin_bookmark_manager(mocker) -> None: - with pytest.warns(ExperimentalWarning, match="bookmark manager"): - bmm = AsyncGraphDatabase.bookmark_manager() + bmm = AsyncGraphDatabase.bookmark_manager() # could be one line, but want to make sure the type checker assigns # bmm whatever type AsyncGraphDatabase.bookmark_manager() returns session_cls_mock = mocker.patch("neo4j._async.driver.AsyncSession", autospec=True) driver = AsyncGraphDatabase.driver("bolt://localhost") async with driver as driver: - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - _ = driver.session(bookmark_manager=bmm) + _ = driver.session(bookmark_manager=bmm) session_cls_mock.assert_called_once() assert session_cls_mock.call_args[0][1].bookmark_manager is bmm @@ -352,8 +331,7 @@ async def forget(self, databases: t.Iterable[str]) -> None: autospec=True) driver = AsyncGraphDatabase.driver("bolt://localhost") async with driver as driver: - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - _ = driver.session(bookmark_manager=bmm) + _ = driver.session(bookmark_manager=bmm) session_cls_mock.assert_called_once() assert session_cls_mock.call_args[0][1].bookmark_manager is bmm @@ -380,8 +358,7 @@ def forget(self, databases: t.Iterable[str]) -> None: autospec=True) driver = AsyncGraphDatabase.driver("bolt://localhost") async with driver as driver: - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - _ = driver.session(bookmark_manager=bmm) + _ = driver.session(bookmark_manager=bmm) session_cls_mock.assert_called_once() assert session_cls_mock.call_args[0][1].bookmark_manager is bmm @@ -408,8 +385,7 @@ async def forget(self, databases: t.Iterable[str]) -> None: autospec=True) driver = AsyncGraphDatabase.driver("bolt://localhost") async with driver as driver: - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - _ = driver.session(bookmark_manager=bmm) + _ = driver.session(bookmark_manager=bmm) session_cls_mock.assert_called_once() assert session_cls_mock.call_args[0][1].bookmark_manager is bmm @@ -436,8 +412,7 @@ def forget(self, databases: t.Iterable[str]) -> None: autospec=True) driver = AsyncGraphDatabase.driver("bolt://localhost") async with driver as driver: - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - _ = driver.session(bookmark_manager=bmm) + _ = driver.session(bookmark_manager=bmm) session_cls_mock.assert_called_once() assert session_cls_mock.call_args[0][1].bookmark_manager is bmm @@ -661,11 +636,10 @@ async def test_execute_query_query( session_cls_mock = mocker.patch("neo4j._async.driver.AsyncSession", autospec=True) async with driver as driver: - with assert_warns_execute_query_experimental(): - if positional: - res = await driver.execute_query(query) - else: - res = await driver.execute_query(query_=query) + if positional: + res = await driver.execute_query(query) + else: + res = await driver.execute_query(query_=query) session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value @@ -691,16 +665,14 @@ async def test_execute_query_parameters( session_cls_mock = mocker.patch("neo4j._async.driver.AsyncSession", autospec=True) async with driver as driver: - with assert_warns_execute_query_experimental(): - if parameters is Ellipsis: - parameters = None - res = await driver.execute_query("") + if parameters is Ellipsis: + parameters = None + res = await driver.execute_query("") + else: + if positional: + res = await driver.execute_query("", parameters) else: - if positional: - res = await driver.execute_query("", parameters) - else: - res = await driver.execute_query("", - parameters_=parameters) + res = await driver.execute_query("", parameters_=parameters) session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value @@ -724,11 +696,10 @@ async def test_execute_query_keyword_parameters( session_cls_mock = mocker.patch("neo4j._async.driver.AsyncSession", autospec=True) async with driver as driver: - with assert_warns_execute_query_experimental(): - if parameters is None: - res = await driver.execute_query("") - else: - res = await driver.execute_query("", **parameters) + if parameters is None: + res = await driver.execute_query("") + else: + res = await driver.execute_query("", **parameters) session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value @@ -751,8 +722,7 @@ async def test_reserved_query_keyword_parameters( mocker.patch("neo4j._async.driver.AsyncSession", autospec=True) async with driver as driver: with pytest.raises(ValueError) as exc: - with assert_warns_execute_query_experimental(): - await driver.execute_query("", **parameters) + await driver.execute_query("", **parameters) exc.match("reserved") exc.match(", ".join(f"'{k}'" for k in parameters)) @@ -799,15 +769,14 @@ async def test_execute_query_parameter_precedence( session_cls_mock = mocker.patch("neo4j._async.driver.AsyncSession", autospec=True) async with driver as driver: - with assert_warns_execute_query_experimental(): - if params is None: - res = await driver.execute_query("", **kw_params) + if params is None: + res = await driver.execute_query("", **kw_params) + else: + if positional: + res = await driver.execute_query("", params, **kw_params) else: - if positional: - res = await driver.execute_query("", params, **kw_params) - else: - res = await driver.execute_query("", parameters_=params, - **kw_params) + res = await driver.execute_query("", parameters_=params, + **kw_params) session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value @@ -826,8 +795,8 @@ async def test_execute_query_parameter_precedence( (None, "execute_write"), ("r", "execute_read"), ("w", "execute_write"), - (neo4j.RoutingControl.READERS, "execute_read"), - (neo4j.RoutingControl.WRITERS, "execute_write"), + (neo4j.RoutingControl.READ, "execute_read"), + (neo4j.RoutingControl.WRITE, "execute_write"), ) ) @pytest.mark.parametrize("positional", (True, False)) @@ -840,14 +809,13 @@ async def test_execute_query_routing_control( session_cls_mock = mocker.patch("neo4j._async.driver.AsyncSession", autospec=True) async with driver as driver: - with assert_warns_execute_query_experimental(): - if routing_mode is None: - res = await driver.execute_query("") + if routing_mode is None: + res = await driver.execute_query("") + else: + if positional: + res = await driver.execute_query("", None, routing_mode) else: - if positional: - res = await driver.execute_query("", None, routing_mode) - else: - res = await driver.execute_query("", routing_=routing_mode) + res = await driver.execute_query("", routing_=routing_mode) session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value @@ -872,15 +840,14 @@ async def test_execute_query_database( session_cls_mock = mocker.patch("neo4j._async.driver.AsyncSession", autospec=True) async with driver as driver: - with assert_warns_execute_query_experimental(): - if database is Ellipsis: - database = None - await driver.execute_query("") + if database is Ellipsis: + database = None + await driver.execute_query("") + else: + if positional: + await driver.execute_query("", None, "w", database) else: - if positional: - await driver.execute_query("", None, "w", database) - else: - await driver.execute_query("", database_=database) + await driver.execute_query("", database_=database) session_cls_mock.assert_called_once() session_config = session_cls_mock.call_args.args[1] @@ -897,19 +864,18 @@ async def test_execute_query_impersonated_user( session_cls_mock = mocker.patch("neo4j._async.driver.AsyncSession", autospec=True) async with driver as driver: - with assert_warns_execute_query_experimental(): - if impersonated_user is Ellipsis: - impersonated_user = None - await driver.execute_query("") + if impersonated_user is Ellipsis: + impersonated_user = None + await driver.execute_query("") + else: + if positional: + await driver.execute_query( + "", None, "w", None, impersonated_user + ) else: - if positional: - await driver.execute_query( - "", None, "w", None, impersonated_user - ) - else: - await driver.execute_query( - "", impersonated_user_=impersonated_user - ) + await driver.execute_query( + "", impersonated_user_=impersonated_user + ) session_cls_mock.assert_called_once() session_config = session_cls_mock.call_args.args[1] @@ -927,20 +893,18 @@ async def test_execute_query_bookmark_manager( session_cls_mock = mocker.patch("neo4j._async.driver.AsyncSession", autospec=True) async with driver as driver: - with assert_warns_execute_query_experimental(): - if bookmark_manager is Ellipsis: - with assert_warns_execute_query_bmm_experimental(): - bookmark_manager = driver.query_bookmark_manager - await driver.execute_query("") + if bookmark_manager is Ellipsis: + bookmark_manager = driver.execute_query_bookmark_manager + await driver.execute_query("") + else: + if positional: + await driver.execute_query( + "", None, "w", None, None, bookmark_manager + ) else: - if positional: - await driver.execute_query( - "", None, "w", None, None, bookmark_manager - ) - else: - await driver.execute_query( - "", bookmark_manager_=bookmark_manager - ) + await driver.execute_query( + "", bookmark_manager_=bookmark_manager + ) session_cls_mock.assert_called_once() session_config = session_cls_mock.call_args.args[1] @@ -959,24 +923,22 @@ async def test_execute_query_result_transformer( autospec=True) res: t.Any async with driver as driver: - with assert_warns_execute_query_experimental(): - if result_transformer is Ellipsis: - result_transformer = AsyncResult.to_eager_result - res_default: neo4j.EagerResult = await driver.execute_query("") - res = res_default + if result_transformer is Ellipsis: + result_transformer = AsyncResult.to_eager_result + res_default: neo4j.EagerResult = await driver.execute_query("") + res = res_default + else: + res_custom: SomeClass + if positional: + bmm = driver.execute_query_bookmark_manager + res_custom = await driver.execute_query( + "", None, "w", None, None, bmm, result_transformer + ) else: - res_custom: SomeClass - if positional: - with assert_warns_execute_query_bmm_experimental(): - bmm = driver.query_bookmark_manager - res_custom = await driver.execute_query( - "", None, "w", None, None, bmm, result_transformer - ) - else: - res_custom = await driver.execute_query( - "", result_transformer_=result_transformer - ) - res = res_custom + res_custom = await driver.execute_query( + "", result_transformer_=result_transformer + ) + res = res_custom session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value diff --git a/tests/unit/async_/work/test_result.py b/tests/unit/async_/work/test_result.py index 7bcdbaeb..47a4a080 100644 --- a/tests/unit/async_/work/test_result.py +++ b/tests/unit/async_/work/test_result.py @@ -29,7 +29,6 @@ Address, AsyncResult, EagerResult, - ExperimentalWarning, Record, ResultSummary, ServerInfo, @@ -56,15 +55,6 @@ from ...._async_compat import mark_async_test -@contextmanager -def assert_warns_to_eager_result_experimental(): - with pytest.warns( - ExperimentalWarning, - match=r"^Result\.to_eager_result is experimental\." - ): - yield - - class Records: def __init__(self, fields, records): self.fields = tuple(fields) @@ -720,8 +710,7 @@ async def test_to_eager_result(records): connection = AsyncConnectionStub(records=records, summary_meta=summary) result = AsyncResult(connection, 1, noop, noop) await result._run("CYPHER", {}, None, None, "r", None, None, None) - with assert_warns_to_eager_result_experimental(): - eager_result = await result.to_eager_result() + eager_result = await result.to_eager_result() assert isinstance(eager_result, EagerResult) diff --git a/tests/unit/common/test_conf.py b/tests/unit/common/test_conf.py index 0a18c535..b3c7cc82 100644 --- a/tests/unit/common/test_conf.py +++ b/tests/unit/common/test_conf.py @@ -21,7 +21,6 @@ import pytest from neo4j import ( - ExperimentalWarning, TrustAll, TrustCustomCAs, TrustSystemCAs, @@ -189,14 +188,6 @@ def test_pool_config_deprecated_and_new_trust_config(value_trust, "trusted_certificates": trusted_certificates}) -@pytest.mark.parametrize("config_cls", (WorkspaceConfig, SessionConfig)) -def test_bookmark_manager_is_experimental(config_cls): - bmm = object() - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - config = config_cls.consume({"bookmark_manager": bmm}) - assert config.bookmark_manager is bmm - - def test_config_consume_chain(): test_config = {} @@ -205,10 +196,9 @@ def test_config_consume_chain(): test_config.update(test_session_config) - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - consumed_pool_config, consumed_session_config = Config.consume_chain( - test_config, PoolConfig, SessionConfig - ) + consumed_pool_config, consumed_session_config = Config.consume_chain( + test_config, PoolConfig, SessionConfig + ) assert isinstance(consumed_pool_config, PoolConfig) assert isinstance(consumed_session_config, SessionConfig) diff --git a/tests/unit/sync/test_bookmark_manager.py b/tests/unit/sync/test_bookmark_manager.py index 8e0133f0..f560d003 100644 --- a/tests/unit/sync/test_bookmark_manager.py +++ b/tests/unit/sync/test_bookmark_manager.py @@ -36,8 +36,7 @@ @copy_signature(neo4j.GraphDatabase.bookmark_manager) def bookmark_manager(*args, **kwargs): - with pytest.warns(neo4j.ExperimentalWarning, match="bookmark manager"): - return neo4j.GraphDatabase.bookmark_manager(*args, **kwargs) + return neo4j.GraphDatabase.bookmark_manager(*args, **kwargs) @mark_sync_test diff --git a/tests/unit/sync/test_driver.py b/tests/unit/sync/test_driver.py index bf59fb4d..07799744 100644 --- a/tests/unit/sync/test_driver.py +++ b/tests/unit/sync/test_driver.py @@ -62,25 +62,6 @@ ) -@contextmanager -def assert_warns_execute_query_experimental(): - with pytest.warns( - ExperimentalWarning, - match=r"^Driver\.execute_query is experimental\." - ): - yield - - -@contextmanager -def assert_warns_execute_query_bmm_experimental(): - with pytest.warns( - ExperimentalWarning, - match=r"^Driver\.query_bookmark_manager is experimental\." - ): - yield - - - @pytest.mark.parametrize("protocol", ("bolt://", "bolt+s://", "bolt+ssc://")) @pytest.mark.parametrize("host", ("localhost", "127.0.0.1", "[::1]", "[0:0:0:0:0:0:0:1]")) @@ -315,16 +296,14 @@ def test_get_server_info_parameters_are_experimental( @mark_sync_test def test_with_builtin_bookmark_manager(mocker) -> None: - with pytest.warns(ExperimentalWarning, match="bookmark manager"): - bmm = GraphDatabase.bookmark_manager() + bmm = GraphDatabase.bookmark_manager() # could be one line, but want to make sure the type checker assigns # bmm whatever type AsyncGraphDatabase.bookmark_manager() returns session_cls_mock = mocker.patch("neo4j._sync.driver.Session", autospec=True) driver = GraphDatabase.driver("bolt://localhost") with driver as driver: - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - _ = driver.session(bookmark_manager=bmm) + _ = driver.session(bookmark_manager=bmm) session_cls_mock.assert_called_once() assert session_cls_mock.call_args[0][1].bookmark_manager is bmm @@ -351,8 +330,7 @@ def forget(self, databases: t.Iterable[str]) -> None: autospec=True) driver = GraphDatabase.driver("bolt://localhost") with driver as driver: - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - _ = driver.session(bookmark_manager=bmm) + _ = driver.session(bookmark_manager=bmm) session_cls_mock.assert_called_once() assert session_cls_mock.call_args[0][1].bookmark_manager is bmm @@ -379,8 +357,7 @@ def forget(self, databases: t.Iterable[str]) -> None: autospec=True) driver = GraphDatabase.driver("bolt://localhost") with driver as driver: - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - _ = driver.session(bookmark_manager=bmm) + _ = driver.session(bookmark_manager=bmm) session_cls_mock.assert_called_once() assert session_cls_mock.call_args[0][1].bookmark_manager is bmm @@ -407,8 +384,7 @@ def forget(self, databases: t.Iterable[str]) -> None: autospec=True) driver = GraphDatabase.driver("bolt://localhost") with driver as driver: - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - _ = driver.session(bookmark_manager=bmm) + _ = driver.session(bookmark_manager=bmm) session_cls_mock.assert_called_once() assert session_cls_mock.call_args[0][1].bookmark_manager is bmm @@ -435,8 +411,7 @@ def forget(self, databases: t.Iterable[str]) -> None: autospec=True) driver = GraphDatabase.driver("bolt://localhost") with driver as driver: - with pytest.warns(ExperimentalWarning, match="bookmark_manager"): - _ = driver.session(bookmark_manager=bmm) + _ = driver.session(bookmark_manager=bmm) session_cls_mock.assert_called_once() assert session_cls_mock.call_args[0][1].bookmark_manager is bmm @@ -660,11 +635,10 @@ def test_execute_query_query( session_cls_mock = mocker.patch("neo4j._sync.driver.Session", autospec=True) with driver as driver: - with assert_warns_execute_query_experimental(): - if positional: - res = driver.execute_query(query) - else: - res = driver.execute_query(query_=query) + if positional: + res = driver.execute_query(query) + else: + res = driver.execute_query(query_=query) session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value @@ -690,16 +664,14 @@ def test_execute_query_parameters( session_cls_mock = mocker.patch("neo4j._sync.driver.Session", autospec=True) with driver as driver: - with assert_warns_execute_query_experimental(): - if parameters is Ellipsis: - parameters = None - res = driver.execute_query("") + if parameters is Ellipsis: + parameters = None + res = driver.execute_query("") + else: + if positional: + res = driver.execute_query("", parameters) else: - if positional: - res = driver.execute_query("", parameters) - else: - res = driver.execute_query("", - parameters_=parameters) + res = driver.execute_query("", parameters_=parameters) session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value @@ -723,11 +695,10 @@ def test_execute_query_keyword_parameters( session_cls_mock = mocker.patch("neo4j._sync.driver.Session", autospec=True) with driver as driver: - with assert_warns_execute_query_experimental(): - if parameters is None: - res = driver.execute_query("") - else: - res = driver.execute_query("", **parameters) + if parameters is None: + res = driver.execute_query("") + else: + res = driver.execute_query("", **parameters) session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value @@ -750,8 +721,7 @@ def test_reserved_query_keyword_parameters( mocker.patch("neo4j._sync.driver.Session", autospec=True) with driver as driver: with pytest.raises(ValueError) as exc: - with assert_warns_execute_query_experimental(): - driver.execute_query("", **parameters) + driver.execute_query("", **parameters) exc.match("reserved") exc.match(", ".join(f"'{k}'" for k in parameters)) @@ -798,15 +768,14 @@ def test_execute_query_parameter_precedence( session_cls_mock = mocker.patch("neo4j._sync.driver.Session", autospec=True) with driver as driver: - with assert_warns_execute_query_experimental(): - if params is None: - res = driver.execute_query("", **kw_params) + if params is None: + res = driver.execute_query("", **kw_params) + else: + if positional: + res = driver.execute_query("", params, **kw_params) else: - if positional: - res = driver.execute_query("", params, **kw_params) - else: - res = driver.execute_query("", parameters_=params, - **kw_params) + res = driver.execute_query("", parameters_=params, + **kw_params) session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value @@ -825,8 +794,8 @@ def test_execute_query_parameter_precedence( (None, "execute_write"), ("r", "execute_read"), ("w", "execute_write"), - (neo4j.RoutingControl.READERS, "execute_read"), - (neo4j.RoutingControl.WRITERS, "execute_write"), + (neo4j.RoutingControl.READ, "execute_read"), + (neo4j.RoutingControl.WRITE, "execute_write"), ) ) @pytest.mark.parametrize("positional", (True, False)) @@ -839,14 +808,13 @@ def test_execute_query_routing_control( session_cls_mock = mocker.patch("neo4j._sync.driver.Session", autospec=True) with driver as driver: - with assert_warns_execute_query_experimental(): - if routing_mode is None: - res = driver.execute_query("") + if routing_mode is None: + res = driver.execute_query("") + else: + if positional: + res = driver.execute_query("", None, routing_mode) else: - if positional: - res = driver.execute_query("", None, routing_mode) - else: - res = driver.execute_query("", routing_=routing_mode) + res = driver.execute_query("", routing_=routing_mode) session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value @@ -871,15 +839,14 @@ def test_execute_query_database( session_cls_mock = mocker.patch("neo4j._sync.driver.Session", autospec=True) with driver as driver: - with assert_warns_execute_query_experimental(): - if database is Ellipsis: - database = None - driver.execute_query("") + if database is Ellipsis: + database = None + driver.execute_query("") + else: + if positional: + driver.execute_query("", None, "w", database) else: - if positional: - driver.execute_query("", None, "w", database) - else: - driver.execute_query("", database_=database) + driver.execute_query("", database_=database) session_cls_mock.assert_called_once() session_config = session_cls_mock.call_args.args[1] @@ -896,19 +863,18 @@ def test_execute_query_impersonated_user( session_cls_mock = mocker.patch("neo4j._sync.driver.Session", autospec=True) with driver as driver: - with assert_warns_execute_query_experimental(): - if impersonated_user is Ellipsis: - impersonated_user = None - driver.execute_query("") + if impersonated_user is Ellipsis: + impersonated_user = None + driver.execute_query("") + else: + if positional: + driver.execute_query( + "", None, "w", None, impersonated_user + ) else: - if positional: - driver.execute_query( - "", None, "w", None, impersonated_user - ) - else: - driver.execute_query( - "", impersonated_user_=impersonated_user - ) + driver.execute_query( + "", impersonated_user_=impersonated_user + ) session_cls_mock.assert_called_once() session_config = session_cls_mock.call_args.args[1] @@ -926,20 +892,18 @@ def test_execute_query_bookmark_manager( session_cls_mock = mocker.patch("neo4j._sync.driver.Session", autospec=True) with driver as driver: - with assert_warns_execute_query_experimental(): - if bookmark_manager is Ellipsis: - with assert_warns_execute_query_bmm_experimental(): - bookmark_manager = driver.query_bookmark_manager - driver.execute_query("") + if bookmark_manager is Ellipsis: + bookmark_manager = driver.execute_query_bookmark_manager + driver.execute_query("") + else: + if positional: + driver.execute_query( + "", None, "w", None, None, bookmark_manager + ) else: - if positional: - driver.execute_query( - "", None, "w", None, None, bookmark_manager - ) - else: - driver.execute_query( - "", bookmark_manager_=bookmark_manager - ) + driver.execute_query( + "", bookmark_manager_=bookmark_manager + ) session_cls_mock.assert_called_once() session_config = session_cls_mock.call_args.args[1] @@ -958,24 +922,22 @@ def test_execute_query_result_transformer( autospec=True) res: t.Any with driver as driver: - with assert_warns_execute_query_experimental(): - if result_transformer is Ellipsis: - result_transformer = Result.to_eager_result - res_default: neo4j.EagerResult = driver.execute_query("") - res = res_default + if result_transformer is Ellipsis: + result_transformer = Result.to_eager_result + res_default: neo4j.EagerResult = driver.execute_query("") + res = res_default + else: + res_custom: SomeClass + if positional: + bmm = driver.execute_query_bookmark_manager + res_custom = driver.execute_query( + "", None, "w", None, None, bmm, result_transformer + ) else: - res_custom: SomeClass - if positional: - with assert_warns_execute_query_bmm_experimental(): - bmm = driver.query_bookmark_manager - res_custom = driver.execute_query( - "", None, "w", None, None, bmm, result_transformer - ) - else: - res_custom = driver.execute_query( - "", result_transformer_=result_transformer - ) - res = res_custom + res_custom = driver.execute_query( + "", result_transformer_=result_transformer + ) + res = res_custom session_cls_mock.assert_called_once() session_mock = session_cls_mock.return_value diff --git a/tests/unit/sync/work/test_result.py b/tests/unit/sync/work/test_result.py index 40afcbd7..9899bd87 100644 --- a/tests/unit/sync/work/test_result.py +++ b/tests/unit/sync/work/test_result.py @@ -28,7 +28,6 @@ from neo4j import ( Address, EagerResult, - ExperimentalWarning, Record, Result, ResultSummary, @@ -56,15 +55,6 @@ from ...._async_compat import mark_sync_test -@contextmanager -def assert_warns_to_eager_result_experimental(): - with pytest.warns( - ExperimentalWarning, - match=r"^Result\.to_eager_result is experimental\." - ): - yield - - class Records: def __init__(self, fields, records): self.fields = tuple(fields) @@ -720,8 +710,7 @@ def test_to_eager_result(records): connection = ConnectionStub(records=records, summary_meta=summary) result = Result(connection, 1, noop, noop) result._run("CYPHER", {}, None, None, "r", None, None, None) - with assert_warns_to_eager_result_experimental(): - eager_result = result.to_eager_result() + eager_result = result.to_eager_result() assert isinstance(eager_result, EagerResult) From 1d9fc74c9222154dce02cb31d29f481cc671d107 Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Thu, 13 Apr 2023 12:21:55 +0200 Subject: [PATCH 2/2] Fix merge Warning checks in the TestKit backend were not merged properly. --- testkitbackend/_async/requests.py | 5 ----- testkitbackend/_sync/requests.py | 5 ----- 2 files changed, 10 deletions(-) diff --git a/testkitbackend/_async/requests.py b/testkitbackend/_async/requests.py index 03bfe2e9..af2c4da1 100644 --- a/testkitbackend/_async/requests.py +++ b/testkitbackend/_async/requests.py @@ -544,11 +544,6 @@ async def NewSession(backend, data): config["bookmark_manager"] = backend.bookmark_managers[ data["bookmarkManagerId"] ] - expected_warnings.append(( - neo4j.ExperimentalWarning, - "The 'bookmark_manager' config key is experimental. It might be " - "changed or removed any time even without prior notice." - )) for (conf_name, data_name) in ( ("fetch_size", "fetchSize"), ("impersonated_user", "impersonatedUser"), diff --git a/testkitbackend/_sync/requests.py b/testkitbackend/_sync/requests.py index fc06c31c..f1ad1859 100644 --- a/testkitbackend/_sync/requests.py +++ b/testkitbackend/_sync/requests.py @@ -544,11 +544,6 @@ def NewSession(backend, data): config["bookmark_manager"] = backend.bookmark_managers[ data["bookmarkManagerId"] ] - expected_warnings.append(( - neo4j.ExperimentalWarning, - "The 'bookmark_manager' config key is experimental. It might be " - "changed or removed any time even without prior notice." - )) for (conf_name, data_name) in ( ("fetch_size", "fetchSize"), ("impersonated_user", "impersonatedUser"),