[Checkins] SVN: Sandbox/faassen/rdbintegration/ Initial import.
Martijn Faassen
faassen at infrae.com
Mon Jun 16 14:28:34 EDT 2008
Log message for revision 87431:
Initial import.
Changed:
A Sandbox/faassen/rdbintegration/
A Sandbox/faassen/rdbintegration/trunk/
A Sandbox/faassen/rdbintegration/trunk/buildout.cfg
A Sandbox/faassen/rdbintegration/trunk/setup.py
A Sandbox/faassen/rdbintegration/trunk/src/
A Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/
A Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/__init__.py
A Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/app.py
A Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/app_templates/
A Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/configure.zcml
A Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/ftesting.zcml
A Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/testing.py
-=-
Added: Sandbox/faassen/rdbintegration/trunk/buildout.cfg
===================================================================
--- Sandbox/faassen/rdbintegration/trunk/buildout.cfg (rev 0)
+++ Sandbox/faassen/rdbintegration/trunk/buildout.cfg 2008-06-16 18:28:31 UTC (rev 87431)
@@ -0,0 +1,66 @@
+[buildout]
+develop = .
+parts = app data zopectl i18n test
+find-links = http://download.zope.org/distribution/
+eggs-directory = /home/faassen/buildout-eggs
+newest = false
+extends= http://grok.zope.org/releaseinfo/grok-0.12.1.cfg
+versions = versions
+
+[app]
+recipe = zc.zope3recipes>=0.5.3:application
+eggs = rdbintegration
+site.zcml = <include package="rdbintegration" />
+ <include package="zope.app.twisted" />
+
+ <configure i18n_domain="rdbintegration">
+ <unauthenticatedPrincipal id="zope.anybody"
+ title="Unauthenticated User" />
+ <unauthenticatedGroup id="zope.Anybody"
+ title="Unauthenticated Users" />
+ <authenticatedGroup id="zope.Authenticated"
+ title="Authenticated Users" />
+ <everybodyGroup id="zope.Everybody"
+ title="All Users" />
+ <principal id="zope.manager"
+ title="Manager"
+ login="admin"
+ password_manager="Plain Text"
+ password="admin"
+ />
+
+ <!-- Replace the following directive if you don't want
+ public access -->
+ <grant permission="zope.View"
+ principal="zope.Anybody" />
+ <grant permission="zope.app.dublincore.view"
+ principal="zope.Anybody" />
+
+ <role id="zope.Manager" title="Site Manager" />
+ <role id="zope.Member" title="Site Member" />
+ <grantAll role="zope.Manager" />
+ <grant role="zope.Manager"
+ principal="zope.manager" />
+ </configure>
+
+[data]
+recipe = zc.recipe.filestorage
+
+# this section named so that the start/stop script is called bin/zopectl
+[zopectl]
+recipe = zc.zope3recipes:instance
+application = app
+zope.conf = ${data:zconfig}
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = rdbintegration
+defaults = ['--tests-pattern', '^f?tests$', '-v']
+
+# this section named so that the i18n scripts are called bin/i18n...
+[i18n]
+recipe = lovely.recipe:i18n
+package = rdbintegration
+domain = rdbintegration
+location = src/rdbintegration
+output = locales
Added: Sandbox/faassen/rdbintegration/trunk/setup.py
===================================================================
--- Sandbox/faassen/rdbintegration/trunk/setup.py (rev 0)
+++ Sandbox/faassen/rdbintegration/trunk/setup.py 2008-06-16 18:28:31 UTC (rev 87431)
@@ -0,0 +1,24 @@
+from setuptools import setup, find_packages
+
+setup(name='rdbintegration',
+ version="0.1",
+ description="An SQLAlchemy integration experiment",
+ classifiers=[],
+ author="Martijn Faassen",
+ author_email="faassen at startifact.com",
+ license="ZPL",
+ package_dir={'': 'src'},
+ packages=find_packages('src'),
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=['setuptools',
+ 'grok',
+ 'SQLAlchemy == 0.5beta1',
+ 'zope.sqlalchemy',
+ 'psycopg2',
+ # Add extra requirements here
+ ],
+ entry_points="""
+ # Add entry points here
+ """,
+ )
Added: Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/__init__.py
===================================================================
--- Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/__init__.py (rev 0)
+++ Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/__init__.py 2008-06-16 18:28:31 UTC (rev 87431)
@@ -0,0 +1 @@
+# this directory is a package
Added: Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/app.py
===================================================================
--- Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/app.py (rev 0)
+++ Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/app.py 2008-06-16 18:28:31 UTC (rev 87431)
@@ -0,0 +1,176 @@
+"""An experiment in integration with SQLAlchemy.
+
+The main goal of this experiment is to allow the user to instantiate a
+Session object in the normal SQLAlchemy way. This session object is
+however also fully aware of Zope transactions (thanks to
+zope.sqlalchemy), and moreover, is managed automatically by SQLAlchemy
+per-thread and per-application, using SQLAlchemy's ScopedSession.
+
+The applications to install expose 2 relevant URLs:
+
+* index - edit the name of the engine this app uses. (engine1, engine2)
+
+* db - do a simple db query
+
+The application expects a database with a 'test' table, which has an
+'id' primary key and a 'name' text column. These databases are
+currently Postgresql databases, experiment and experiment2. For the
+experiment, they should each have different information the test table
+(name column).
+
+You can create applications and set their engine using the index
+view. You can then use 'db' to look at the query. The result should be
+different if you set the engine differently. If you change the engine
+while the application is running, it will have no effect as the same
+session will still be reused (with the old engine bound to it). Instead
+you can restart the application to see the effect.
+
+This experiment will hopefully result in a new Zope 3 extension that
+allows the use of this pattern of configuration.
+
+Note that this experiment uses Grok, but the fundamental mechanics are
+not related to Grok. The ORM mapping bits are also just to test whether
+things work, not fundamental to the example.
+"""
+
+import grok
+from zope import schema
+
+from sqlalchemy.orm import scoped_session
+from zope import component
+from zope.interface import Interface
+import thread
+from sqlalchemy.orm import mapper
+from sqlalchemy.orm.session import Session as _Session
+from zope.sqlalchemy import ZopeTransactionExtension
+from sqlalchemy import create_engine
+import sqlalchemy as sa
+
+class IDatabase(Interface):
+ """A utility that specifies the database.
+ """
+
+ def engine():
+ """Get the engine in use for this database session.
+
+ The engine is not created on the fly. Each time the engine is
+ looked up for a site (application), the same engine should be found.
+ """
+
+ def configuration():
+ """Get all configuration parameters for Session.
+
+ This should give the configuration parameters to be used for
+ a session in this site.
+ """
+
+ def id():
+ """Get unique id for this database configuration.
+
+ This should be unique per site (application).
+ """
+
+class Database(grok.LocalUtility):
+ grok.implements(IDatabase)
+
+ def engine(self):
+ # we look up the engine with the name defined in the application
+ return component.getUtility(IEngine, self.__parent__.engine_name)
+
+ def configuration(self):
+ # we return the configuration parameters as for an
+ # SQLAlchemy sessionmaker
+ return dict(
+ bind=self.engine(),
+ autocommit=True,
+ autoflush=True,
+ extension=ZopeTransactionExtension())
+
+ def id(self):
+ # we use the application name as the unique id. Can we use
+ # something more clever and universally working?
+ return self.__parent__.__name__
+
+class IEngine(Interface):
+ """The database engine.
+ """
+
+# we register the available engines as global utilities.
+# we want to be able to configure the engines, preferably also through
+# the UI. This might mean we need to register the engine as a local,
+# non-persistent utility that is somehow recreated on each restart.
+engine1 = create_engine('postgres:///experiment', convert_unicode=True)
+grok.global_utility(engine1, provides=IEngine, direct=True, name='engine1')
+
+engine2 = create_engine('postgres:///experiment2', convert_unicode=True)
+grok.global_utility(engine2, provides=IEngine, direct=True, name='engine2')
+
+def session_factory():
+ """This is used by scoped session to create a new Session object.
+ """
+ utility = component.getUtility(IDatabase)
+ print "Creating new session"
+ return _Session(**utility.configuration())
+
+def scopefunc():
+ """This is used by scoped session to distinguish between sessions.
+
+ We distinguish between sessions by thread id and IDatabase unique
+ application id.
+ """
+ utility = component.getUtility(IDatabase)
+ result = (thread.get_ident(), utility.id())
+ print "Scope: ", result
+ return result
+
+# this is a frame-work central configuration, we only need to do this
+# once in our integration framework, after which we can just import
+# Session
+Session = scoped_session(session_factory,
+ scopefunc)
+
+# an application that allows the configuration of the engine name
+class IForm(Interface):
+ engine_name = schema.TextLine(title=u"Engine name")
+
+class App(grok.Application, grok.Container):
+ grok.local_utility(Database, provides=IDatabase, public=True,
+ name_in_container='database')
+
+ grok.implements(IForm)
+
+ engine_name = ''
+
+class Index(grok.EditForm):
+ grok.context(App)
+
+ form_fields = grok.Fields(IForm)
+
+ @grok.action("Submit")
+ def submit(self, engine_name):
+ self.context.engine_name = engine_name
+
+# here we define the table information and inform the ORM of the mapping
+# this is not part of the experiment, just so we can test things.
+class Test(object):
+ """An object that is mapped with the ORM"""
+ pass
+
+metadata = sa.MetaData()
+test_table = sa.Table('test', metadata,
+ sa.Column('id', sa.Integer, primary_key=True),
+ sa.Column('name', sa.Text))
+mapper(Test, test_table)
+
+# the db view does a query in the Test table using the ORM. It uses
+# an instance of Session to do so. This is to verify that our scoped session
+# is working; it will automatically use a cached session.
+class Db(grok.View):
+ grok.context(App)
+
+ def render(self):
+ # this is the normal SQLAlchemy usage: just instantiate
+ # Session. No special Zope-related lookup logic
+ session = Session()
+ result = session.query(Test).all()
+ return repr([obj.name for obj in result])
Added: Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/configure.zcml
===================================================================
--- Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/configure.zcml (rev 0)
+++ Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/configure.zcml 2008-06-16 18:28:31 UTC (rev 87431)
@@ -0,0 +1,6 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:grok="http://namespaces.zope.org/grok">
+ <include package="grok" />
+ <includeDependencies package="." />
+ <grok:grok package="." />
+</configure>
Added: Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/ftesting.zcml
===================================================================
--- Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/ftesting.zcml (rev 0)
+++ Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/ftesting.zcml 2008-06-16 18:28:31 UTC (rev 87431)
@@ -0,0 +1,35 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ i18n_domain="rdbintegration"
+ package="rdbintegration"
+ >
+
+ <include package="grok" />
+ <include package="rdbintegration" />
+
+ <!-- Typical functional testing security setup -->
+ <securityPolicy
+ component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy"
+ />
+
+ <unauthenticatedPrincipal
+ id="zope.anybody"
+ title="Unauthenticated User"
+ />
+ <grant
+ permission="zope.View"
+ principal="zope.anybody"
+ />
+
+ <principal
+ id="zope.mgr"
+ title="Manager"
+ login="mgr"
+ password="mgrpw"
+ />
+
+ <role id="zope.Manager" title="Site Manager" />
+ <grantAll role="zope.Manager" />
+ <grant role="zope.Manager" principal="zope.mgr" />
+
+</configure>
Added: Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/testing.py
===================================================================
--- Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/testing.py (rev 0)
+++ Sandbox/faassen/rdbintegration/trunk/src/rdbintegration/testing.py 2008-06-16 18:28:31 UTC (rev 87431)
@@ -0,0 +1,7 @@
+import os.path
+import rdbintegration
+from zope.app.testing.functional import ZCMLLayer
+
+ftesting_zcml = os.path.join(
+ os.path.dirname(rdbintegration.__file__), 'ftesting.zcml')
+FunctionalLayer = ZCMLLayer(ftesting_zcml, __name__, 'FunctionalLayer')
More information about the Checkins
mailing list