inoi / trombi

Trombi is an asynchronous CouchDB client for Tornado

Home Page:http://inoi.github.com/trombi

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Change Database.set() signature

mikek opened this issue · comments

set([doc_id], data, callback[, attachments=None]) has a really strange signature. It is the only method in trombi, which has first optional positional argument. Arguments parsing is manual (which can be then simplified). The real reason to change it, however, is inability to pass callback keyword argument. This does not allow to use tornado.gen to simplify asynchronous code.
I guess it can't be handled without changing method's signature and breaking existing code. At least the first argument would become required: set(doc_id, data, callback[, attachments=None]).
Please, let me know if there is a clean way to get around this particular issue.

The first argument is intentionally optional. If it wasn't optional and you already had a Document instance, you'd have to say db.set(doc.id, doc, callback) instead of just db.set(doc, callback). Making the callback keyword arg is possible without making doc_id a required argument.

Yeah, an ugly workaround is to respect additional callback keyword argument and cowardly append it to the *args. Requires nothing but trivial changes at the top of set() method:

     def set(self, *args, **kwargs):
+        cb = kwargs.pop('callback', None)
+        if cb:
+            args = list(args)
+            args.append(cb)
+            args = tuple(args)
         if len(args) == 2:
             data, callback = args
             doc_id = None
         elif len(args) == 3:
             doc_id, data, callback = args
         else:
-            raise TypeError(
-                'Database.set expected 2 or 3 arguments, got %d' % len(args))
+            raise TypeError('Database.set is missing callback argument')

This kind of change looks not so terrible looking at how it is now. Cleaner but backwards-incompatible way would require to change order of arguments.

Here's a more compact version:

     def set(self, *args, **kwargs):
+        cb = kwargs.pop('callback', None)
+        if cb:
+            args += (cb,)
         if len(args) == 2:
             data, callback = args
             doc_id = None
         elif len(args) == 3:
             doc_id, data, callback = args
         else:
-            raise TypeError(
-                'Database.set expected 2 or 3 arguments, got %d' % len(args))
+            raise TypeError('Database.set is missing callback argument')

I think this is the way to go.

@nailor Comments?

@mikek Thanks for the bug report! Making everything work with tornado.gen is top priority before 1.0 release of trombi and it's more than desired that bugs like this surface!

@akheron Your patch seems fine, go ahead and commit :)

The proposed error message is bad. If called with e.g. set(a, b, c, callback=d), the error message is 'Database.set is missing callback argument'.

Yeah, that's true. Maybe something along the lines TypeError("Database.set takes at most 2 non-keyword arguments.")

This is a bit misleading, as the user can give: set(a,b,c), which essentially has 3 positional arguments. However, I'm planning to update the documentation in a way that set will have clearly documented callback-keyword. Thus enabling the use of set(a, b, c) should be considered as a backwards compatible way of doing things.

Sounds good to me.

Hmm. Github failed to close this, however this is now fixed in b0a45d2