[Checkins] SVN: z3c.zalchemy/sandbox/src/z3c/ refactored to z3c.zalchemy, added create to connect directive, TODO: fix tests

Bernd Dorn bernd.dorn at fhv.at
Fri Apr 21 06:25:36 EDT 2006


Log message for revision 67202:
  refactored to z3c.zalchemy, added create to connect directive, TODO: fix tests

Changed:
  A   z3c.zalchemy/sandbox/src/z3c/__init__.py
  U   z3c.zalchemy/sandbox/src/z3c/zalchemy/README.txt
  U   z3c.zalchemy/sandbox/src/z3c/zalchemy/datamanager.py
  U   z3c.zalchemy/sandbox/src/z3c/zalchemy/metaconfigure.py
  U   z3c.zalchemy/sandbox/src/z3c/zalchemy/metadirectives.py
  U   z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/TRANSACTION.txt
  U   z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/test_directives.py
  U   z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/test_zalchemy.py
  A   z3c.zalchemy/sandbox/src/z3c/zalchemy/z3c.zalchemy-configure.zcml
  A   z3c.zalchemy/sandbox/src/z3c/zalchemy/z3c.zalchemy-meta.zcml
  D   z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-configure.zcml
  D   z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-meta.zcml

-=-
Added: z3c.zalchemy/sandbox/src/z3c/__init__.py
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/__init__.py	2006-04-21 09:59:20 UTC (rev 67201)
+++ z3c.zalchemy/sandbox/src/z3c/__init__.py	2006-04-21 10:25:35 UTC (rev 67202)
@@ -0,0 +1,19 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""z3c.zalchemy integrates sqlalchemy into zope 3
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+


Property changes on: z3c.zalchemy/sandbox/src/z3c/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: z3c.zalchemy/sandbox/src/z3c/zalchemy/README.txt
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/README.txt	2006-04-21 09:59:20 UTC (rev 67201)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/README.txt	2006-04-21 10:25:35 UTC (rev 67202)
@@ -2,8 +2,8 @@
 SQLAlchemy and Zope 3
 =====================
 
-"zalchemy" integrates the object relational mapper sqlalchemy into zope 3
-as SQLOS integrates sqlobject.
+"z3c.zalchemy" integrates the object relational mapper sqlalchemy into
+zope 3 as SQLOS integrates sqlobject.
 
 zalchemy tries to do it's best not to interfere with the standard sqlalchemy
 usage.
@@ -23,26 +23,29 @@
 A SQLAlchemy engine is represented as a utility :
 
   >>> import os
-  >>> from zalchemy.datamanager import AlchemyEngineUtility
+  >>> from z3c.zalchemy.datamanager import AlchemyEngineUtility
   >>> engineUtil = AlchemyEngineUtility(
   ...     'sqlite',
   ...     dns='sqlite://',
   ...     )
 
-We create our tables as usual sqlalchemy table :
-Note that we use a ProxyEngine which is important here.
-The real connection to database engine will be done later in our utility.
+We create our tables as usual sqlalchemy table : 
 
   >>> import sqlalchemy
-  >>> engine = sqlalchemy.ext.proxy.ProxyEngine()
 
   >>> aTable = sqlalchemy.Table(
   ...     'aTable',
-  ...     engine,
   ...     sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True),
   ...     sqlalchemy.Column('value', sqlalchemy.Integer),
   ...     )
 
+Note that by not specifying an engine we use a ProxyEngine which is
+important here.  The real connection to database engine will be done
+later in our utility.
+
+  >>> aTable.engine
+  <sqlalchemy.ext.proxy.ProxyEngine object at ...>
+
 Define a simple class which will be used later to map to a database table.
 
   >>> class A(object):
@@ -52,10 +55,11 @@
 
   >>> sqlalchemy.assign_mapper(A, aTable)
 
-The next step is to connect the table to the database engine.
-We use our utility for that :
+The next step is to connect the table to the database engine.  We use
+our utility for that. The ``create`` argument tells the utility if it
+should try to create the table.
 
-  >>> engineUtil.addTable(aTable)
+  >>> engineUtil.addTable(aTable,create=True)
 
 To let zalchemy do his magic thing we need to register our database utility
 as a named utility :
@@ -66,26 +70,9 @@
 From now on zalchemy takes care of the zope transaction process behind the
 scenes :
 - connect the engine to the tables for every thread
-- create the tables in the database if not already done
 - handle the two phase commit process
 - disconnect the engine from the tables at the end of the thread
 
-Now let's try to use our database objects :
-
-  >>> a = A()
-  >>> a.value = 1
-  >>> sqlalchemy.objectstore.commit()
-  Traceback (most recent call last):
-  ...
-  AttributeError: No connection established
-
-Ups, this is because the tabel is not connected to a real database engine.
-We need to use zope transactions.
-
-First let's clear the current unit of work :
-
-  >>> sqlalchemy.objectstore.clear()
-
 Note that the transaction handling is done inside zope.
 
   >>> import transaction
@@ -93,7 +80,7 @@
 
 Then we need to simulate a beforeTraversal Event :
 
-  >>> from zalchemy.datamanager import beforeTraversal
+  >>> from z3c.zalchemy.datamanager import beforeTraversal
   >>> beforeTraversal(None)
 
   >>> a = A()
@@ -106,6 +93,8 @@
   >>> txn = transaction.begin()
   >>> beforeTraversal(None)
 
+XXX this is not the same db, use filebased db?
+
   >>> a = A.get(1)
   >>> a.value
   123
@@ -126,14 +115,13 @@
 
   >>> bTable = sqlalchemy.Table(
   ...     'bTable',
-  ...     engine,
   ...     sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True),
   ...     sqlalchemy.Column('value', sqlalchemy.String),
   ...     )
   >>> class B(object):
   ...     pass
   >>> sqlalchemy.assign_mapper(B, bTable)
-  >>> engine2Util.addTable(bTable)
+  >>> engine2Util.addTable(bTable,create=True)
 
   >>> txn = transaction.begin()
   >>> beforeTraversal(None)

Modified: z3c.zalchemy/sandbox/src/z3c/zalchemy/datamanager.py
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/datamanager.py	2006-04-21 09:59:20 UTC (rev 67201)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/datamanager.py	2006-04-21 10:25:35 UTC (rev 67202)
@@ -41,7 +41,7 @@
         self.storage = local()
         self.createdTables = {}
 
-    def addTable(self, table):
+    def addTable(self, table, create=False):
         if not isinstance(table.engine, sqlalchemy.ext.proxy.ProxyEngine):
             raise TypeError(table.engine)
         utils = getUtilitiesFor(IAlchemyEngineUtility)
@@ -50,15 +50,34 @@
                 #TODO: should raise an exception here
                 return
         self.tables.append(table)
+        if create:
+            self.createTable(table)
 
-    def connectTablesForThread(self):
-        # create a thread local engine
+    def createTable(self,table):
+
+        """tries to create the given table if not there"""
+        self.initEngine()
+        table.engine.engine = self.storage.engine
+        table.create()
+
+        
+    def initEngine(self):
+
+        """create a thread local engine if not there, returns True if
+        a new engine is created"""
+        
         engine=getattr(self.storage,'engine',None)
         if engine is not None:
-            return
+            return False
         self.storage.engine = create_engine(self.dns,
                                             self.kw,
                                             echo=self.echo)
+        return True
+
+    def connectTablesForThread(self):
+        # create a thread local engine
+        if not self.initEngine():
+            return
         engine = self.storage.engine
         # create a data manager
         if self.echo:
@@ -69,14 +88,6 @@
         # connect the tables to the engine
         for table in self.tables:
             table.engine.engine = engine
-            #TODO: this is a bad hack which must go away soon !
-            if table not in self.createdTables:
-                try:
-                    # make sure the table exists :
-                    table.create()
-                except:
-                    pass
-                self.createdTables[table]=True
 
     def dataManagerFinished(self):
         self.storage.engine=None

Modified: z3c.zalchemy/sandbox/src/z3c/zalchemy/metaconfigure.py
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/metaconfigure.py	2006-04-21 09:59:20 UTC (rev 67201)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/metaconfigure.py	2006-04-21 10:25:35 UTC (rev 67202)
@@ -25,15 +25,15 @@
             permission=PublicPermission,
             name=name)
 
-def connect(_context, engine, table):
+def connect(_context, engine, table, create=False):
     _context.action(
             discriminator = (engine, table),
             callable = connector,
-            args = (engine, table)
+            args = (engine, table, create)
             )
 
-def connector(engine, table):
+def connector(engine, table, create):
     util = component.getUtility(IAlchemyEngineUtility, engine)
-    util.addTable(table)
+    util.addTable(table,create=create)
     #connections.append((util, table))
 

Modified: z3c.zalchemy/sandbox/src/z3c/zalchemy/metadirectives.py
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/metadirectives.py	2006-04-21 09:59:20 UTC (rev 67201)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/metadirectives.py	2006-04-21 10:25:35 UTC (rev 67202)
@@ -13,7 +13,7 @@
 ##############################################################################
 from zope import interface
 from zope import schema
-from zope.configuration.fields import GlobalObject
+from zope.configuration.fields import GlobalObject,Bool
 
 
 class IEngineDirective(interface.Interface):
@@ -52,3 +52,5 @@
             required = True,
             )
 
+    create = Bool(title=u'Create Table',default=False,
+                  required=False)

Modified: z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/TRANSACTION.txt
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/TRANSACTION.txt	2006-04-21 09:59:20 UTC (rev 67201)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/TRANSACTION.txt	2006-04-21 10:25:35 UTC (rev 67202)
@@ -2,7 +2,7 @@
 ================================
 
 When a zope transaction is used also a sqlalchemy transaction must be
-activated. "zalchemy" installs a data manager every time a new zope
+activated. "z3c.zalchemy" installs a data manager every time a new zope
 transaction is created. 
 
 Setup zope's test environment :
@@ -13,9 +13,9 @@
 Create a utility to provide a database :
 
   >>> from zope.component import provideUtility
-  >>> from zalchemy.datamanager import AlchemyEngineUtility
+  >>> from z3c.zalchemy.datamanager import AlchemyEngineUtility
   >>> engineUtility = AlchemyEngineUtility('database',
-  ...                                      'sqlite://filename=abc.db',
+  ...                                      'sqlite://filename=/tmp/abc.db',
   ...                                      echo=False)
   >>> provideUtility(engineUtility, name="test")
 
@@ -40,7 +40,7 @@
 
   >>> import os
   >>> try:
-  ...     os.remove('abc.db')
+  ...     os.remove('/tmp/abc.db')
   ... except:
   ...     pass
 
@@ -57,7 +57,7 @@
 
 Now we need to connect our table to a real engine :
 
-  >>> from zalchemy.datamanager import beforeTraversal
+  >>> from z3c.zalchemy.datamanager import beforeTraversal
   >>> beforeTraversal(None)
 
   >>> aTable.engine.engine is not None
@@ -143,8 +143,16 @@
 
 Connect the new table to the already existing database :
 
-  >>> engineUtility.addTable(bTable)
+  >>> engineUtility.addTable(bTable,create=True)
+  >>> not not bTable.engine.engine
+  True
 
+The table should now be created.
+
+  >>> c = bTable.engine.engine.execute("select * from bTable")
+  >>> [row for row in c]
+  []
+
   >>> log = []
   >>> def createB():
   ...     txn = transaction.begin()
@@ -169,6 +177,10 @@
   >>> log
   [1]
 
+XXX why do we have to do this?
+
+  >>> transaction.get().commit()  
+
   >>> log = []
   >>> thread = threading.Thread(target=doB)
   >>> thread.start()

Modified: z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/test_directives.py
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/test_directives.py	2006-04-21 09:59:20 UTC (rev 67201)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/test_directives.py	2006-04-21 10:25:35 UTC (rev 67202)
@@ -7,8 +7,8 @@
 from zope.testing.doctestunit import DocTestSuite
 from zope.app.testing.placelesssetup import PlacelessSetup
 
-import zalchemy
-from zalchemy.interfaces import IAlchemyEngineUtility
+import z3c.zalchemy
+from z3c.zalchemy.interfaces import IAlchemyEngineUtility
 
 template = """<configure
    xmlns='http://namespaces.zope.org/zope'
@@ -22,7 +22,7 @@
 
     def setUp(self):
         super(TestDirectives, self).setUp()
-        XMLConfig('meta.zcml', zalchemy)()
+        XMLConfig('meta.zcml', z3c.zalchemy)()
 
     def testEngineDirective(self):
         xmlconfig(StringIO(template % (
@@ -53,14 +53,14 @@
                 />
             <alchemy:connect
                 engine="sqlite-in-memory"
-                table="zalchemy.tests.environ.testTable"
+                table="z3c.zalchemy.tests.environ.testTable"
                 />
             '''
             )))
         util = component.getUtility(IAlchemyEngineUtility,'sqlite-in-memory')
         self.assert_(len(util.tables)==1)
         self.assertEqual(util.tables[0],
-                         zalchemy.tests.environ.testTable)
+                         z3c.zalchemy.tests.environ.testTable)
 
     def tearDown(self):
         PlacelessSetup.tearDown(self)

Modified: z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/test_zalchemy.py
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/test_zalchemy.py	2006-04-21 09:59:20 UTC (rev 67201)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/tests/test_zalchemy.py	2006-04-21 10:25:35 UTC (rev 67202)
@@ -1,11 +1,28 @@
 import unittest
+import doctest
 from zope.testing.doctestunit import DocFileSuite
+from zope.app.testing import setup
 
+def setUp(test):
+    setup.placefulSetUp()
+
+
+def tearDown(test):
+    setup.placefulTearDown()
+
+
+
 def test_suite():
     return unittest.TestSuite((
-            DocFileSuite('TRANSACTION.txt'),
-            DocFileSuite('../README.txt'),
-            ))
+        DocFileSuite('../README.txt',
+                     setUp=setUp, tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        DocFileSuite('TRANSACTION.txt',
+                     setUp=setUp, tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        ))
 
 if __name__ == '__main__':
     unittest.main(defaultTest='test_suite')

Copied: z3c.zalchemy/sandbox/src/z3c/zalchemy/z3c.zalchemy-configure.zcml (from rev 67198, z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-configure.zcml)
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-configure.zcml	2006-04-21 08:24:00 UTC (rev 67198)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/z3c.zalchemy-configure.zcml	2006-04-21 10:25:35 UTC (rev 67202)
@@ -0,0 +1 @@
+<include package="z3c.zalchemy"/>

Copied: z3c.zalchemy/sandbox/src/z3c/zalchemy/z3c.zalchemy-meta.zcml (from rev 67198, z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-meta.zcml)
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-meta.zcml	2006-04-21 08:24:00 UTC (rev 67198)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/z3c.zalchemy-meta.zcml	2006-04-21 10:25:35 UTC (rev 67202)
@@ -0,0 +1 @@
+<include package="z3c.zalchemy" file="meta.zcml" />

Deleted: z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-configure.zcml
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-configure.zcml	2006-04-21 09:59:20 UTC (rev 67201)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-configure.zcml	2006-04-21 10:25:35 UTC (rev 67202)
@@ -1 +0,0 @@
-<include package="zalchemy"/>

Deleted: z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-meta.zcml
===================================================================
--- z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-meta.zcml	2006-04-21 09:59:20 UTC (rev 67201)
+++ z3c.zalchemy/sandbox/src/z3c/zalchemy/zalchemy-meta.zcml	2006-04-21 10:25:35 UTC (rev 67202)
@@ -1 +0,0 @@
-<include package="zalchemy" file="meta.zcml" />



More information about the Checkins mailing list