decorator to fetch arguments from global objects

Wolfgang Maier wolfgang.maier at biologie.uni-freiburg.de
Tue Jun 18 09:25:52 EDT 2013


andrea crotti <andrea.crotti.0 <at> gmail.com> writes:

> 
> 
> Using a CouchDB server we have a different database object potentially for
every request.
> 
> We already set that db in the request object to make it easy to pass it
around form our django app, however it would be nice if I could set it once
in the API and automatically fetch it from there.
> 
> Basically I have something like
> 
> class Entity:
>      def save_doc(db)
>         ...
> 
> I would like basically to decorate this function in such a way that:
> - if I pass a db object use it
> - if I don't pass it in try to fetch it from a global object
> - if both don't exist raise an exception
> 
> Now it kinda of works already with the decorator below.
> The problem is that the argument is positional so I end up maybe passing
it twice.
> So I have to enforce that 'db' if there is passed as first argument..
> 
> It would be a lot easier removing the db from the arguments but then it
would look too magic and I didn't want to change the signature.. any other
advice?
> 
> def with_optional_db(func):
>     """Decorator that sets the database to the global current one if
>     not passed in or if passed in and None
>     """
>      <at> wraps(func)
>     def _with_optional_db(*args, **kwargs):
>         func_args = func.func_code.co_varnames
>         db = None
>         # if it's defined in the first elements it needs to be
>         # assigned to *args, otherwise to kwargs
>         if 'db' in func_args:
>             assert 'db' == func_args[0], "Needs to be the first defined"
>         else:
>             db = kwargs.get('db', None)
> 
>         if db is None:
>             kwargs['db'] = get_current_db()
> 
>         assert kwargs['db'] is not None, "Can't have a not defined database"
>         ret = func(*args, **kwargs)
>         return ret
> 
>     return _with_optional_db
> 

I'm not sure, whether your code would work. I get the logic for the db in
kwargs case, but why are you checking whether db is in func_args? Isn't the
real question whether it's in args ?? In general, I don't understand why you
want to use .func_code.co_varnames here. You know how you defined your
function (or rather method):
class Entity:
    def save_doc(db):
        ...
Maybe I misunderstood the problem?
Wolfgang







More information about the Python-list mailing list