Skip to content

reintroduced helper functions for the Record object and updated docum… #437

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 3, 2020
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
15 changes: 10 additions & 5 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,11 @@ A :class:`neo4j.Result` is attached to an active connection, through a :class:`n

**This is experimental.**

.. automethod:: value

.. automethod:: values

.. automethod:: data

See https://neo4j.com/docs/driver-manual/current/cypher-workflow/#driver-type-mapping for more about type mapping.

Expand Down Expand Up @@ -698,22 +703,22 @@ Record
Derive a sub-record based on a start and end index.
All keys and values within those bounds will be copied across in the same order as in the original record.

.. automethod:: keys

.. describe:: record[key]

Obtain a value from the record by key.
This will raise a :exc:`KeyError` if the specified key does not exist.

.. automethod:: get(key, default=None)

.. automethod:: value(key=0, default=None)

.. automethod:: index(key)

.. automethod:: keys
.. automethod:: items

.. automethod:: values
.. automethod:: value(key=0, default=None)

.. automethod:: items
.. automethod:: values

.. automethod:: data

Expand Down
21 changes: 12 additions & 9 deletions neo4j/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ def get(self, key, default=None):
""" Obtain a value from the record by key, returning a default
value if the key does not exist.

:param key:
:param default:
:return:
:param key: a key
:param default: default value
:return: a value
"""
try:
index = self.__keys.index(str(key))
Expand All @@ -126,8 +126,9 @@ def get(self, key, default=None):
def index(self, key):
""" Return the index of the given item.

:param key:
:return:
:param key: a key
:return: index
:rtype: int
"""
if isinstance(key, int):
if 0 <= key < len(self.__keys):
Expand All @@ -146,9 +147,9 @@ def value(self, key=0, default=None):
index or key is specified, the first value is returned. If the
specified item does not exist, the default value is returned.

:param key:
:param default:
:return:
:param key: an index or key
:param default: default value
:return: a single value
"""
try:
index = self.index(key)
Expand All @@ -171,6 +172,7 @@ def values(self, *keys):
:param keys: indexes or keys of the items to include; if none
are provided, all values will be included
:return: list of values
:rtype: list
"""
if keys:
d = []
Expand All @@ -187,7 +189,8 @@ def values(self, *keys):
def items(self, *keys):
""" Return the fields of the record as a list of key and value tuples

:return:
:return: a list of value tuples
:rtype: list
"""
if keys:
d = []
Expand Down
68 changes: 37 additions & 31 deletions neo4j/work/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ def keys(self):
"""The keys for the records in this result.

:returns: tuple of key names
:rtype: tuple
"""
return self._keys

Expand All @@ -249,7 +250,7 @@ def single(self):
A warning is generated if more than one record is available but
the first of these is still returned.

:returns: the next :class:`.Record` or :const:`None` if none remain
:returns: the next :class:`neo4j.Record` or :const:`None` if none remain
:warns: if more than one record is available
"""
records = list(self) # TODO: exhausts the result with self.consume if there are more records.
Expand Down Expand Up @@ -277,42 +278,47 @@ def peek(self):

return None

# See Record class for available methods.

# NOT IN THE API

def graph(self):
"""Return a Graph instance containing all the graph objects
"""Return a :class:`neo4j.graph.Graph` instance containing all the graph objects
in the result. After calling this method, the result becomes
detached, buffering all remaining records.

:returns: result graph
:returns: a result graph
:rtype: :class:`neo4j.graph.Graph`
"""
self._buffer_all()
return self._hydrant.graph

# def value(self, item=0, default=None):
# """Return the remainder of the result as a list of values.
#
# :param item: field to return for each remaining record
# :param default: default value, used if the index of key is unavailable
# :returns: list of individual values
# """
# return [record.value(item, default) for record in self._records()]

# def values(self, *items):
# """Return the remainder of the result as a list of tuples.
#
# :param items: fields to return for each remaining record
# :returns: list of value tuples
# """
# return [record.values(*items) for record in self._records()]

# def data(self, *items):
# """Return the remainder of the result as a list of dictionaries.
#
# :param items: fields to return for each remaining record
# :returns: list of dictionaries
# """
# return [record.data(*items) for record in self]
def value(self, key=0, default=None):
"""Helper function that return the remainder of the result as a list of values.

See :class:`neo4j.Record.value`

:param key: field to return for each remaining record. Obtain a single value from the record by index or key.
:param default: default value, used if the index of key is unavailable
:returns: list of individual values
:rtype: list
"""
return [record.value(key, default) for record in self]

def values(self, *keys):
"""Helper function that return the remainder of the result as a list of values lists.

See :class:`neo4j.Record.values`

:param keys: fields to return for each remaining record. Optionally filtering to include only certain values by index or key.
:returns: list of values lists
:rtype: list
"""
return [record.values(*keys) for record in self]

def data(self, *keys):
"""Helper function that return the remainder of the result as a list of dictionaries.

See :class:`neo4j.Record.data`

:param keys: fields to return for each remaining record. Optionally filtering to include only certain values by index or key.
:returns: list of dictionaries
:rtype: list
"""
return [record.data(*keys) for record in self]
18 changes: 18 additions & 0 deletions tests/integration/test_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,21 @@ def test_single_indexed_values(session):
def test_single_keyed_values(session):
result = session.run("RETURN 1 AS x, 2 AS y, 3 AS z")
assert result.single().values("z", "x") == [3, 1]


def test_result_with_helper_function_value(session):

def f(tx):
result = tx.run("UNWIND range(1, 3) AS n RETURN n")
assert result.value(0) == [1, 2, 3]

session.read_transaction(f)


def test_result_with_helper_function_values(session):

def f(tx):
result = tx.run("UNWIND range(1, 3) AS n RETURN n, 0")
assert result.values(0, 1) == [[1, 0], [2, 0], [3, 0]]

session.read_transaction(f)
17 changes: 17 additions & 0 deletions tests/integration/test_result_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,37 @@ def test_data_with_one_key_and_no_records(session):
assert data == []


def test_data_with_one_key_and_no_records_with_helper_function(session):
result = session.run("UNWIND range(1, 0) AS n RETURN n")
assert result.data() == []


def test_multiple_data(session):
result = session.run("UNWIND range(1, 3) AS n "
"RETURN 1 * n AS x, 2 * n AS y, 3 * n AS z")
data = [record.data() for record in result]
assert data == [{"x": 1, "y": 2, "z": 3}, {"x": 2, "y": 4, "z": 6}, {"x": 3, "y": 6, "z": 9}]


def test_multiple_data_with_helper_function(session):
result = session.run("UNWIND range(1, 3) AS n "
"RETURN 1 * n AS x, 2 * n AS y, 3 * n AS z")
assert result.data() == [{"x": 1, "y": 2, "z": 3}, {"x": 2, "y": 4, "z": 6}, {"x": 3, "y": 6, "z": 9}]


def test_multiple_indexed_data(session):
result = session.run("UNWIND range(1, 3) AS n "
"RETURN 1 * n AS x, 2 * n AS y, 3 * n AS z")
data = [record.data(2, 0) for record in result]
assert data == [{"x": 1, "z": 3}, {"x": 2, "z": 6}, {"x": 3, "z": 9}]


def test_multiple_indexed_data_with_helper_function(session):
result = session.run("UNWIND range(1, 3) AS n "
"RETURN 1 * n AS x, 2 * n AS y, 3 * n AS z")
assert result.data(2, 0) == [{"x": 1, "z": 3}, {"x": 2, "z": 6}, {"x": 3, "z": 9}]


def test_multiple_keyed_data(session):
result = session.run("UNWIND range(1, 3) AS n "
"RETURN 1 * n AS x, 2 * n AS y, 3 * n AS z")
Expand Down