Skip to content

Commit f2790c4

Browse files
committed
Add more user API methods and improve documentation
1 parent 52392e4 commit f2790c4

25 files changed

+585
-506
lines changed

Diff for: README.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
|
3232
3333
Welcome to the GitHub page for **python-arango**, a Python driver for
34-
`ArangoDB's REST API <https://www.arangodb.com/>`__.
34+
`ArangoDB <https://www.arangodb.com/>`__.
3535

3636
Features
3737
========
@@ -100,12 +100,12 @@ Here is a simple usage example:
100100
101101
# Insert new documents into the collection
102102
students.insert({'name': 'jane', 'age': 19})
103-
students.insert({'name': 'josh', 'age': 13})
103+
students.insert({'name': 'josh', 'age': 18})
104104
students.insert({'name': 'jake', 'age': 21})
105105
106-
# Execute an AQL query and iterate through the result cursor
107-
cursor = db.aql.execute('FOR s IN students RETURN s')
108-
print(student['name'] for student in cursor)
106+
# Execute an AQL query
107+
result = db.aql.execute('FOR s IN students RETURN s')
108+
print([student['name'] for student in result])
109109
110110
Please read the full `API documentation`_ for more details!
111111

Diff for: arango/client.py

+155-144
Large diffs are not rendered by default.

Diff for: arango/connection.py

+18-12
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,15 @@ def head(self, endpoint, params=None, headers=None, **_):
154154
:returns: the ArangoDB http response
155155
:rtype: arango.response.Response
156156
"""
157+
url = self._url_prefix + endpoint
157158
res = self._http.head(
158-
url=self._url_prefix + endpoint,
159+
url=url,
159160
params=params,
160161
headers=headers,
161162
auth=(self._username, self._password)
162163
)
163164
if self._logging:
164-
logger.debug('HEAD {} {}'.format(endpoint, res.status_code))
165+
logger.debug('HEAD {} {}'.format(url, res.status_code))
165166
return res
166167

167168
def get(self, endpoint, params=None, headers=None, **_):
@@ -176,14 +177,15 @@ def get(self, endpoint, params=None, headers=None, **_):
176177
:returns: the ArangoDB http response
177178
:rtype: arango.response.Response
178179
"""
180+
url = self._url_prefix + endpoint
179181
res = self._http.get(
180-
url=self._url_prefix + endpoint,
182+
url=url,
181183
params=params,
182184
headers=headers,
183185
auth=(self._username, self._password)
184186
)
185187
if self._logging:
186-
logger.debug('GET {} {}'.format(endpoint, res.status_code))
188+
logger.debug('GET {} {}'.format(url, res.status_code))
187189
return res
188190

189191
def put(self, endpoint, data=None, params=None, headers=None, **_):
@@ -200,15 +202,16 @@ def put(self, endpoint, data=None, params=None, headers=None, **_):
200202
:returns: the ArangoDB http response
201203
:rtype: arango.response.Response
202204
"""
205+
url = self._url_prefix + endpoint
203206
res = self._http.put(
204-
url=self._url_prefix + endpoint,
207+
url=url,
205208
data=sanitize(data),
206209
params=params,
207210
headers=headers,
208211
auth=(self._username, self._password)
209212
)
210213
if self._logging:
211-
logger.debug('PUT {} {}'.format(endpoint, res.status_code))
214+
logger.debug('PUT {} {}'.format(url, res.status_code))
212215
return res
213216

214217
def post(self, endpoint, data=None, params=None, headers=None, **_):
@@ -225,15 +228,16 @@ def post(self, endpoint, data=None, params=None, headers=None, **_):
225228
:returns: the ArangoDB http response
226229
:rtype: arango.response.Response
227230
"""
231+
url = self._url_prefix + endpoint
228232
res = self._http.post(
229-
url=self._url_prefix + endpoint,
233+
url=url,
230234
data=sanitize(data),
231235
params=params,
232236
headers=headers,
233237
auth=(self._username, self._password)
234238
)
235239
if self._logging:
236-
logger.debug('POST {} {}'.format(endpoint, res.status_code))
240+
logger.debug('POST {} {}'.format(url, res.status_code))
237241
return res
238242

239243
def patch(self, endpoint, data=None, params=None, headers=None, **_):
@@ -250,15 +254,16 @@ def patch(self, endpoint, data=None, params=None, headers=None, **_):
250254
:returns: the ArangoDB http response
251255
:rtype: arango.response.Response
252256
"""
257+
url = self._url_prefix + endpoint
253258
res = self._http.patch(
254-
url=self._url_prefix + endpoint,
259+
url=url,
255260
data=sanitize(data),
256261
params=params,
257262
headers=headers,
258263
auth=(self._username, self._password)
259264
)
260265
if self._logging:
261-
logger.debug('PATCH {} {}'.format(endpoint, res.status_code))
266+
logger.debug('PATCH {} {}'.format(url, res.status_code))
262267
return res
263268

264269
def delete(self, endpoint, data=None, params=None, headers=None, **_):
@@ -275,13 +280,14 @@ def delete(self, endpoint, data=None, params=None, headers=None, **_):
275280
:returns: the ArangoDB http response
276281
:rtype: arango.response.Response
277282
"""
283+
url = self._url_prefix + endpoint
278284
res = self._http.delete(
279-
url=self._url_prefix + endpoint,
285+
url=url,
280286
data=sanitize(data),
281287
params=params,
282288
headers=headers,
283289
auth=(self._username, self._password)
284290
)
285291
if self._logging:
286-
logger.debug('DELETE {} {}'.format(endpoint, res.status_code))
292+
logger.debug('DELETE {} {}'.format(url, res.status_code))
287293
return res

Diff for: arango/exceptions.py

+4
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ class UserDeleteError(ArangoError):
213213
"""Failed to delete the user."""
214214

215215

216+
class UserAccessError(ArangoError):
217+
"""Failed to retrieve the names of databases user can access."""
218+
219+
216220
class UserGrantAccessError(ArangoError):
217221
"""Failed to grant user access to a database."""
218222

Diff for: arango/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
VERSION = '3.1.0'
1+
VERSION = '3.2.0'

Diff for: docs/admin.rst

+4-14
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,11 @@
33
Server Administration
44
---------------------
55

6-
Python-arango provides operations for server administration and monitoring.
7-
For more information on the HTTP REST API visit this
8-
`page <https://docs.arangodb.com/HTTP/AdministrationAndMonitoring>`__.
6+
Python-arango provides operations for administration and monitoring. Some of
7+
these operations require root privileges (i.e. access to the ``_system``
8+
database).
99

10-
.. note::
11-
Some operations in the example below require root privileges (i.e. the
12-
user must have access to the ``_system`` database).
13-
14-
.. warning::
15-
`Replication <https://docs.arangodb.com/HTTP/Replications>`__ and
16-
`sharding <https://docs.arangodb.com/HTTP/ShardingInterface>`__ are
17-
currently not supported by python-arango.
18-
19-
**Example:**
10+
Example:
2011

2112
.. code-block:: python
2213
@@ -60,5 +51,4 @@ For more information on the HTTP REST API visit this
6051
# Reload the routing collection (requires root access)
6152
client.reload_routing()
6253
63-
6454
Refer to :ref:`ArangoClient` class for more details.

Diff for: docs/aql.rst

+8-16
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@ AQL Queries
1414
===========
1515

1616
**AQL queries** can be invoked using the :ref:`AQL` class, which returns
17-
instances of :ref:`Cursor`. For more information on the syntax of AQL visit
18-
this `page <https://docs.arangodb.com/AQL/Fundamentals/Syntax.html>`__ and
19-
for more information on the HTTP REST API visit this
20-
`page <https://docs.arangodb.com/HTTP/AqlQuery>`__.
17+
instances of :ref:`Cursor`. For more information on AQL syntax visit this
18+
`page <https://docs.arangodb.com/AQL/Fundamentals/Syntax.html>`__.
2119

22-
**Example:**
20+
Here is an example showing how AQL queries can be executed:
2321

2422
.. code-block:: python
2523
@@ -56,13 +54,10 @@ AQL User Functions
5654
**AQL user functions** are custom functions defined by the users to extend the
5755
functionality of AQL. Although python-arango provides ways to add, delete and
5856
retrieve user functions in Python, the functions themselves must be defined in
59-
Javascript.
57+
Javascript. For more general information on AQL user functions visit this
58+
`page <https://docs.arangodb.com/AQL/Extending>`__.
6059

61-
For more information on the HTTP REST API for AQL user functions visit this
62-
`page <https://docs.arangodb.com/HTTP/AqlQueryCache>`__ and for more general
63-
information this `page <https://docs.arangodb.com/AQL/Extending>`__.
64-
65-
**Example:**
60+
Here is an example showing how AQL functions can be created or deleted:
6661

6762
.. code-block:: python
6863
@@ -90,13 +85,10 @@ AQL Query Cache
9085

9186
**AQL query cache** minimizes redundant calculation of the same query results.
9287
If it useful when read queries are called frequently and write queries are not.
93-
94-
For more information on the HTTP REST API for AQL query caches visit this
95-
`page <https://docs.arangodb.com/HTTP/AqlQueryCache>`__ and for more general
96-
information visit this
88+
For more general information on AQL query caches visit this
9789
`page <https://docs.arangodb.com/AQL/ExecutionAndPerformance/QueryCache.html>`__.
9890

99-
**Example:**
91+
Here is an example showing how the AQL query cache can be used:
10092

10193
.. code-block:: python
10294

Diff for: docs/async.rst

+15-15
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,55 @@
33
Async Execution
44
---------------
55

6-
Python-arango provides support for **asynchronous execution**, where incoming
6+
Python-arango provides support for **asynchronous executions**, where incoming
77
requests are placed in a server-side, in-memory task queue and executed in a
88
fire-and-forget style. The results of the requests can be retrieved later via
99
:ref:`AsyncJob` objects.
1010

11-
For more information on the HTTP REST API for retrieving asynchronous results
12-
visit this `page <https://docs.arangodb.com/HTTP/AsyncResultsManagement>`_.
11+
.. note::
12+
The user should be mindful of the server-side memory while using async
13+
executions with a large number of requests.
1314

14-
**Example:**
15+
Here is an example showing how asynchronous executions can be used:
1516

1617
.. code-block:: python
1718
18-
from arango import ArangoClient
19+
from arango import ArangoClient, ArangoError
1920
2021
client = ArangoClient()
2122
db = client.db('my_database')
2223
23-
# Initialize an AsyncExecution object to make asynchronous calls
24+
# Initialize an AsyncExecution object to make asynchronous requests
2425
async = db.async(return_result=True)
2526
2627
# AsyncExecution has a similar interface as that of Database, but
27-
# AsyncJob objects are returned instead of results on API calls
28+
# AsyncJob objects are returned instead of results on method calls
2829
job1 = async.collection('students').insert({'_key': 'Abby'})
2930
job2 = async.collection('students').insert({'_key': 'John'})
3031
job3 = async.collection('students').insert({'_key': 'John'})
3132
job4 = async.aql.execute('FOR d IN students RETURN d')
3233
33-
# Once the jobs finish, their results can be accessed before expiry
34+
# Check the statuses of the asynchronous jobs
3435
for job in [job1, job2, job3, job4]:
35-
print(job, job.status())
36+
print(job.status())
3637
3738
# Retrieve the result of a job
3839
result = job1.result()
39-
assert isinstance(result, dict)
4040
41-
# If a job fails the error is returned as opposed to being raised
41+
# If a job fails, the exception object is returned (not raised)
4242
result = job3.result()
43-
assert isinstance(result, Exception)
43+
assert isinstance(result, ArangoError)
4444
4545
# Cancel a pending job
4646
job3.cancel()
4747
48-
# Clear a result of a job from the server
48+
# Delete a result of a job from the server to free up resources
4949
job4.clear()
5050
51-
# List the first 100 jobs done
51+
# List the first 100 jobs completed
5252
client.async_jobs(status='done', count=100)
5353
54-
# List the first 100 jobs pending in the queue
54+
# List the first 100 jobs still pending in the queue
5555
client.async_jobs(status='pending', count=100)
5656
5757
# Clear all jobs from the server

Diff for: docs/batch.rst

+17-19
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,49 @@
33
Batch Execution
44
---------------
55

6-
Python-arango provides support for **batch execution**, where incoming requests
7-
are queued in client-side memory and executed in a single HTTP call. After the
8-
batch is committed/executed, the results of the requests can be retrieved via
9-
:ref:`BatchJob` objects.
6+
Python-arango provides support for **batch executions**, where incoming
7+
requests are queued in client-side memory and executed in a single HTTP call.
8+
After the batch is committed, the results of the queued requests can be
9+
retrieved via :ref:`BatchJob` objects.
1010

11-
For more information on the HTTP REST API for batch requests visit this
12-
`page <https://docs.arangodb.com/HTTP/BatchRequest>`_.
11+
.. note::
12+
The user should be mindful of the client-side memory while using batch
13+
executions with a large number of requests.
1314

14-
15-
**Example:**
15+
Here is an example showing how batch executions can be used:
1616

1717
.. code-block:: python
1818
19-
from arango import ArangoClient
19+
from arango import ArangoClient, ArangoError
2020
2121
client = ArangoClient()
2222
db = client.db('my_database')
2323
24-
# Initialize a BatchExecution object via a context manager
24+
# Initialize the BatchExecution object via a context manager
2525
with db.batch(return_result=True) as batch:
2626
2727
# BatchExecution has a similar interface as that of Database, but
28-
# BatchJob objects are returned instead of results on API calls
28+
# BatchJob objects are returned instead of results on method calls
2929
job1 = batch.aql.execute('FOR d IN students RETURN d')
3030
job2 = batch.collection('students').insert({'_key': 'Abby'})
3131
job3 = batch.collection('students').insert({'_key': 'John'})
3232
job4 = batch.collection('students').insert({'_key': 'John'})
3333
3434
# Upon exiting context, the queued requests are committed
3535
for job in [job1, job2, job3, job4]:
36-
print(job, job.status())
36+
print(job.status())
3737
3838
# Retrieve the result of a job
39-
print(job1.result())
39+
job1.result()
4040
41-
# If a job fails the error is returned as opposed to being raised
42-
assert isinstance(job4.result(), Exception)
41+
# If a job fails, the exception object is returned (not raised)
42+
assert isinstance(job4.result(), ArangoError)
4343
4444
# BatchExecution can also be initialized without a context manager
4545
batch = db.batch(return_result=True)
4646
students = batch.collection('students')
4747
job5 = batch.collection('students').insert({'_key': 'Jake'})
4848
job6 = batch.collection('students').insert({'_key': 'Jill'})
49-
batch.commit() # The commit must be called manually
50-
49+
batch.commit() # In which case the commit must be called explicitly
5150
52-
Refer to :ref:`BatchExecution` and :ref:`BatchJob` classes for more
53-
details.
51+
Refer to :ref:`BatchExecution` and :ref:`BatchJob` classes for more details.

0 commit comments

Comments
 (0)