[Sqlalchemy-commits] [1336] sqlalchemy/branches/schema/lib/sqlalchemy/ext/sessioncontext.py: initial
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-04-25 05:44:21
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1336] sqlalchemy/branches/schema/lib/sqlalchemy/ext/sessioncontext.py: initial checkin for dan miller's SessionContext implementation</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1336</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-04-25 00:44:11 -0500 (Tue, 25 Apr 2006)</dd> </dl> <h3>Log Message</h3> <pre>initial checkin for dan miller's SessionContext implementation</pre> <h3>Added Paths</h3> <ul> <li><a href="#sqlalchemybranchesschemalibsqlalchemyextsessioncontextpy">sqlalchemy/branches/schema/lib/sqlalchemy/ext/sessioncontext.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesschemalibsqlalchemyextsessioncontextpy"></a> <div class="addfile"><h4>Added: sqlalchemy/branches/schema/lib/sqlalchemy/ext/sessioncontext.py (1335 => 1336)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/ext/sessioncontext.py 2006-04-25 01:57:51 UTC (rev 1335) +++ sqlalchemy/branches/schema/lib/sqlalchemy/ext/sessioncontext.py 2006-04-25 05:44:11 UTC (rev 1336) </span><span class="lines">@@ -0,0 +1,118 @@ </span><ins>+from sqlalchemy.util import ScopedRegistry + +class SessionContext(object): + """A simple wrapper for ScopedRegistry that provides a "current" property + which can be used to get, set, or remove the session in the current scope. + + By default this object provides thread-local scoping, which is the default + scope provided by sqlalchemy.util.ScopedRegistry. + + Usage: + engine = create_engine(...) + def session_factory(): + return Session(bind_to=engine) + context = SessionContext(session_factory) + + s = context.current # get thread-local session + context.current = Session(bind_to=other_engine) # set current session + del context.current # discard the thread-local session (a new one will + # be created on the next call to context.current) + """ + def __init__(self, session_factory, scopefunc=None): + self.registry = ScopedRegistry(session_factory, scopefunc) + super(SessionContext, self).__init__() + + def get_current(self): + return self.registry() + def set_current(self, session): + self.registry.set(session) + def del_current(self): + self.registry.clear() + current = property(get_current, set_current, del_current, + """Property used to get/set/del the session in the current scope""") + + def create_metaclass(session_context): + """return a metaclass to be used by objects that wish to be bound to a + thread-local session upon instantiatoin. + + Note non-standard use of session_context rather than self as the name + of the first arguement of this method. + + Usage: + context = SessionContext(...) + class MyClass(object): + __metaclass__ = context.metaclass + ... + """ + try: + return session_context._metaclass + except AttributeError: + class metaclass(type): + def __init__(cls, name, bases, dct): + old_init = getattr(cls, "__init__") + def __init__(self, *args, **kwargs): + session_context.current.save(self) + old_init(self, *args, **kwargs) + setattr(cls, "__init__", __init__) + super(metaclass, cls).__init__(name, bases, dct) + session_context._metaclass = metaclass + return metaclass + metaclass = property(create_metaclass) + + def create_baseclass(session_context): + """return a baseclass to be used by objects that wish to be bound to a + thread-local session upon instantiatoin. + + Note non-standard use of session_context rather than self as the name + of the first arguement of this method. + + Usage: + context = SessionContext(...) + class MyClass(context.baseclass): + ... + """ + try: + return session_context._baseclass + except AttributeError: + class baseclass(object): + def __init__(self, *args, **kwargs): + session_context.current.save(self) + super(baseclass, self).__init__(*args, **kwargs) + session_context._baseclass = baseclass + return baseclass + baseclass = property(create_baseclass) + + +def test(): + + def run_test(class_, context): + obj = class_() + assert context.current == get_session(obj) + + # keep a reference so the old session doesn't get gc'd + old_session = context.current + + context.current = create_session() + assert context.current != get_session(obj) + assert old_session == get_session(obj) + + del context.current + assert context.current != get_session(obj) + assert old_session == get_session(obj) + + obj2 = class_() + assert context.current == get_session(obj2) + + # test metaclass + context = SessionContext(create_session) + class MyClass(object): __metaclass__ = context.metaclass + run_test(MyClass, context) + + # test baseclass + context = SessionContext(create_session) + class MyClass(context.baseclass): pass + run_test(MyClass, context) + +if __name__ == "__main__": + test() + print "All tests passed!" </ins></span></pre> </div> </div> </body> </html> |