Skip to content

Commit

Permalink
Mature execute_query API (#911)
Browse files Browse the repository at this point in the history
 * 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()`
  • Loading branch information
robsdedude committed Apr 13, 2023
1 parent a2d7d33 commit a6d9050
Show file tree
Hide file tree
Showing 29 changed files with 259 additions and 498 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 8 additions & 8 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ Closing a driver will immediately shut down all connections in the pool.
verify_connectivity, get_server_info, verify_authentication,
supports_session_auth, supports_multi_db

.. 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.

Expand Down Expand Up @@ -194,9 +194,9 @@ Closing a driver will immediately shut down all connections in the pool.
bookmark_manager=bookmark_manager_,
auth=auth_,
) 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::
Expand All @@ -211,7 +211,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
Expand All @@ -232,7 +232,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,
Expand Down Expand Up @@ -380,7 +380,8 @@ Closing a driver will immediately shut down all connections in the pool.
.. versionadded:: 5.5

.. versionchanged:: 5.8
Added the ``auth_`` parameter.
* Added the ``auth_`` parameter.
* Stabilized from experimental.


.. _driver-configuration-ref:
Expand Down Expand Up @@ -1022,8 +1023,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-auth-ref:
Expand Down
23 changes: 8 additions & 15 deletions docs/source/async_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ Closing a driver will immediately shut down all connections in the pool.
verify_connectivity, get_server_info, verify_authentication,
supports_session_auth, supports_multi_db

.. 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.
Expand Down Expand Up @@ -184,9 +184,9 @@ Closing a driver will immediately shut down all connections in the pool.
bookmark_manager=bookmark_manager_,
auth=auth_,
) 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::
Expand All @@ -201,7 +201,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
Expand All @@ -222,7 +222,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,
age=15,
Expand Down Expand Up @@ -360,17 +360,11 @@ 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
Added the ``auth_`` parameter.
* Added the ``auth_`` parameter.
* Stabilized from experimental.


.. _async-driver-configuration-ref:
Expand Down Expand Up @@ -659,8 +653,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



Expand Down
15 changes: 8 additions & 7 deletions src/neo4j/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/neo4j/_async/auth_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# work around for https://github.com/sphinx-doc/sphinx/pull/10880
# make sure TAuth is resolved in the docs, else they're pretty useless


import time
import typing as t
from logging import getLogger
Expand Down
73 changes: 21 additions & 52 deletions src/neo4j/_async/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@
)
from .._meta import (
deprecation_warn,
experimental,
experimental_warn,
ExperimentalWarning,
preview,
preview_warn,
PreviewWarning,
Expand Down Expand Up @@ -293,10 +291,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,
Expand Down Expand Up @@ -357,9 +351,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
Expand All @@ -373,6 +364,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,
Expand Down Expand Up @@ -480,12 +473,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
Expand Down Expand Up @@ -579,7 +567,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[
Expand All @@ -598,7 +586,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[
Expand All @@ -612,15 +600,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[
Expand Down Expand Up @@ -661,9 +645,9 @@ async def work(tx):
bookmark_manager=bookmark_manager_,
auth=auth_,
) 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::
Expand All @@ -678,7 +662,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
Expand All @@ -699,7 +683,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,
age=15,
Expand Down Expand Up @@ -837,17 +821,11 @@ 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.
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
Added the ``auth_`` parameter.
* Added the ``auth_`` parameter.
* Stabilized from experimental.
"""
invalid_kwargs = [k for k in kwargs if
k[-2:-1] != "_" and k[-1:] == "_"]
Expand All @@ -866,9 +844,6 @@ async def example(driver: neo4j.AsyncDriver) -> neo4j.Record::
assert bookmark_manager_ is not _default

with warnings.catch_warnings():
warnings.filterwarnings("ignore",
message=r".*\bbookmark_manager\b.*",
category=ExperimentalWarning)
warnings.filterwarnings("ignore",
message=r"^User switching\b.*",
category=PreviewWarning)
Expand All @@ -877,9 +852,9 @@ async def example(driver: neo4j.AsyncDriver) -> neo4j.Record::
bookmark_manager=bookmark_manager_,
auth=auth_)
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"
Expand All @@ -889,11 +864,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
Expand All @@ -912,10 +883,12 @@ async def example(driver: neo4j.AsyncDriver) -> None:
# (i.e., can read what was written by <QUERY 2>)
await driver.execute_query("<QUERY 3>")
**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

Expand Down Expand Up @@ -1212,11 +1185,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)


Expand Down
Loading

0 comments on commit a6d9050

Please sign in to comment.