--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/iro/model/dbdefer.py Thu Sep 27 17:15:46 2012 +0200
@@ -0,0 +1,92 @@
+# 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
+
+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."""
+
+def setEngine(engine,autocommit=False):
+ """set the engine and autocommit for the decorator (see :class:`DBDefer`)."""
+ dbdefer.engine = engine
+ dbdefer.autocommit = autocommit
+
+