Skip to content

Commit 9e53762

Browse files
committed
Use the correct cursor for document exports and improve documentation
1 parent ecc3184 commit 9e53762

File tree

8 files changed

+93
-33
lines changed

8 files changed

+93
-33
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ install:
1414
- python setup.py install
1515
script:
1616
- py.test --cov-report= --cov=arango tests/
17-
after_success:
18-
- coveralls
17+
# after_success:
18+
# - coveralls

arango/collections/base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import absolute_import, unicode_literals
22

33
from arango.api import APIWrapper, api_method
4-
from arango.cursor import Cursor
4+
from arango.cursor import Cursor, ExportCursor
55
from arango.exceptions import *
66
from arango.request import Request
77
from arango.utils import HTTP_OK
@@ -49,7 +49,7 @@ def __iter__(self):
4949
)
5050
if res.status_code not in HTTP_OK:
5151
raise DocumentGetError(res)
52-
return Cursor(self._conn, res.body)
52+
return ExportCursor(self._conn, res.body)
5353

5454
def __len__(self):
5555
"""Return the number of documents in the collection.
@@ -542,7 +542,7 @@ def all(self,
542542
def handler(res):
543543
if res.status_code not in HTTP_OK:
544544
raise DocumentGetError(res)
545-
return Cursor(self._conn, res.body)
545+
return ExportCursor(self._conn, res.body)
546546

547547
return request, handler
548548

arango/cursor.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,45 @@ def close(self, ignore_missing=True):
142142
return False
143143
raise CursorCloseError(res)
144144
return True
145+
146+
147+
class ExportCursor(Cursor):
148+
"""ArangoDB cursor for export queries only.
149+
150+
.. note::
151+
This class is designed to be instantiated internally only.
152+
"""
153+
154+
def next(self):
155+
"""Read the next result from the cursor.
156+
157+
:returns: the next item in the cursor
158+
:rtype: dict
159+
:raises: StopIteration, CursorNextError
160+
"""
161+
if not self.batch() and self.has_more():
162+
res = self._conn.put("/_api/export/{}".format(self.id))
163+
if res.status_code not in HTTP_OK:
164+
raise CursorNextError(res)
165+
self._data = res.body
166+
elif not self.batch() and not self.has_more():
167+
raise StopIteration
168+
return self.batch().pop(0)
169+
170+
def close(self, ignore_missing=True):
171+
"""Close the cursor and free the resources tied to it.
172+
173+
:returns: whether the cursor was closed successfully
174+
:rtype: bool
175+
:param ignore_missing: ignore missing cursors
176+
:type ignore_missing: bool
177+
:raises: CursorCloseError
178+
"""
179+
if not self.id:
180+
return False
181+
res = self._conn.delete("/_api/export/{}".format(self.id))
182+
if res.status_code not in HTTP_OK:
183+
if res.status_code == 404 and ignore_missing:
184+
return False
185+
raise CursorCloseError(res)
186+
return True

docs/aql.rst

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@
33
AQL
44
----
55

6-
**ArangoDB AQL Language (AQL)** is used to retrieve and modify data stored in
7-
ArangoDB. AQL is similar to SQL for relational databases but without the
8-
support for data-definition operations such as creating or deleting
6+
**ArangoDB Query Language (AQL)** is used to retrieve and modify data in
7+
ArangoDB. AQL is similar to SQL for relational databases, but without the
8+
support for data definition operations such as creating/deleting
99
:ref:`databases <database-page>`, :ref:`collections <collection-page>` and
10-
:ref:`indexes <index-page>` etc. For more general information on AQL visit this
11-
`page <https://docs.arangodb.com/AQL>`__.
10+
:ref:`indexes <index-page>`. For more general information on AQL visit
11+
`here <https://docs.arangodb.com/AQL>`__.
1212

1313
AQL Queries
1414
===========
1515

16-
**AQL queries** can be invoked using the :ref:`AQL` class, which returns
17-
instances of :ref:`Cursor`. For more information on AQL syntax visit this
18-
`page <https://docs.arangodb.com/AQL/Fundamentals/Syntax.html>`__.
16+
**AQL queries** can be invoked using the :ref:`AQL` class, which outputs
17+
instances of the :ref:`Cursor` class. For more information on the syntax of AQL
18+
visit `here <https://docs.arangodb.com/AQL/Fundamentals/Syntax.html>`__.
1919

20-
Here is an example showing how AQL queries can be executed:
20+
Below is an example of executing a query:
2121

2222
.. code-block:: python
2323
@@ -51,13 +51,13 @@ Here is an example showing how AQL queries can be executed:
5151
AQL User Functions
5252
==================
5353

54-
**AQL user functions** are custom functions defined by the users to extend the
55-
functionality of AQL. Although python-arango provides ways to add, delete and
56-
retrieve user functions in Python, the functions themselves must be defined in
57-
Javascript. For more general information on AQL user functions visit this
58-
`page <https://docs.arangodb.com/AQL/Extending>`__.
54+
**AQL user functions** are custom functions which can be defined by users to
55+
extend the functionality of AQL. While python-arango provides ways to add,
56+
delete and retrieve user functions in Python, the functions themselves must be
57+
defined in Javascript. For more general information on AQL user functions visit
58+
this `page <https://docs.arangodb.com/AQL/Extending>`__.
5959

60-
Here is an example showing how AQL functions can be created or deleted:
60+
Below is an example of creating and deleting an AQL function:
6161

6262
.. code-block:: python
6363
@@ -83,9 +83,9 @@ Refer to :ref:`AQL` class for more details.
8383
AQL Query Cache
8484
===============
8585

86-
**AQL query cache** minimizes redundant calculation of the same query results.
87-
If it useful when read queries are called frequently and write queries are not.
88-
For more general information on AQL query caches visit this
86+
**AQL query cache** is used to minimize redundant calculation of the same
87+
query result. It is useful when read queries are called frequently and write
88+
queries are not. For more general information on AQL query caches visit this
8989
`page <https://docs.arangodb.com/AQL/ExecutionAndPerformance/QueryCache.html>`__.
9090

9191
Here is an example showing how the AQL query cache can be used:

docs/client.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
Getting Started
44
---------------
55

6-
Here is an example showing how **python-arango** client can be used:
6+
Here is an example showing how a **python-arango** client can be initialized
7+
and used:
78

89
.. code-block:: python
910
@@ -41,4 +42,4 @@ Here is an example showing how **python-arango** client can be used:
4142
result = db.aql.execute('FOR s IN students RETURN s')
4243
print([student['name'] for student in result])
4344
44-
Read the rest of the documentation to discover much more!
45+
Pretty simple right? Read the rest of the documentation to discover much more!

docs/database.rst

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
Databases
44
---------
55

6-
A single ArangoDB instance can house multiple databases, which in turn can have
6+
A single ArangoDB instance can house multiple databases, which in turn contain
77
their own set of worker processes, :ref:`collections <collection-page>`, and
8-
:ref:`graphs <graph-page>`. There is also a default database named ``_system``.
9-
This database cannot be dropped, can only be accessed with root privileges, and
10-
provides operations for managing other user-defined databases.
8+
:ref:`graphs <graph-page>`. There must always be a default database named
9+
``_system``. This database cannot be dropped, can only be accessed with root
10+
privileges, and provides operations for managing other user-defined databases.
1111

1212
Here is an example showing how databases can be managed with different users:
1313

@@ -18,7 +18,8 @@ Here is an example showing how databases can be managed with different users:
1818
# Initialize the ArangoDB client as root
1919
client = ArangoClient(username='root', password='')
2020
21-
# Create a database, again as root (the user is inherited if not specified)
21+
# Create a database, again as root (the user is inherited from client
22+
# initialization if the username and password are not specified)
2223
db = client.create_database('my_database', username=None, password=None)
2324
2425
# Retrieve the properties of the new database
@@ -27,12 +28,14 @@ Here is an example showing how databases can be managed with different users:
2728
# Create another database, this time with a predefined set of users
2829
db = client.create_database(
2930
name='another_database',
31+
# Users jane, john and jake will have access to the new database
3032
users=[
3133
{'username': 'jane', 'password': 'foo', 'active': True},
3234
{'username': 'john', 'password': 'bar', 'active': True},
3335
{'username': 'jake', 'password': 'baz', 'active': True},
3436
],
35-
username='jake', # The new database object uses jake's credentials
37+
# API calls through this database object uses jake's credentials
38+
username='jake',
3639
password='baz'
3740
)
3841

scripts/setup_arangodb.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
44
cd $DIR
55

6-
VERSION=3.0.5
6+
VERSION=3.1.3
77
NAME=ArangoDB-$VERSION
88

99
if [ ! -d "$DIR/$NAME" ]; then
@@ -56,4 +56,4 @@ then
5656
fi
5757

5858

59-
echo "ArangoDB is up"
59+
echo "ArangoDB is up"

tests/test_document.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,20 @@ def test_all():
11521152
with pytest.raises(DocumentGetError):
11531153
bad_col.all()
11541154

1155+
# Test closing export cursor
1156+
result = col.all(count=True, batch_size=1)
1157+
assert result.close(ignore_missing=False) is True
1158+
assert result.close(ignore_missing=True) is False
1159+
1160+
assert clean_keys(result.next()) == doc1
1161+
with pytest.raises(CursorNextError):
1162+
result.next()
1163+
with pytest.raises(CursorCloseError):
1164+
result.close(ignore_missing=False)
1165+
1166+
result = col.all(count=True)
1167+
assert result.close(ignore_missing=True) is False
1168+
11551169

11561170
def test_random():
11571171
# Set up test documents

0 commit comments

Comments
 (0)