2121
2222from ..._async_compat .util import AsyncUtil
2323from ...data import DataDehydrator
24+ from ...exceptions import ResultNotSingleError
2425from ...work import ResultSummary
2526from ..io import ConnectionErrorHandler
2627
@@ -37,6 +38,7 @@ def __init__(self, connection, hydrant, fetch_size, on_closed,
3738 self ._hydrant = hydrant
3839 self ._on_closed = on_closed
3940 self ._metadata = None
41+ self ._keys = None
4042 self ._record_buffer = deque ()
4143 self ._summary = None
4244 self ._bookmark = None
@@ -179,7 +181,7 @@ def on_success(summary_metadata):
179181 async def __aiter__ (self ):
180182 """Iterator returning Records.
181183 :returns: Record, it is an immutable ordered collection of key-value pairs.
182- :rtype: :class:`neo4j.Record `
184+ :rtype: :class:`neo4j.AsyncRecord `
183185 """
184186 while self ._record_buffer or self ._attached :
185187 if self ._record_buffer :
@@ -211,6 +213,8 @@ async def _buffer(self, n=None):
211213 Might ent up with fewer records in the buffer if there are not enough
212214 records available.
213215 """
216+ if n is not None and len (self ._record_buffer ) >= n :
217+ return
214218 record_buffer = deque ()
215219 async for record in self :
216220 record_buffer .append (record )
@@ -304,24 +308,21 @@ async def single(self):
304308 A warning is generated if more than one record is available but
305309 the first of these is still returned.
306310
307- :returns: the next :class:`neo4j.Record` or :const:`None` if none remain
308- :warns: if more than one record is available
311+ :returns: the next :class:`neo4j.AsyncRecord`.
312+ :raises: ResultNotSingleError if not exactly one record is available.
309313 """
310- # TODO in 5.0 replace with this code that raises an error if there's not
311- # exactly one record in the left result stream.
312- # self._buffer(2).
313- # if len(self._record_buffer) != 1:
314- # raise SomeError("Expected exactly 1 record, found %i"
315- # % len(self._record_buffer))
316- # return self._record_buffer.popleft()
317- # TODO: exhausts the result with self.consume if there are more records.
318- records = await AsyncUtil .list (self )
319- size = len (records )
320- if size == 0 :
321- return None
322- if size != 1 :
323- warn ("Expected a result with a single record, but this result contains %d" % size )
324- return records [0 ]
314+ await self ._buffer (2 )
315+ if not self ._record_buffer :
316+ raise ResultNotSingleError (
317+ "No records found. "
318+ "Make sure your query returns exactly one record."
319+ )
320+ elif len (self ._record_buffer ) > 1 :
321+ raise ResultNotSingleError (
322+ "More than one record found. "
323+ "Make sure your query returns exactly one record."
324+ )
325+ return self ._record_buffer .popleft ()
325326
326327 async def peek (self ):
327328 """Obtain the next record from this result without consuming it.
@@ -347,7 +348,7 @@ async def graph(self):
347348 async def value (self , key = 0 , default = None ):
348349 """Helper function that return the remainder of the result as a list of values.
349350
350- See :class:`neo4j.Record .value`
351+ See :class:`neo4j.AsyncRecord .value`
351352
352353 :param key: field to return for each remaining record. Obtain a single value from the record by index or key.
353354 :param default: default value, used if the index of key is unavailable
@@ -359,7 +360,7 @@ async def value(self, key=0, default=None):
359360 async def values (self , * keys ):
360361 """Helper function that return the remainder of the result as a list of values lists.
361362
362- See :class:`neo4j.Record .values`
363+ See :class:`neo4j.AsyncRecord .values`
363364
364365 :param keys: fields to return for each remaining record. Optionally filtering to include only certain values by index or key.
365366 :returns: list of values lists
@@ -370,7 +371,7 @@ async def values(self, *keys):
370371 async def data (self , * keys ):
371372 """Helper function that return the remainder of the result as a list of dictionaries.
372373
373- See :class:`neo4j.Record .data`
374+ See :class:`neo4j.AsyncRecord .data`
374375
375376 :param keys: fields to return for each remaining record. Optionally filtering to include only certain values by index or key.
376377 :returns: list of dictionaries
0 commit comments