Skip to content

Allow ChangeNotifier to use a bound database #31

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Implements the CouchDB API for twisted.

_Enhancements_

* No more bound databases: if no database parameter is passed, the database given during client creation is used.
* Added CouchDB authentication support (supply username and password args when instantiating)
* Re-factored underlying HTTP transport to use Twisted Web Agent (will allow connection pooling in the future).
* Re-factored code into formal Python package. API compatible with old package layout.
Expand Down
11 changes: 4 additions & 7 deletions paisley/changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ def connectionLost(self, reason):

class ChangeNotifier(object):

def __init__(self, db, dbName, since=None):
def __init__(self, db, dbName=None, since=None):
self._db = db
self._dbName = dbName
# if dbName is None, we assume that db is already bound
self._dbName = dbName

self._caches = []
self._listeners = []
Expand Down Expand Up @@ -105,11 +106,7 @@ def setSince(info):
d.addCallback(setSince)

def requestChanges():
kwargs['feed'] = 'continuous'
kwargs['since'] = self._since
# FIXME: str should probably be unicode, as dbName can be
url = str(self._db.url_template %
'/%s/_changes?%s' % (self._dbName, urlencode(kwargs)))
url = self._db.changesUrl(self._dbName, feed='continuous', since = self._since)
return self._db.client.request('GET', url)
d.addCallback(lambda _: requestChanges())

Expand Down
50 changes: 26 additions & 24 deletions paisley/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,7 @@ def __init__(self, host, port=5984, dbName=None, username=None, password=None, d
self.username = username
self.password =password
self.url_template = "http://%s:%s%%s" % (self.host, self.port)
if dbName is not None:
self.bindToDB(dbName)
self.dbName = dbName

if disable_log:
# since this is the db layer, and we generate a lot of logs,
Expand All @@ -155,34 +154,29 @@ def nullfn(self, *a, **k):
port,
dbName if dbName else '')


def parseResult(self, result):
"""
Parse JSON result from the DB.
"""
return json.loads(result)


def bindToDB(self, dbName):
"""
Bind all operations asking for a DB name to the given DB.
"""
for methname in ["createDB", "deleteDB", "infoDB", "listDoc",
"openDoc", "saveDoc", "deleteDoc", "openView",
"tempView"]:
method = getattr(self, methname)
newMethod = partial(method, dbName)
setattr(self, methname, newMethod)


# Database operations

def createDB(self, dbName):
def changesUrl(self, dbName=None, **kwargs):
if dbName == None : dbName = self.dbName
# FIXME: str should probably be unicode, as dbName can be
url = str(self.url_template %
'/%s/_changes?%s' % (dbName, urlencode(kwargs)))
return url

def createDB(self, dbName=None):
"""
Creates a new database on the server.

@type dbName: str
"""
if dbName == None : dbName = self.dbName
# Responses: {u'ok': True}, 409 Conflict, 500 Internal Server Error,
# 401 Unauthorized
# 400 {"error":"illegal_database_name","reason":"Only lowercase
Expand All @@ -193,12 +187,13 @@ def createDB(self, dbName):
).addCallback(self.parseResult)


def deleteDB(self, dbName):
def deleteDB(self, dbName=None):
"""
Deletes the database on the server.

@type dbName: str
"""
if dbName == None : dbName = self.dbName
# Responses: {u'ok': True}, 404 Object Not Found
return self.delete("/%s/" % (dbName,)
).addCallback(self.parseResult)
Expand All @@ -212,10 +207,11 @@ def listDB(self):
return self.get("/_all_dbs", descr='listDB').addCallback(self.parseResult)


def infoDB(self, dbName):
def infoDB(self, dbName=None):
"""
Returns info about the couchDB.
"""
if dbName == None : dbName = self.dbName
# Responses: {u'update_seq': 0, u'db_name': u'mydb', u'doc_count': 0}
# 404 Object Not Found
return self.get("/%s/" % (dbName,), descr='infoDB'
Expand All @@ -224,10 +220,11 @@ def infoDB(self, dbName):

# Document operations

def listDoc(self, dbName, reverse=False, startKey=0, count=-1):
def listDoc(self, dbName=None, reverse=False, startKey=0, count=-1):
"""
List all documents in a given database.
"""
if dbName == None : dbName = self.dbName
# Responses: {u'rows': [{u'_rev': -1825937535, u'_id': u'mydoc'}],
# u'view': u'_all_docs'}, 404 Object Not Found
uri = "/%s/_all_docs" % (dbName,)
Expand All @@ -244,7 +241,7 @@ def listDoc(self, dbName, reverse=False, startKey=0, count=-1):
).addCallback(self.parseResult)


def openDoc(self, dbName, docId, revision=None, full=False, attachment=""):
def openDoc(self, docId, dbName=None, revision=None, full=False, attachment=""):
"""
Open a document in a given database.

Expand All @@ -264,6 +261,7 @@ def openDoc(self, dbName, docId, revision=None, full=False, attachment=""):
# Responses: {u'_rev': -1825937535, u'_id': u'mydoc', ...}
# 404 Object Not Found

if dbName == None : dbName = self.dbName
# FIXME: remove these conversions and have our callers do them
docId = unicode(docId)
assert type(docId) is unicode, \
Expand Down Expand Up @@ -303,7 +301,7 @@ def addAttachments(self, document, attachments):
document["_attachments"][name] = {"type": "base64", "data": data}


def saveDoc(self, dbName, body, docId=None):
def saveDoc(self, body, dbName=None, docId=None):
"""
Save/create a document to/in a given database.

Expand All @@ -320,6 +318,7 @@ def saveDoc(self, dbName, body, docId=None):

# 404 Object not found (if database does not exist)
# 409 Conflict, 500 Internal Server Error
if dbName == None : dbName = self.dbName
if docId:
# FIXME: remove these conversions and have our callers do them
docId = unicode(docId)
Expand All @@ -335,7 +334,7 @@ def saveDoc(self, dbName, body, docId=None):
return d.addCallback(self.parseResult)


def deleteDoc(self, dbName, docId, revision):
def deleteDoc(self, docId, revision, dbName=None):
"""
Delete a document on given database.

Expand All @@ -352,6 +351,7 @@ def deleteDoc(self, dbName, docId, revision):
# Responses: {u'_rev': 1469561101, u'ok': True}
# 500 Internal Server Error

if dbName == None : dbName = self.dbName
docId = unicode(docId)
assert type(docId) is unicode, \
'docId is %r instead of unicode' % (type(docId), )
Expand All @@ -370,12 +370,13 @@ def deleteDoc(self, dbName, docId, revision):

# View operations

def openView(self, dbName, docId, viewId, **kwargs):
def openView(self, docId, viewId, dbName=None, **kwargs):
"""
Open a view of a document in a given database.
"""
# Responses:
# 500 Internal Server Error (illegal database name)
if dbName == None : dbName = self.dbName
def buildUri(dbName=dbName, docId=docId, viewId=viewId, kwargs=kwargs):
return "/%s/_design/%s/_view/%s?%s" % (
dbName, quote(docId), viewId, urlencode(kwargs))
Expand Down Expand Up @@ -415,10 +416,11 @@ def addViews(self, document, views):
document["views"][name] = data


def tempView(self, dbName, view):
def tempView(self, view, dbName=None):
"""
Make a temporary view on the server.
"""
if dbName == None : dbName = self.dbName
d = self.post("/%s/_temp_view" % (dbName,), view, descr='tempView')
return d.addCallback(self.parseResult)

Expand Down
Loading