diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fd470009..10b3e2d5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -95,6 +95,8 @@ See also https://github.com/neo4j/neo4j-python-driver/wiki for a full changelog. - Calling `driver.close()` again is now a no-op. - No longer implicitly closing drivers and sessions in `__del__()` (finalizer/destructor). Make sure to call `.close()` on them explicitly or use them in a `with` statement. +- Make `Summary.summary_notifications` a `tuple` instead of a `list` and type it with `Sequence` to signify that it + should be treated as immutable. ## Version 5.28 diff --git a/src/neo4j/_work/summary.py b/src/neo4j/_work/summary.py index 21002cfae..0445badc4 100644 --- a/src/neo4j/_work/summary.py +++ b/src/neo4j/_work/summary.py @@ -31,6 +31,8 @@ if t.TYPE_CHECKING: + from collections.abc import Sequence + import typing_extensions as te from .._addressing import Address @@ -93,7 +95,7 @@ class ResultSummary: _notifications_set: bool = False # cache for property `summary_notifications` - _summary_notifications: list[SummaryNotification] + _summary_notifications: tuple[SummaryNotification, ...] # cache for property `summary_notifications` _gql_status_objects: tuple[GqlStatusObject, ...] @@ -202,9 +204,8 @@ def _set_notifications(self) -> None: self.notifications = None - # TODO: 6.0 - return a tuple for immutability (annotate with Sequence) @property - def summary_notifications(self) -> list[SummaryNotification]: + def summary_notifications(self) -> Sequence[SummaryNotification]: """ The same as ``notifications`` but in a parsed, structured form. @@ -220,11 +221,11 @@ def summary_notifications(self) -> list[SummaryNotification]: raw_notifications = self.notifications if not isinstance(raw_notifications, list): - self._summary_notifications = [] + self._summary_notifications = () return self._summary_notifications - self._summary_notifications = [ + self._summary_notifications = tuple( SummaryNotification._from_metadata(n) for n in raw_notifications - ] + ) return self._summary_notifications @property diff --git a/tests/unit/common/work/test_summary.py b/tests/unit/common/work/test_summary.py index 73e8c005b..229d71c2e 100644 --- a/tests/unit/common/work/test_summary.py +++ b/tests/unit/common/work/test_summary.py @@ -21,6 +21,8 @@ if t.TYPE_CHECKING: + from collections.abc import Sequence + import typing_extensions as te _T = t.TypeVar("_T") @@ -759,11 +761,11 @@ def test_summary_summary_notifications( kwargs["metadata"]["notifications"] = summary_in summary = ResultSummary(*args, **kwargs) - summary_out: list[SummaryNotification] = summary.summary_notifications + summary_out: Sequence[SummaryNotification] = summary.summary_notifications - assert isinstance(summary_out, list) + assert isinstance(summary_out, tuple) if summary_in is None: - assert summary_out == [] + assert summary_out == () return assert summary_in is not None @@ -1469,12 +1471,12 @@ def test_no_notification_from_status(raw_status, summary_args_kwargs) -> None: summary = ResultSummary(*args, **kwargs) notifications: list[dict] | None = summary.notifications - summary_notifications: list[SummaryNotification] = ( + summary_notifications: Sequence[SummaryNotification] = ( summary.summary_notifications ) assert notifications is None - assert summary_notifications == [] + assert summary_notifications == () @pytest.mark.parametrize( @@ -1745,7 +1747,7 @@ def test_no_notification_from_wrong_type_status( summary_notifications = summary.summary_notifications assert notifications is None - assert summary_notifications == [] + assert summary_notifications == () def _get_from_dict( @@ -1939,7 +1941,7 @@ def test_no_notification_from_status_without_neo4j_code( summary_notifications = summary.summary_notifications assert notifications is None - assert summary_notifications == [] + assert summary_notifications == () @pytest.mark.parametrize( @@ -1977,9 +1979,9 @@ def test_notification_from_incomplete_status( assert notifications == [raw_notification] - assert summary_notifications == [ - SummaryNotification._from_metadata(raw_notification) - ] + assert summary_notifications == ( + SummaryNotification._from_metadata(raw_notification), + ) @pytest.mark.parametrize( @@ -2027,9 +2029,9 @@ def test_notification_from_unexpected_status( assert notifications == [raw_notification] - assert summary_notifications == [ - SummaryNotification._from_metadata(raw_notification) - ] + assert summary_notifications == ( + SummaryNotification._from_metadata(raw_notification), + ) def _test_status():