Source code for iro.model.dbdefer

# Copyright (c) 2012 netzguerilla.net <iro@netzguerilla.net>
# 
# This file is part of Iro.
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
# #Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

from decorator import FunctionMaker
import sqlalchemy

from .pool import runInDBPool
from .utils import WithSession

import inspect

[docs]class DBDefer(object): '''a twisted sqlalchemy connector. This is used as a Decorator class. It adds a session parameter to the function with a valid session. If the session parmaeter is used in calling this function only calls a commit after running the function, instead of createing a new session.''' def __init__(self, engine, autocommit=False): """ :param `sqlalchemy.engine.base.Engine` engine: a valid sqlalchemy engine object (normally created via :func:`sqlalchemy.create_engine`). :param boolean autocommit: autocommit after running the function. """ self.autocommit=autocommit self.engine = engine def __call__(self, func): @runInDBPool def wrapper(func,*a, **kw): i = argspec.args.index("session") ab = a[:i] ae = a[i:-1] if isinstance(a[-1],sqlalchemy.orm.session.Session): al = ab + (a[-1],) + ae ret = func(*al, **kw) if self.autocommit: a[-1].commit() return ret else: with WithSession(self.engine, self.autocommit) as session: al = ab + (session,) + ae return func(*al, **kw) caller=func argspec = inspect.getargspec(caller) args =[i for i in argspec.args if i != "session" ] sargs=", ".join(args) if sargs: sargs+=", session" else: sargs="session" defaults = argspec.defaults if not defaults: defaults = (None,) else: defaults += (None,) evaldict = caller.func_globals.copy() evaldict['_call_'] = func evaldict['decorator'] = wrapper wrap = FunctionMaker.create( '%s(%s)' % (caller.__name__, sargs), 'return decorator(_call_, %s)' % sargs, evaldict, defaults=defaults, undecorated=caller, __wrapped__=caller, doc=caller.__doc__, module=caller.__module__, addsource=True) return wrap
dbdefer=DBDefer(None) """the decorator to use. Use :func:`setEngine` to set a valid engine after program has started."""
[docs]def setEngine(engine,autocommit=False): """set the engine and autocommit for the decorator (see :class:`DBDefer`).""" dbdefer.engine = engine dbdefer.autocommit = autocommit