The pouchdb package

The pouchdb package mostly mirrors the PouchDB JavaScript API.

There are two API versions: one asynchronous one, which almost directly maps functions to their JavaScript equivalents and supports both promises and callbacks in most cases, and a synchronous one, which doesn’t have a JavaScript equivalent, but is often easier to use.

API examples

Synchronous:

>>> environment = setup()
>>> db = environment.PouchDB('example')
>>> printjson(db.put({"_id": 'my_example_doc'})) 
{"id": "my_example_doc", "ok": true, "rev": "1-..."}
>>> printjson(db.get('my_example_doc')) 
{"_id": "my_example_doc", "_rev": "1-..."}

and (using dict-like syntax):

>>> db["my_example_doc"] = {}
>>> printjson(db["my_example_doc"]) 
{"_id": "my_example_doc", "_rev": "2-..."}

Asynchronous:

>>> def callback(err, resp):
...     printjson(["inside callback:", resp])
... 
>>> env = setup(async=True)
>>> db = env.PouchDB('example')
>>> promise = db.post({}, callback)

or db.post({}).then(callback), with the err argument removed from the callback function. Time to run the event loop. Normally, that’s done using e.g. QtGui.QApplication().exec_(), but for testing purposes like this the following can be used:

>>> env.context.waitUntilCalled(callback) 
["inside callback:", {"id": "...", "ok": true, "rev": "1-..."}]
>>> promise2 = env.destroy('example')

For more examples, see the The pouchdb.tests package documentation page.

API conventions

Since the asynchronous and synchronous api have the same methods, those methods are documented in abstract base classes: AbstractEnvironment and AbstractPouchDB. Their subclasses (AsyncEnvironment, SyncEnvironment, AsyncPouchDB and SyncPouchDB) are the ones actually exposed to you in the API.

The names in the JavaScript API of PouchDB are in camelCase. Python-PouchDB provides snake_case aliases where necessary, since that’s the preffered form according to the PEP 8 style guide.

As shown in the example, you can pass in dictionaries as documents. Additionally, Python-PouchDB allows passing in JSON strings. So, no need to convert if you already have a JSON string.

API access point

pouchdb.setup(storageDir=None, async=False, baseUrl='file:///')[source]

Sets up an environment which allows access to the rest of the API, which mostly consists out of wrappers around PouchDB’s functions. This environment is then returned to the user.

Depending on the async parameter, this is either an instance of SyncEnvironment or AsyncEnvironment.

The storageDir is created automatically if it doesn’t already exist. It can be relative, and should be a directory (not a file). It’s where databases are saved (or more specific: WebKit’s backend database files). When it is None (the default), a temporary directory is created by Python-PouchDB, which is also removed at process exit. This function can raise an EnvironmentError when a storageDir other than one used earlier is passed in as a parameter. (That’s a Qt restriction, unfortunately.)

In older versions of QtWebKit, the same-origin policy is a little too strict which makes it impossible to replicate with databases that aren’t on the same domain as baseUrl. In newer versions, as long as baseUrl is file:///, this problem doesn’t exist. When you need to support the older version, you can set this to a domain so you can at least replicate to one site.

Errors

exception pouchdb.BaseError[source]

The base class for all errors this module should raise.

exception pouchdb.EnvironmentError[source]

Raised when something is wrong relating to the environment in which Python-PouchDB runs.

exception pouchdb.PouchDBError(message, *args, **kwargs)[source]

All error responses PouchDB would normally give you get raised in the form of this error class in Python-PouchDB. You can use get item syntax to access properties set on the error object. E.g.:

>>> try:
...     setup().PouchDB('new-db').get('unexisting-doc')
... except pouchdb.PouchDBError as e:
...    if e["status"] == 404:
...        print("Not found")
...    else:
...        print("Unknown error")
...
Not found

Environment

Documentation on the functionality of all methods is available in the abstract base class AbstractEnvironment. While coding, you get an instance of one of its subclasses: SyncEnvironment or AsyncEnvironment.

Abstract

class pouchdb.AbstractEnvironment[source]

The environment is an event emitter and will emit a ‘created’ event when a database is created. A ‘destroy’ event is emited when a database is destroyed.

Don’t instantiate this class or one of its subclasses yourself, use the setup() function instead.

__getitem__(dbName)[source]

A shortcut for the PouchDB attribute. The following two lines of code are, as you can see, equivalent:

>>> setup()["test"] 
<pouchdb.SyncPouchDB object at 0x...>
>>> setup().PouchDB('test') 
<pouchdb.SyncPouchDB object at 0x...>
POUCHDB_VERSION[source]

The value of what is PouchDB.version in JavaScript, in other words, the version of PouchDB that Python-PouchDB wraps.

PouchDB = '<subclass of AbstractPouchDB (approximately)>'

The PouchDB class that you can use to make a new database instance. You should always use this: never instantiate SyncPouchDB or AsyncPouchDB manually.

addListener(event, listener)[source]

Adds a listener to the end of the listeners array for the specified event.

add_listener(*args, **kwargs)

Alias for addListener().

allDbs()[source]

Wraps the pouchdb-all-dbs plug-in. Returns a list of the names of all local databases.

all_dbs(*args, **kwargs)

Alias for allDbs().

context[source]

Allows access to the internals of Python-Pouch; only useful for debugging purposes. E.g. context.inspect() and context.waitUntilCalled(). The last is used by the test suite.

destroy(name_=None, **options)[source]

Allows you to destroy a database without creating a new PouchDB instance first.

The name argument in PouchDB is called name_ in Python-PouchDB, to prevent a clash with the options["name"] argument. In JavaScript where there are no keyword arguments the problem doesn’t exist, in Python it does, hence the change.

emit(event, *args)[source]

Execute each of the listeners in order with the supplied args. Returns True if event had listeners, False otherwise.

listeners(event)[source]

Returns an array of listeners for the specified event.

on(*args, **kwargs)

Alias for addListener().

once(event, listener)[source]

Adds a one time listener for the event. This listener is invoked only the next time the event is fired, after which it is removed.

removeAllListeners(event=None)[source]

Removes all listeners, or those of the specified event.

removeListener(event, listener)[source]

Remove a listener from the listener array for the specified event. Caution: changes array indices in the listener array behind the listener.

remove_all_listeners(*args, **kwargs)

Alias for removeAllListeners().

remove_listener(*args, **kwargs)

Alias for removeListener().

replicate(source, target, **options)[source]

Replicate data from source to target. Both the source and target can be a string representing a CouchDB database url or the name a local PouchDB database. If live is true, then this will track future changes and also replicate them automatically.

resetAllDbs()[source]

Wraps the pouchdb-all-dbs plug-in. Destroys the separate allDbs database. You should never need to call this function.

reset_all_dbs(*args, **kwargs)

Alias for resetAllDbs().

setMaxListeners(n)[source]

By default EventEmitters will print a warning if more than 10 listeners are added for a particular event. This is a useful default which helps finding memory leaks. Obviously not all Emitters should be limited to 10. This function allows that to be increased. Set to zero for unlimited.

set_max_listeners(*args, **kwargs)

Alias for setMaxListeners().

sync(source, target, **options)[source]

Sync data from source to target and target to source. This is a convience method for bidirectional data replication.

Implementations

class pouchdb.SyncEnvironment[source]

Bases: pouchdb.AbstractEnvironment, _abcoll.Mapping

This class is a Mapping, which means it can be used like a dict. (Except for setting values, in this case).

See for all the methods that being a Mapping offers, the docs about it.

>>> env = setup()
>>> env.keys() 
[...]
__delitem__(dbName)[source]

A shortcut for the AbstractEnvironment.destroy() method. The last two of the following lines of code are equivalent:

>>> env = setup()
>>> del env["test"]
>>> env.destroy("test")
replicate(source, target, **options)[source]

When the live or continuous option is active, this method acts like its asynchronous equivalent.

sync(source, target, **options)[source]

When the live or continuous option is active, this method acts like its asynchronous equivalent.

class pouchdb.AsyncEnvironment[source]

Bases: pouchdb.AbstractEnvironment

Database instance

Documentation on the functionality of all methods is available in the abstract base class AbstractPouchDB. While coding, you get an instance of one of its subclasses: SyncPouchDB or AsyncPouchDB.

Abstract

class pouchdb.AbstractPouchDB[source]

Never instantiate this class or one of its subclasses yourself. Create an environment using the setup() function instead, and then use its AbstractEnvironment.PouchDB attribute, with the arguments specified at __init__().

Extra (optional) options for all AbstractPouchDB.validating* methods compared to their normal AbstractPouchDB.* counterparts are:

  • secObj: e.g.:

    {
            "admins": {
                    "names": [],
                    "roles": []
            },
            "members": {
                    "names": [],
                    "roles": []
            }
    }
    
  • userCtx: e.g.:

    {
            "db": "test_db",
            "name": "username",
            "roles": [
                    "_admin"
            ]
    }
    
  • checkHttp: Set this to True if you want to validate HTTP database documents offline too. Unnecessary for CouchDB, but handy for e.g. PouchDB-Server, which doesn’t validate itself.

__init__(name, **options)[source]

This method creates a database or opens an existing one. If you use a URL like http://domain.com/dbname then Python-PouchDB will work as a client to an online CouchDB instance. Otherwise it will create a local database using the WebSQL backend.

allDocs(**options)[source]

Fetch multiple documents. Deleted documents are only included if keys is specified.

all_docs(*args, **kwargs)

Alias for allDocs().

bulkDocs(docs, **options)[source]

Modify, create or delete multiple documents. The docs argument is an object with property docs which is an array of documents. You can also specify a new_edits property on the docs object that when set to false allows you to post existing documents.

If you omit an _id parameter on a given document, the database will create a new document and assign the ID for you. To update a document, you must include both an _id parameter and a _rev parameter, which should match the ID and revision of the document on which to base your updates. Finally, to delete a document, include a _deleted parameter with the value True.

bulk_docs(*args, **kwargs)

Alias for bulkDocs().

changes(**options)[source]

A list of changes made to documents in the database, in the order they were made. It returns an object with one method cancel, which you call if you don’t want to listen to new changes anymore. onChange will be be called for each change that is encountered.

compact()[source]

Runs compaction of the database. Fires callback when compaction is done. If you use the http adapter and have specified a callback, Pouch will ping the remote database in regular intervals unless the compaction is finished.

destroy()[source]

Delete database.

get(docid, **options)[source]

Retrieves a document, specified by docid.

getAttachment(docId, attachmentId, **options)[source]

Get attachment data. Returns a dictionary with the following format:

{
        "data": b"Bytes as byte string",
        "type": "text/plain"
}
getSession(**options)[source]

Returns information about the current session. In other words, this tells you which user is currently logged in.

getUser(username, **options)[source]

Returns the user document associated with a username. (CouchDB, in a pleasing show of consistency, stores users as JSON documents in the special _users database.) This is the primary way to get metadata about a user.

get_attachment(*args, **kwargs)

Alias for get_attachment().

get_session(*args, **kwargs)

Alias for getSession().

get_user(*args, **kwargs)

Alias for getUser().

gql(query, **options)[source]

Uses the GQL PouchDB plug-in. Check out its documentation.

The Google Query Language (GQL) interface provides an alternative method for accessing data. The version of GQL implemented here is based on the Google Visualization API Query Language.

The syntax of GQL queries should be familiar to those who have used SQL, but the capabilities of GQL are much more limited.

info()[source]

Get information about a database.

list(listPath, **options)[source]

Same as requesting _list in CouchDB. Wraps the list PouchDB plug-in.

logIn(*args, **kwargs)

Alias for login().

logOut(*args, **kwargs)

Alias for logout().

log_in(*args, **kwargs)

Alias for login().

log_out(*args, **kwargs)

Alias for log_out().

login(username, password, **options)[source]

Log in an existing user. Throws an error if the user doesn’t exist yet, the password is wrong, the HTTP server is unreachable, or a meteor struck your computer.

logout(**options)[source]

Logs out whichever user is currently logged in. If nobody’s logged in, it does nothing and just returns {"ok": True}.

post(doc, **options)[source]

Create a new document and let PouchDB generate an _id for it.

put(doc, id=None, rev=None, **options)[source]

Create a new document or update an existing document. If the document already exists, you must specify its revision _rev, otherwise a conflict will occur.

putAttachment(docId, attachmentId, doc, type, rev=None)[source]

Attaches a binary object to a document. Most of Python-PouchDB’s API deals with JSON, but if you’re dealing with large binary data (such as PNGs), you may incur a performance or storage penalty if you simply include them as base64- or hex-encoded strings. In these cases, you can store the binary data as an attachment.

Be aware that the argument order is different than in PouchDB due to the rev argument being optional. Byte strings replace blobs in Python-PouchDB. (e.g. b"Hello World!")

put_attachment(*args, **kwargs)

Alias for putAttachment().

query(fun, **options)[source]

Retrieves a view, which allows you to perform more complex queries on Python-PouchDB. The CouchDB documentation for map/ reduce applies to Python-PouchDB.

Since views perform a full scan of all documents, this method may be slow, unless you first save your view in a design document.

remove(doc, **options)[source]

Deletes the document. doc is required to be a document with at least an _id and a _rev property. Sending the full document will work as well.

removeAttachment(docId, attachmentId, rev)[source]

Delete an attachment from a doc.

remove_attachment(*args, **kwargs)

Alias for remove_attachment().

replicateFrom(remoteDB, **options)[source]

A shorthand for AbstractEnvironment.replicate()

replicateTo(remoteDB, **options)[source]

A shorthand for AbstractEnvironment.replicate()

replicate_from(*args, **kwargs)

Alias for replicateFrom().

replicate_to(*args, **kwargs)

Alias for replicateTo().

revsDiff(diff)[source]

Given a set of document/revision IDs, returns the subset of those that do not correspond to revisions stored in the database. Primarily used in replication.

revs_diff(*args, **kwargs)

Alias for revsDiff().

rewrite(url, **options)[source]

Same as sending a request to _rewrite in CouchDB. Wraps the rewrite PouchDB plug-in. The url has the form designDocName/rewritePath. Keep in mind that you need to use options.query instead of appending a ?key=value string to the url.

options:

  • withValidation: If True, the db.validating* functions are used instead of their db.* counterparts if the rewrite routes to such a resource where that is relevant.
rewriteResultRequestObject(url, **options)[source]

See rewrite(). Instead of returning the result of the function that the rewrite routes to, this returns a CouchDB request object that points to the resource the rewrite resolves to. See also the CouchDB documentation on the request object.

search(func, **options)[source]

Wraps the pouchdb-search plug-in.

show(showPath, **options)[source]

Same as requesting _show in CouchDB. Wraps the show PouchDB plug-in.

signUp(*args, **kwargs)

Alias for signup().

sign_up(*args, **kwargs)

Alias for signup().

signup(username, password, **options)[source]

Sign up a new user who doesn’t exist yet. Throws an error if the user already exists or if the username is invalid, or if some network error occurred. CouchDB has some limitations on user names (e.g. they cannot contain the character ‘:’).

Note: Signing up does not automatically log in a user; you will need to call login() afterwards.

Options:

  • metadata : Object of metadata you want to store with the username, e.g. an email address or any other info. Can be as deeply structured as you want.
spatial(fun, **options)[source]

Same as requesting _spatial in CouchDB when GeoCouch is installed. Wraps the geopouch plug-in.

sync(remoteDB, **options)[source]

A shorthand for AbstractEnvironment.sync()

update(url, **options)[source]

Same as sending a request to _update in CouchDB. Wraps the update PouchDB plug-in.

options:

validatingBulkDocs(docs, **options)[source]

Same as bulkDocs(), but validates like in CouchDB. Wraps the validation PouchDB plug-in.

validatingPost(doc, **options)[source]

Same as post(), but validates like in CouchDB. Wraps the validation PouchDB plug-in.

validatingPut(doc, id=None, rev=None, **options)[source]

Same as put(), but validates like in CouchDB. Wraps the validation PouchDB plug-in.

validatingPutAttachment(docId, attachmentId, doc, type, rev=None, **options)[source]

Same as putAttachment(), but validates like in CouchDB. Wraps the validation PouchDB plug-in.

validatingRemove(doc, **options)[source]

Same as remove(), but validates like in CouchDB. Wraps the validation PouchDB plug-in.

validatingRemoveAttachment(docId, attachmentId, rev, **options)[source]

Same as removeAttachment(), but validates like in CouchDB. Wraps the validation PouchDB plug-in.

validating_bulk_docs(*args, **kwargs)

Alias for validatingBulkDocs().

validating_post(*args, **kwargs)

Alias for validatingPost().

validating_put(*args, **kwargs)

Alias for validatingPut().

validating_put_attachment(*args, **kwargs)

Alias for validatingPutAttachment().

validating_remove(*args, **kwargs)

Alias for validatingRemove().

validating_remove_attachment(*args, **kwargs)

Alias for validatingRemoveAttachment().

viewCleanup(**options)[source]

Cleans up any stale map/reduce indexes.

As design docs are deleted or modified, their associated index files (in CouchDB) or companion databases (in local PouchDBs) continue to take up space on disk. viewCleanup() removes these unnecessary index files.

view_cleanup(*args, **kwargs)

Alias for viewCleanup().

Implementations

class pouchdb.SyncPouchDB[source]

Bases: pouchdb.AbstractPouchDB, _abcoll.MutableMapping

This class is a MutableMapping, which means it can be used like a dict. For details on how that works with revisions, see the documentations on the following methods: __getitem__(), __setitem__() and __delitem__().

See for all the methods that being a MutableMapping offers, the docs about it.

>>> db = setup()["my-example"]
>>> db["mytest"] = {"test": "ok"}
>>> printjson(list(db))
["mytest"]
>>> len(db)
1
>>> "mytest" in db
True
>>> "abc" in db
False
__getitem__(docId)[source]

A shortcut for the AbstractPouchDB.get() method.

Raises a KeyError in place of a PouchDBError if that error’s status is 404 Not Found.

>>> db = setup().PouchDB("example")
>>> db["abc"]
Traceback (most recent call last):
  ...
KeyError: '{"status":404,"name":"not_found","message":"missing"}'
__delitem__(docId)[source]

A shortcut for the AbstractPouchDB.remove() method.

Raises a KeyError in place of a PouchDBError if that error’s status is 404 Not Found. Removes the current document from the database (in other words, the latest revision is taken from the database).

>>> db = setup()["example"]
>>> del db["abc"]
Traceback (most recent call last):
  ...
KeyError: '{"status":404,"name":"not_found","message":"missing"}'
__setitem__(docId, doc)[source]

Sets doc‘s _id to docId and saves the result. When no doc["_rev"] is defined, the one from the current document saved under that id is reused. That is a difference from the normal AbstractPouchDB.put() method. When succesful, doc["_rev"] will have been set to its new value.

changes(**options)[source]

When the live or continuous option is active, this method acts like its asynchronous equivalent.

get_(*args, **kwargs)[source]

Because MutableMapping.get is overwritten by the get() method, it’s aliased under this name.

>>> printjson(db.get_("abc", {"hello": "world"}))
{"hello": "world"}
replicateFrom(remoteDB, **options)[source]

When the live or continuous option is active, this method acts like its asynchronous equivalent.

replicateTo(remoteDB, **options)[source]

When the live or continuous option is active, this method acts like its asynchronous equivalent.

sync(remoteDB, **options)[source]

When the live or continuous option is active, this method acts like its asynchronous equivalent.

class pouchdb.AsyncPouchDB[source]

Bases: pouchdb.AbstractPouchDB

The GQL plug-in only supports the callback interface, it doesn’t provide a promise.

Unsupported PouchDB APIs

The wrapper that wraps Python-PouchDB isn’t advanced enough to get a return value of a Python function called from JavaScript. In most cases this is no problem, but this prevents three things that you might expect to work.

  • It’s not possible to pass a Python function reference as argument in the AbstractPouchDB.query(). JavaScript functions and design doc paths are of course fine.
  • It’s not possible to pass database objects into the replicate functions. AbstractPouchDB.replicate_from() and AbstractPouchDB.replicate_to() allow you to use at least one AbstractPouchDB object though, so you shouldn’t have any problems because of this.
  • It’s not possible to write a PouchDB plug-in in Python. In other words, PouchDB.plug-in isn’t implemented. But seriously, why would you ever want to do that anyway?

It’s not impossible to fix this restriction, it’s just not something that has a very high priority. Patches welcome!

Other unsupported things:

  • Accessing PouchDB.prefix: Python-PouchDB is run in an isolated environment, accessing/changing it makes no sense. The value for the property is set by Python-PouchDB to be an empty string. (No _pouch_!)