Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.
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
23 changes: 18 additions & 5 deletions cloudant/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,21 @@
class Account(Resource):

"""
A account to a Cloudant or CouchDB account.
An account to a Cloudant or CouchDB account.

account = cloudant.Account()
account.login(USERNAME, PASSWORD).result()
print account.get().result().json()
# {"couchdb": "Welcome", ...}
response = account.login(USERNAME, PASSWORD)
print response.json()
# { "ok": True, ... }

Like all Cloudant-Python objects, pass `async=True`
to make asynchronous requests, like this:

account = cloudant.Account(async=True)
future = account.login(USERNAME, PASSWORD)
response = future.result()
print response.json()
# { "ok": True, ... }
"""

def __init__(self, uri="http://localhost:5984", **kwargs):
Expand All @@ -34,7 +43,11 @@ def __delitem__(self, name):
Blocks until the response returns,
and raises an error if the deletion failed.
"""
return self.database(name, **self.opts).delete().result().raise_for_status()
response = self.database(name, **self.opts).delete()
# block until result if the object is using async
if hasattr(response, 'result'):
response = response.result()
response.raise_for_status()

def all_dbs(self, **kwargs):
"""List all databases."""
Expand Down
6 changes: 5 additions & 1 deletion cloudant/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ def __getitem__(self, name):

def __setitem__(self, name, doc):
"""Creates `doc` with an ID of `name`."""
self.put(name, params=doc).result()
response = self.put(name, params=doc)
# block until result if the object is using async
if hasattr(response, 'result'):
response = response.result()
response.raise_for_status()

def all_docs(self, **kwargs):
"""
Expand Down
6 changes: 5 additions & 1 deletion cloudant/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ def merge(self, change, **kwargs):
Merge `change` into the document,
and then `PUT` the updated document back to the server.
"""
doc = self.get().result().json()
response = self.get()
# block until result if the object is using async
if hasattr(response, 'result'):
response = response.result()
doc = response.json()
doc.update(change)
return self.put(params=doc, **kwargs)

Expand Down
5 changes: 4 additions & 1 deletion cloudant/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ class Index(Resource):
"""

def __iter__(self):
response = self.get(stream=True).result()
response = self.get(stream=True)
# block until result if the object is using async
if hasattr(response, 'result'):
response = response.result()
for line in response.iter_lines():
if line:
if line[-1] == ',':
Expand Down
8 changes: 6 additions & 2 deletions cloudant/resource.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from requests_futures.sessions import FuturesSession
import requests
import urlparse
import json
import copy
Expand All @@ -20,11 +21,14 @@ def __init__(self, uri, **kwargs):
self.uri = uri
self.uri_parts = urlparse.urlparse(self.uri)

if 'session' in kwargs.keys():
if kwargs.get('session'):
self._session = kwargs['session']
del kwargs['session']
else:
elif kwargs.get('async'):
self._session = FuturesSession()
del kwargs['async']
else:
self._session = requests.Session()

self._set_options(**kwargs)

Expand Down
57 changes: 44 additions & 13 deletions docs/site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ <h2>Install</h2>
<pre><code>pip install cloudant
</code></pre>
<h2>Usage</h2>
<p>Cloudant-Python is an asynchronous wrapper around Python <a href="http://www.python-requests.org/en/latest/">Requests</a> for interacting with CouchDB or Cloudant instances. Check it out:</p>
<p>Cloudant-Python is a wrapper around Python <a href="http://www.python-requests.org/en/latest/">Requests</a> for interacting with CouchDB or Cloudant instances. Check it out:</p>
<pre><code class="python">import cloudant

# connect to your account
Expand All @@ -52,19 +52,34 @@ <h2>Usage</h2>

# login, so we can make changes
login = account.login(USERNAME, PASSWORD)
assert login.result().status_code == 200
assert login.status_code == 200

# create a database object
db = account.database('test')

# now, create the database on the server
future = db.put()
response = future.result()
response = db.put()
print response.json()
# {'ok': True}
</code></pre>

<p>HTTP requests return <a href="http://docs.python.org/dev/library/concurrent.futures.html#future-objects">Future</a> objects, which will await the return of the HTTP response. Call <code>result()</code> to get the <a href="http://www.python-requests.org/en/latest/api/#requests.Response">Response</a> object.</p>
<p>HTTP requests return [Response][response] objects, right from <a href="http://www.python-requests.org/en/latest/">Requests</a>.</p>
<p>Cloudant-Python can also make asynchronous requests by passing <code>async=True</code> to an object's constructor, like so:</p>
<pre><code class="python">import cloudant

# connect to your account
# in this case, https://garbados.cloudant.com
USERNAME = 'garbados'
account = cloudant.Account(USERNAME, async=True)

# login, so we can make changes
future = account.login(USERNAME, PASSWORD)
# block until we get the response body
login = future.result()
assert login.status_code == 200
</code></pre>

<p>Asynchronous HTTP requests return <a href="http://docs.python.org/dev/library/concurrent.futures.html#future-objects">Future</a> objects, which will await the return of the HTTP response. Call <code>result()</code> to get the <a href="http://www.python-requests.org/en/latest/api/#requests.Response">Response</a> object.</p>
<p>See the <a href="http://cloudant-labs.github.io/cloudant-python/#api">API reference</a> for all the details you could ever want.</p>
<h2>Philosophy</h2>
<p>Cloudant-Python is minimal, performant, and effortless. Check it out:</p>
Expand Down Expand Up @@ -92,11 +107,11 @@ <h3>Pythonisms</h3>
resp = doc.put({
'_id': 'hello_world',
'herp': 'derp'
}).result()
})

# delete the document
rev = resp.json()['_rev']
doc.delete(rev).result()
doc.delete(rev).raise_for_status()

# but this also creates a document
db['hello_world'] = {'herp': 'derp'}
Expand Down Expand Up @@ -129,7 +144,7 @@ <h3>Special Endpoints</h3>
<li><code>http://localhost:5984/DB/_design/DOC/_view/INDEX</code> -&gt; <code>Account().database(DB).design(DOC).view(INDEX)</code></li>
</ul>
<h3>Asynchronous</h3>
<p>HTTP request methods like <code>get</code> and <code>post</code> return <a href="http://docs.python.org/dev/library/concurrent.futures.html#future-objects">Future</a> objects, which represent an eventual response. This allows your code to keep executing while the request is off doing its business in cyberspace. To get the <a href="http://www.python-requests.org/en/latest/api/#requests.Response">Response</a> object (waiting until it arrives if necessary) use the <code>result</code> method, like so:</p>
<p>If you instantiate an object with the <code>async=True</code> option, its HTTP request methods (such as <code>get</code> and <code>post</code>) will return <a href="http://docs.python.org/dev/library/concurrent.futures.html#future-objects">Future</a> objects, which represent an eventual response. This allows your code to keep executing while the request is off doing its business in cyberspace. To get the <a href="http://www.python-requests.org/en/latest/api/#requests.Response">Response</a> object (waiting until it arrives if necessary) use the <code>result</code> method, like so:</p>
<pre><code class="python">import cloudant

account = cloudant.Account()
Expand Down Expand Up @@ -186,9 +201,17 @@ <h1>API Reference</h1>
<h2>Account</h2>
<p>A account to a Cloudant or CouchDB account.</p>
<pre><code>account = cloudant.Account()
account.login(USERNAME, PASSWORD).result()
print account.get().result().json()
# {"couchdb": "Welcome", ...}
response = account.login(USERNAME, PASSWORD)
print response.json()
# { "ok": True, ... }
</code></pre>
<p>Like all Cloudant-Python objects, pass <code>async=True</code>
to make asynchronous requests, like this:</p>
<pre><code>account = cloudant.Account(async=True)
future = account.login(USERNAME, PASSWORD)
response = future.result()
print response.json()
# { "ok": True, ... }
</code></pre>
</div>
</div>
Expand Down Expand Up @@ -861,7 +884,11 @@ <h3>merge</h3>
<div class='code'>
<pre><code> def merge(self, change, **kwargs):

doc = self.get().result().json()
response = self.get()
# block until result if the object is using async
if hasattr(response, 'result'):
response = response.result()
doc = response.json()
doc.update(change)
return self.put(params=doc, **kwargs)
</code></pre>
Expand Down Expand Up @@ -1090,7 +1117,11 @@ <h3>merge</h3>
<div class='code'>
<pre><code> def merge(self, change, **kwargs):

doc = self.get().result().json()
response = self.get()
# block until result if the object is using async
if hasattr(response, 'result'):
response = response.result()
doc = response.json()
doc.update(change)
return self.put(params=doc, **kwargs)
</code></pre>
Expand Down
37 changes: 28 additions & 9 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[![PyPi downloads](https://pypip.in/d/cloudant/badge.png)](https://crate.io/packages/cloudant/)

[futures]: http://docs.python.org/dev/library/concurrent.futures.html#future-objects
[requests]: http://www.python-requests.org/en/latest/
[responses]: http://www.python-requests.org/en/latest/api/#requests.Response

An effortless Cloudant / CouchDB interface for Python.
Expand All @@ -16,7 +17,7 @@ An effortless Cloudant / CouchDB interface for Python.

## Usage

Cloudant-Python is an asynchronous wrapper around Python [Requests](http://www.python-requests.org/en/latest/) for interacting with CouchDB or Cloudant instances. Check it out:
Cloudant-Python is a wrapper around Python [Requests][requests] for interacting with CouchDB or Cloudant instances. Check it out:

```python
import cloudant
Expand All @@ -28,19 +29,37 @@ account = cloudant.Account(USERNAME)

# login, so we can make changes
login = account.login(USERNAME, PASSWORD)
assert login.result().status_code == 200
assert login.status_code == 200

# create a database object
db = account.database('test')

# now, create the database on the server
future = db.put()
response = future.result()
response = db.put()
print response.json()
# {'ok': True}
```

HTTP requests return [Future][futures] objects, which will await the return of the HTTP response. Call `result()` to get the [Response][responses] object.
HTTP requests return [Response][responses] objects, right from [Requests][requests].

Cloudant-Python can also make asynchronous requests by passing `async=True` to an object's constructor, like so:

```python
import cloudant

# connect to your account
# in this case, https://garbados.cloudant.com
USERNAME = 'garbados'
account = cloudant.Account(USERNAME, async=True)

# login, so we can make changes
future = account.login(USERNAME, PASSWORD)
# block until we get the response body
login = future.result()
assert login.status_code == 200
```

Asynchronous HTTP requests return [Future][futures] objects, which will await the return of the HTTP response. Call `result()` to get the [Response][responses] object.

See the [API reference](http://cloudant-labs.github.io/cloudant-python/#api) for all the details you could ever want.

Expand Down Expand Up @@ -77,11 +96,11 @@ doc = db.document('test_doc')
resp = doc.put({
'_id': 'hello_world',
'herp': 'derp'
}).result()
})

# delete the document
rev = resp.json()['_rev']
doc.delete(rev).result()
doc.delete(rev).raise_for_status()

# but this also creates a document
db['hello_world'] = {'herp': 'derp'}
Expand Down Expand Up @@ -120,12 +139,12 @@ If CouchDB has a special endpoint for something, it's in Cloudant-Python as a sp

### Asynchronous

HTTP request methods like `get` and `post` return [Future][futures] objects, which represent an eventual response. This allows your code to keep executing while the request is off doing its business in cyberspace. To get the [Response][responses] object (waiting until it arrives if necessary) use the `result` method, like so:
If you instantiate an object with the `async=True` option, its HTTP request methods (such as `get` and `post`) will return [Future][futures] objects, which represent an eventual response. This allows your code to keep executing while the request is off doing its business in cyberspace. To get the [Response][responses] object (waiting until it arrives if necessary) use the `result` method, like so:

```python
import cloudant

account = cloudant.Account()
account = cloudant.Account(async=True)
db = account['test']
future = db.put()
response = future.result()
Expand Down
Loading