From 414a0c82b162a976e1da34b46d80503be28003c9 Mon Sep 17 00:00:00 2001 From: Robsdedude Date: Fri, 14 Jun 2024 13:08:07 +0200 Subject: [PATCH] Make usage of raw bookmarks easier (Async)Neo4jBookmarkManager's `initial_bookmarks` parameter, as well as `Bookmarks.from_raw_values` `values` parameter accept anything of type `Iterable[str]`. Unfortunately, `str` itself implements that type and yields the characters of the string. That most certainly not what the user intended. In an ideal world, we could tell the type checker to only accept `Iterable[str]` when *not* of type `str`. See also https://github.com/python/typing/issues/256. To help users out, we now explicitly check for `isinstance(input, str)` and turn such inputs into an iterable with the input string as the only element. --- src/neo4j/_async/bookmark_manager.py | 11 +++++++---- src/neo4j/_sync/bookmark_manager.py | 11 +++++++---- src/neo4j/api.py | 6 +++++- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/neo4j/_async/bookmark_manager.py b/src/neo4j/_async/bookmark_manager.py index b9a278c53..004e08479 100644 --- a/src/neo4j/_async/bookmark_manager.py +++ b/src/neo4j/_async/bookmark_manager.py @@ -51,10 +51,13 @@ def __init__( if not initial_bookmarks: self._bookmarks = set() else: - self._bookmarks = set(getattr( - initial_bookmarks, "raw_values", - t.cast(t.Iterable[str], initial_bookmarks) - )) + if not hasattr(initial_bookmarks, "raw_values"): + initial_bookmarks = Bookmarks.from_raw_values( + t.cast(t.Iterable[str], initial_bookmarks) + ) + self._bookmarks = set( + t.cast(Bookmarks, initial_bookmarks).raw_values + ) self._lock = AsyncCooperativeLock() async def update_bookmarks( diff --git a/src/neo4j/_sync/bookmark_manager.py b/src/neo4j/_sync/bookmark_manager.py index b75b74938..c2cd522a4 100644 --- a/src/neo4j/_sync/bookmark_manager.py +++ b/src/neo4j/_sync/bookmark_manager.py @@ -51,10 +51,13 @@ def __init__( if not initial_bookmarks: self._bookmarks = set() else: - self._bookmarks = set(getattr( - initial_bookmarks, "raw_values", - t.cast(t.Iterable[str], initial_bookmarks) - )) + if not hasattr(initial_bookmarks, "raw_values"): + initial_bookmarks = Bookmarks.from_raw_values( + t.cast(t.Iterable[str], initial_bookmarks) + ) + self._bookmarks = set( + t.cast(Bookmarks, initial_bookmarks).raw_values + ) self._lock = CooperativeLock() def update_bookmarks( diff --git a/src/neo4j/api.py b/src/neo4j/api.py index 4306bb984..9af802cbb 100644 --- a/src/neo4j/api.py +++ b/src/neo4j/api.py @@ -287,8 +287,12 @@ def from_raw_values(cls, values: t.Iterable[str]) -> Bookmarks: bookmarks. :param values: ASCII string values (raw bookmarks) - :type values: Iterable[str] """ + if isinstance(values, str): + # Unfortunately, str itself is an iterable of str, iterating + # over characters. Type checkers will not catch this, so we help + # the user out. + values = values, obj = cls() bookmarks = [] for value in values: