Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@ See also https://github.com/neo4j/neo4j-python-driver/wiki for a full changelog.
- `neo4j.spatial.Point` (and subclasses)
- Separate out log entries that are session-related (including transaction retries)
form sub-logger `neo4j.pool` to a new sub-logger `neo4j.session`.
- Notifications:
- Deprecate notifications and related APIs:
- `ResultSummary.notifications`
- `ResultSummary.summary_notifications`
- `neo4j.SummaryNotification`
- `neo4j.NotificationCategory`
- `neo4j.NotificationDisabledCategory`
- Stabilize GQL status objects (use this instead of notifications):
- `ResultSummary.gql_status_objects`
- `neo4j.GqlStatusObject`
- (`neo4j.exceptions.GqlError`, `neo4j.exceptions.GqlErrorClassification`)


## Version 5.28
Expand Down
90 changes: 46 additions & 44 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -687,49 +687,50 @@ See also :attr:`.GqlStatusObject.is_notification`.

``notifications_disabled_categories``
-------------------------------------
Set categories/classifications of notifications the server should not send to the client.
Disabling categories allows the server to skip analysis for those, which can speed up query execution.
Identical to :ref:`driver-notifications-disabled-classifications-ref`.

Notifications are available via :attr:`.ResultSummary.notifications` and :attr:`.ResultSummary.summary_notifications`.
Further, they are surfaced (alongside other status objects) through :attr:`.ResultSummary.gql_status_objects`:
See also :attr:`.GqlStatusObject.is_notification`.

:data:`None` will apply the server's default setting.

If specified together with :ref:`driver-notifications-disabled-classifications-ref`, the settings will be merged.

.. Note::
If configured, the server or all servers of the cluster need to support notifications filtering
(server version 5.7 and newer).
Otherwise, the driver will raise a :exc:`.ConfigurationError` as soon as it encounters a server that does not.
This alias is provided for a consistent naming with :attr:`.SummaryNotification.category`.

:Type: :data:`None`, :term:`iterable` of :class:`.NotificationDisabledCategory` and/or :class:`str`
:Default: :data:`None`

.. versionadded:: 5.7

.. seealso:: :class:`.NotificationDisabledCategory`, session config :ref:`session-notifications-disabled-categories-ref`
.. deprecated:: 6.0
This setting is deprecated in favor of :ref:`driver-notifications-disabled-classifications-ref`.
It will be removed in a future release.

.. seealso:: :class:`.NotificationDisabledCategory`, session config :ref:`session-notifications-disabled-categories-ref`, :attr:`.SummaryNotification.category`


.. _driver-notifications-disabled-classifications-ref:

``notifications_disabled_classifications``
------------------------------------------
Identical to :ref:`driver-notifications-disabled-categories-ref`.
Set classifications/categories of notifications the server should not send to the client.
Disabling classifications allows the server to skip analysis for those, which can speed up query execution.

This alias is provided for a consistent naming with :attr:`.GqlStatusObject.classification`.
Notifications are available via :attr:`.ResultSummary.notifications` and :attr:`.ResultSummary.summary_notifications`.
Further, they are surfaced (alongside other status objects) through :attr:`.ResultSummary.gql_status_objects`:
See also :attr:`.GqlStatusObject.is_notification`.

**This is a preview** (see :ref:`filter-warnings-ref`).
It might be changed without following the deprecation policy.
See also
https://github.com/neo4j/neo4j-python-driver/wiki/preview-features
:data:`None` will apply the server's default setting.

If specified together with :ref:`driver-notifications-disabled-categories-ref`, the settings will be merged.

.. Note::
If configured, the server or all servers of the cluster need to support notifications filtering
(server version 5.7 and newer).
Otherwise, the driver will raise a :exc:`.ConfigurationError` as soon as it encounters a server that does not.

:Type: :data:`None`, :term:`iterable` of :class:`.NotificationDisabledClassification` and/or :class:`str`
:Default: :data:`None`

.. versionadded:: 5.22

.. seealso:: :class:`.NotificationDisabledClassification`, session config :ref:`session-notifications-disabled-classifications-ref`
.. versionchanged:: 6.0 Stabilized from preview.

.. seealso:: :class:`.NotificationDisabledClassification`, session config :ref:`session-notifications-disabled-classifications-ref`, :attr:`.GqlStatusObject.classification`


.. _driver-warn-notification-severity-ref:
Expand Down Expand Up @@ -1186,49 +1187,50 @@ See also :attr:`.GqlStatusObject.is_notification`.

``notifications_disabled_categories``
-------------------------------------
Set categories of notifications the server should not send to the client.
Disabling categories allows the server to skip analysis for those, which can speed up query execution.

Notifications are available via :attr:`.ResultSummary.notifications` and :attr:`.ResultSummary.summary_notifications`.
Further, they are surfaced (alongside other status objects) through :attr:`.ResultSummary.gql_status_objects`:
See also :attr:`.GqlStatusObject.is_notification`.

:data:`None` will apply the driver's configuration setting (:ref:`driver-notifications-disabled-categories-ref`).
Identical to :ref:`session-notifications-disabled-classifications-ref`.

If specified together with :ref:`session-notifications-disabled-classifications-ref`, the settings will be merged.

.. Note::
If configured, the server or all servers of the cluster need to support notifications filtering
(server version 5.7 and newer).
Otherwise, the driver will raise a :exc:`.ConfigurationError` as soon as it encounters a server that does not.
This alias is provided for a consistent naming with :attr:`.SummaryNotification.category`.

:Type: :data:`None`, :term:`iterable` of :class:`.NotificationDisabledCategory` and/or :class:`str`
:Default: :data:`None`

.. versionadded:: 5.7

.. seealso:: :class:`.NotificationDisabledCategory`
.. deprecated:: 6.0
This setting is deprecated in favor of :ref:`session-notifications-disabled-classifications-ref`.
It will be removed in a future release.

.. seealso:: :class:`.NotificationDisabledCategory`, :attr:`.SummaryNotification.category`


.. _session-notifications-disabled-classifications-ref:

``notifications_disabled_classifications``
------------------------------------------
Identical to :ref:`session-notifications-disabled-categories-ref`.
Set classifications/categories of notifications the server should not send to the client.
Disabling classifications allows the server to skip analysis for those, which can speed up query execution.

This alias is provided for a consistent naming with :attr:`.GqlStatusObject.classification`.
Notifications are available via :attr:`.ResultSummary.notifications` and :attr:`.ResultSummary.summary_notifications`.
Further, they are surfaced (alongside other status objects) through :attr:`.ResultSummary.gql_status_objects`:
See also :attr:`.GqlStatusObject.is_notification`.

**This is a preview** (see :ref:`filter-warnings-ref`).
It might be changed without following the deprecation policy.
See also
https://github.com/neo4j/neo4j-python-driver/wiki/preview-features
:data:`None` will apply the driver's configuration setting (:ref:`driver-notifications-disabled-classifications-ref`).

If specified together with :ref:`session-notifications-disabled-categories-ref`, the settings will be merged.

.. Note::
If configured, the server or all servers of the cluster need to support notifications filtering
(server version 5.7 and newer).
Otherwise, the driver will raise a :exc:`.ConfigurationError` as soon as it encounters a server that does not.

:Type: :data:`None`, :term:`iterable` of :class:`.NotificationDisabledClassification` and/or :class:`str`
:Default: :data:`None`

.. versionadded:: 5.22

.. seealso:: :class:`.NotificationDisabledClassification`
.. versionchanged:: 6.0 Stabilized from preview.

.. seealso:: :class:`.NotificationDisabledClassification`, :attr:`.GqlStatusObject.classification`



Expand Down
55 changes: 33 additions & 22 deletions src/neo4j/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@


from . import _typing as _t
from ._api import ( # noqa: F401 dynamic attributes
NotificationCategory,
NotificationDisabledCategory,
NotificationDisabledClassification as _NotificationDisabledClassification,
from ._api import (
NotificationCategory as _NotificationCategory,
NotificationDisabledCategory as _NotificationDisabledCategory,
NotificationDisabledClassification,
NotificationMinimumSeverity,
NotificationSeverity,
RoutingControl,
Expand Down Expand Up @@ -59,27 +59,28 @@
)
from ._warnings import (
deprecation_warn as _deprecation_warn,
preview_warn as _preview_warn,
PreviewWarning as _PreviewWarning,
)
from ._work import ( # noqa: F401 dynamic attribute
from ._work import (
EagerResult,
GqlStatusObject as _GqlStatusObject,
NotificationClassification as _NotificationClassification,
GqlStatusObject,
NotificationClassification,
Query,
ResultSummary,
SummaryCounters,
SummaryInputPosition,
SummaryNotification,
SummaryNotification as _SummaryNotification,
unit_of_work,
)


if _t.TYPE_CHECKING:
from ._api import NotificationDisabledClassification
from ._api import (
NotificationCategory,
NotificationDisabledCategory,
)
from ._work import (
GqlStatusObject,
NotificationClassification,
SummaryNotification,
)
from ._warnings import PreviewWarning

Expand Down Expand Up @@ -164,18 +165,28 @@


def __getattr__(name) -> _t.Any:
# TODO: 6.0 - remove this
if name in {
"NotificationClassification",
"GqlStatusObject",
"NotificationDisabledClassification",
}:
_preview_warn(
f"{name} is part of GQLSTATUS support, "
"which is a preview feature.",
# TODO: 7.0 - consider removing this
if name == "SummaryNotification":
_deprecation_warn(
"SummaryNotification and related APIs are deprecated. "
"Use GqlStatusObjects and related APIs instead.",
stack_level=2,
)
return _SummaryNotification
if name == "NotificationCategory":
_deprecation_warn(
"NotificationCategory is deprecated. "
"Use NotificationClassification instead.",
stack_level=2,
)
return _NotificationCategory
if name == "NotificationDisabledCategory":
_deprecation_warn(
"NotificationDisabledCategory is deprecated. "
"Use NotificationDisabledClassification instead.",
stack_level=2,
)
return globals()[f"_{name}"]
return _NotificationDisabledCategory
# TODO: 7.0 - remove this
if name == "PreviewWarning":
_deprecation_warn(
Expand Down
16 changes: 8 additions & 8 deletions src/neo4j/_async/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,10 @@ def driver(
config["encrypted"] = True
config["trusted_certificates"] = TrustAll()

if "notifications_disabled_classifications" in config:
preview_warn(
"notifications_disabled_classifications "
"is a preview feature.",
if "notifications_disabled_categories" in config:
deprecation_warn(
"notifications_disabled_categories is deprecated, "
"use notifications_disabled_classifications instead.",
stack_level=2,
)
_normalize_notifications_config(config, driver_level=True)
Expand Down Expand Up @@ -578,10 +578,10 @@ def session(self, **config) -> AsyncSession:
config.pop("warn_notification_severity", None)

self._check_state()
if "notifications_disabled_classifications" in config:
preview_warn(
"notifications_disabled_classifications "
"is a preview feature.",
if "notifications_disabled_categories" in config:
deprecation_warn(
"notifications_disabled_categories is deprecated, "
"use notifications_disabled_classifications instead.",
stack_level=2,
)
session_config = self._read_session_config(config)
Expand Down
19 changes: 13 additions & 6 deletions src/neo4j/_async/work/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

from ... import _typing as t
from ..._api import (
NotificationCategory,
NotificationClassification,
NotificationMinimumSeverity,
NotificationSeverity,
)
Expand Down Expand Up @@ -325,21 +325,28 @@ def _handle_warnings(self) -> None:

summary = self._obtain_summary()
query = self._metadata.get("query")
for notification in summary.summary_notifications:
for notification in (
gql_status_object
for gql_status_object in summary.gql_status_objects
if gql_status_object.is_notification
):
log_call = notification_log.debug
if notification.severity_level == NotificationSeverity.INFORMATION:
if notification.severity == NotificationSeverity.INFORMATION:
log_call = notification_log.info
elif notification.severity_level == NotificationSeverity.WARNING:
elif notification.severity == NotificationSeverity.WARNING:
log_call = notification_log.warning
log_call(
"Received notification from DBMS server: %s",
NotificationPrinter(notification, query, one_line=True),
)

if notification.severity_level not in sev_filter:
if notification.severity not in sev_filter:
continue
warning_cls: type[Warning] = Neo4jWarning
if notification.category == NotificationCategory.DEPRECATION:
if (
notification.classification
== NotificationClassification.DEPRECATION
):
warning_cls = Neo4jDeprecationWarning
creation_frame = self._creation_frame
if creation_frame is False:
Expand Down
14 changes: 7 additions & 7 deletions src/neo4j/_debug/_notification_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@


if t.TYPE_CHECKING:
from .._work import SummaryNotification
from .._work import GqlStatusObject


class NotificationPrinter:
notification: SummaryNotification
notification: GqlStatusObject
query: str | None

def __init__(
self,
notification: SummaryNotification,
notification: GqlStatusObject,
query: str | None = None,
one_line: bool = False,
) -> None:
Expand All @@ -39,13 +39,13 @@ def __init__(

def __str__(self):
if self.query is None:
return str(self.notification)
return repr(self.notification)
if self._one_line:
return f"{self.notification} for query: {self.query!r}"
return f"{self.notification!r} for query: {self.query!r}"
pos = self.notification.position
if pos is None:
return f"{self.notification} for query:\n{self.query}"
s = f"{self.notification} for query:\n"
return f"{self.notification!r} for query:\n{self.query}"
s = f"{self.notification!r} for query:\n"
query_lines = self.query.splitlines()
if pos.line <= 0 or pos.line > len(query_lines) or pos.column <= 0:
return s + self.query
Expand Down
16 changes: 8 additions & 8 deletions src/neo4j/_sync/driver.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading