[Checkins] SVN: z3c.saconfig/trunk/src/z3c/saconfig/ Named session support; session directive; setup hook for engine factory (i.e. for mapper registration)
Laurence Rowe
l at lrowe.co.uk
Tue Aug 12 07:15:47 EDT 2008
Log message for revision 89707:
Named session support; session directive; setup hook for engine factory (i.e. for mapper registration)
Changed:
U z3c.saconfig/trunk/src/z3c/saconfig/README.txt
U z3c.saconfig/trunk/src/z3c/saconfig/__init__.py
U z3c.saconfig/trunk/src/z3c/saconfig/meta.zcml
U z3c.saconfig/trunk/src/z3c/saconfig/scopedsession.py
U z3c.saconfig/trunk/src/z3c/saconfig/tests.py
U z3c.saconfig/trunk/src/z3c/saconfig/utility.py
U z3c.saconfig/trunk/src/z3c/saconfig/zcml.py
-=-
Modified: z3c.saconfig/trunk/src/z3c/saconfig/README.txt
===================================================================
--- z3c.saconfig/trunk/src/z3c/saconfig/README.txt 2008-08-12 10:45:24 UTC (rev 89706)
+++ z3c.saconfig/trunk/src/z3c/saconfig/README.txt 2008-08-12 11:15:46 UTC (rev 89707)
@@ -324,3 +324,27 @@
>>> component.getUtility(IEngineFactory, name="dummy")
<z3c.saconfig.utility.EngineFactory object at ...>
+This time with a setup call.
+
+ >>> xmlconfig.xmlconfig(StringIO("""
+ ... <configure xmlns="http://namespaces.zope.org/db">
+ ... <engine name="dummy2" url="sqlite:///:memory:"
+ ... setup="z3c.saconfig.tests.engine_subscriber" />
+ ... </configure>"""))
+ got: Engine(sqlite:///:memory:)
+
+The session directive is provided to register a scoped session utility:
+
+ >>> xmlconfig.xmlconfig(StringIO("""
+ ... <configure xmlns="http://namespaces.zope.org/db">
+ ... <session name="dummy" engine="dummy2" />
+ ... </configure>"""))
+
+ >>> component.getUtility(IScopedSession, name="dummy")
+ <z3c.saconfig.utility.GloballyScopedSession object at ...>
+
+ >>> from z3c.saconfig import named_scoped_session
+ >>> factory = component.getUtility(IEngineFactory, name="dummy2")
+ >>> Session = named_scoped_session('dummy')
+ >>> Session().bind is factory()
+ True
Modified: z3c.saconfig/trunk/src/z3c/saconfig/__init__.py
===================================================================
--- z3c.saconfig/trunk/src/z3c/saconfig/__init__.py 2008-08-12 10:45:24 UTC (rev 89706)
+++ z3c.saconfig/trunk/src/z3c/saconfig/__init__.py 2008-08-12 11:15:46 UTC (rev 89707)
@@ -1,3 +1,3 @@
-from z3c.saconfig.scopedsession import Session
+from z3c.saconfig.scopedsession import Session, named_scoped_session
from z3c.saconfig.utility import (
GloballyScopedSession, SiteScopedSession, EngineFactory)
Modified: z3c.saconfig/trunk/src/z3c/saconfig/meta.zcml
===================================================================
--- z3c.saconfig/trunk/src/z3c/saconfig/meta.zcml 2008-08-12 10:45:24 UTC (rev 89706)
+++ z3c.saconfig/trunk/src/z3c/saconfig/meta.zcml 2008-08-12 11:15:46 UTC (rev 89707)
@@ -12,6 +12,12 @@
handler=".zcml.engine"
/>
+ <meta:directive
+ name="session"
+ schema=".zcml.ISessionDirective"
+ handler=".zcml.session"
+ />
+
</meta:directives>
</configure>
Modified: z3c.saconfig/trunk/src/z3c/saconfig/scopedsession.py
===================================================================
--- z3c.saconfig/trunk/src/z3c/saconfig/scopedsession.py 2008-08-12 10:45:24 UTC (rev 89706)
+++ z3c.saconfig/trunk/src/z3c/saconfig/scopedsession.py 2008-08-12 11:15:46 UTC (rev 89707)
@@ -3,22 +3,32 @@
from sqlalchemy.orm import scoped_session
from zope import component
-def session_factory():
+def session_factory(name=u''):
"""This is used by scoped session to create a new Session object.
It delegates to a IScopedSession utility.
"""
- utility = component.getUtility(IScopedSession)
+ utility = component.getUtility(IScopedSession, name)
return utility.sessionFactory()
-def scopefunc():
+def scopefunc(name=u''):
"""This is used by scoped session to distinguish between sessions.
It delegates to a IScopedSession utility.
"""
- utility = component.getUtility(IScopedSession)
+ utility = component.getUtility(IScopedSession, name)
return utility.scopeFunc()
# this is framework central configuration. Use a IScopedSession utility
# to define behavior.
Session = scoped_session(session_factory, scopefunc)
+
+_named_scoped_sessions = {}
+
+def named_scoped_session(name):
+ try:
+ return _named_scoped_sessions[name]
+ except KeyError:
+ return _named_scoped_sessions.setdefault(name,
+ scoped_session(lambda:session_factory(name),
+ lambda:scopefunc(name)))
Modified: z3c.saconfig/trunk/src/z3c/saconfig/tests.py
===================================================================
--- z3c.saconfig/trunk/src/z3c/saconfig/tests.py 2008-08-12 10:45:24 UTC (rev 89706)
+++ z3c.saconfig/trunk/src/z3c/saconfig/tests.py 2008-08-12 11:15:46 UTC (rev 89707)
@@ -89,7 +89,10 @@
# make sure hooks get cleaned up after tests are run
addCleanUp(resetHooks)
-
+
+def engine_subscriber(engine):
+ print "got: %s " % engine
+
def test_suite():
optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
globs = {
Modified: z3c.saconfig/trunk/src/z3c/saconfig/utility.py
===================================================================
--- z3c.saconfig/trunk/src/z3c/saconfig/utility.py 2008-08-12 10:45:24 UTC (rev 89706)
+++ z3c.saconfig/trunk/src/z3c/saconfig/utility.py 2008-08-12 11:15:46 UTC (rev 89707)
@@ -39,10 +39,13 @@
to pass the right arguments to the superclasses __init__.
"""
implements(IScopedSession)
-
- def __init__(self, **kw):
+
+ def __init__(self, engine=u'', **kw):
"""Pass keywords arguments for sqlalchemy.orm.create_session.
+ The `engine` argument is the name of a utility implementing
+ IEngineFactory.
+
Note that GloballyScopedSesssion does have different defaults than
``create_session`` for various parameters where it makes sense
for Zope integration, namely:
@@ -54,13 +57,14 @@
Normally you wouldn't pass these in, but if you have the need
to override them, you could.
"""
+ self.engine = engine
self.kw = _zope_session_defaults(kw)
def sessionFactory(self):
kw = self.kw.copy()
if 'bind' not in kw:
- # look up the engine using IEngineFactory if needed
- engine_factory = component.getUtility(IEngineFactory)
+ engine_factory = component.getUtility(IEngineFactory,
+ name=self.engine)
kw['bind'] = engine_factory()
return sqlalchemy.orm.create_session(**kw)
@@ -87,13 +91,15 @@
a SiteScopedSession utility without passing parameters to its constructor.
"""
implements(ISiteScopedSession)
-
- def __init__(self, **kw):
+
+ def __init__(self, engine=u'', **kw):
assert 'bind' not in kw
+ self.engine = engine
self.kw = _zope_session_defaults(kw)
def sessionFactory(self):
- engine_factory = component.getUtility(IEngineFactory)
+ engine_factory = component.getUtility(IEngineFactory,
+ name=self.engine)
kw = self.kw.copy()
kw['bind'] = engine_factory()
return sqlalchemy.orm.create_session(**kw)
Modified: z3c.saconfig/trunk/src/z3c/saconfig/zcml.py
===================================================================
--- z3c.saconfig/trunk/src/z3c/saconfig/zcml.py 2008-08-12 10:45:24 UTC (rev 89706)
+++ z3c.saconfig/trunk/src/z3c/saconfig/zcml.py 2008-08-12 11:15:46 UTC (rev 89707)
@@ -1,6 +1,7 @@
import zope.interface
import zope.schema
import zope.component.zcml
+import zope.dottedname.resolve
import utility
import interfaces
@@ -25,7 +26,42 @@
required=False,
default=False)
-def engine(_context, url, name=u"", echo=False):
+ setup = zope.schema.DottedName(
+ title=u'After engine creation hook',
+ description=u'Callback for creating mappers etc. One argument is passed, the engine',
+ required=False,
+ default=None)
+
+
+class ISessionDirective(zope.interface.Interface):
+ """Registers a database scoped session"""
+
+ name = zope.schema.Text(
+ title=u"Scoped session name",
+ description=u"Empty if this is the default session.",
+ required=False,
+ default=u"")
+
+ twophase = zope.schema.Bool(
+ title=u'Use two-phase commit',
+ description=u'Session should use two-phase commit',
+ required=False,
+ default=False)
+
+ engine = zope.schema.Text(
+ title=u"Engine name",
+ description=u"Empty if this is to use the default engine.",
+ required=False,
+ default=u"")
+
+ factory = zope.schema.DottedName(
+ title=u'Scoped Session utility factory',
+ description=u'GloballyScopedSession by default',
+ required=False,
+ default="z3c.saconfig.utility.GloballyScopedSession")
+
+
+def engine(_context, url, name=u"", echo=False, setup=None, twophase=False):
factory = utility.EngineFactory(url, echo=echo)
zope.component.zcml.utility(
@@ -34,4 +70,20 @@
component=factory,
permission=zope.component.zcml.PublicPermission,
name=name)
-
+
+ if setup:
+ callback = zope.dottedname.resolve.resolve(setup)
+ callback(factory())
+
+def session(_context, name=u"", engine=u"", twophase=False,
+ factory="z3c.saconfig.utility.GloballyScopedSession"):
+ ScopedSession = zope.dottedname.resolve.resolve(factory)
+ scoped_session = ScopedSession(engine=engine, twophase=twophase)
+
+ zope.component.zcml.utility(
+ _context,
+ provides=interfaces.IScopedSession,
+ component=scoped_session,
+ permission=zope.component.zcml.PublicPermission,
+ name=name)
+
More information about the Checkins
mailing list