[Zodb-checkins] SVN: ZODB/trunk/src/ZODB/ The databasesFrom... methods now support multiple databases.

Jim Fulton jim at zope.com
Thu Apr 30 07:43:49 EDT 2009


Log message for revision 99604:
  The databasesFrom... methods now support multiple databases.
  
  Added an option to disallow cross-database references.
  

Changed:
  U   ZODB/trunk/src/ZODB/config.py
  U   ZODB/trunk/src/ZODB/config.xml
  U   ZODB/trunk/src/ZODB/tests/testConfig.py

-=-
Modified: ZODB/trunk/src/ZODB/config.py
===================================================================
--- ZODB/trunk/src/ZODB/config.py	2009-04-30 11:43:47 UTC (rev 99603)
+++ ZODB/trunk/src/ZODB/config.py	2009-04-30 11:43:49 UTC (rev 99604)
@@ -49,9 +49,16 @@
     config, handler = ZConfig.loadConfig(getDbSchema(), url)
     return databaseFromConfig(config.database)
 
-def databaseFromConfig(section):
-    return section.open()
+def databaseFromConfig(database_factories):
+    databases = {}
+    first = None
+    for factory in database_factories:
+        db = factory.open(databases)
+        if first is None:
+            first = db
 
+    return first
+
 def storageFromString(s):
     return storageFromFile(StringIO(s))
 
@@ -93,9 +100,17 @@
         section = self.config
         storage = section.storage.open()
         options = {}
-        if section.pool_timeout is not None:
-            options['pool_timeout'] = section.pool_timeout
 
+        def _option(name, oname=None):
+            v = getattr(section, name)
+            if v is not None:
+                if oname is None:
+                    oname = name
+                options[oname] = v
+
+        _option('pool_timeout')
+        _option('allow_implicit_cross_references', 'xrefs')
+
         try:
             return ZODB.DB(
                 storage,
@@ -106,7 +121,7 @@
                 historical_cache_size=section.historical_cache_size,
                 historical_cache_size_bytes=section.historical_cache_size_bytes,
                 historical_timeout=section.historical_timeout,
-                database_name=section.database_name,
+                database_name=section.database_name or self.name or '',
                 databases=databases,
                 **options)
         except:

Modified: ZODB/trunk/src/ZODB/config.xml
===================================================================
--- ZODB/trunk/src/ZODB/config.xml	2009-04-30 11:43:47 UTC (rev 99603)
+++ ZODB/trunk/src/ZODB/config.xml	2009-04-30 11:43:49 UTC (rev 99604)
@@ -2,6 +2,7 @@
 
   <import package="ZODB"/>
 
-  <section type="ZODB.database" name="*" attribute="database"/>
+  <multisection type="ZODB.database" name="*" attribute="database"
+                required="yes" />
 
 </schema>

Modified: ZODB/trunk/src/ZODB/tests/testConfig.py
===================================================================
--- ZODB/trunk/src/ZODB/tests/testConfig.py	2009-04-30 11:43:47 UTC (rev 99603)
+++ ZODB/trunk/src/ZODB/tests/testConfig.py	2009-04-30 11:43:49 UTC (rev 99604)
@@ -12,23 +12,26 @@
 #
 ##############################################################################
 
-import os
+import doctest
+import tempfile
+import unittest
+
 import transaction
-import unittest
-import ZEO.ClientStorage
 import ZODB.config
-import ZODB.POSException
-import ZODB.tests.util
-from zope.testing import doctest
+from ZODB.POSException import ReadOnlyError
 
-class ConfigTestBase(ZODB.tests.util.TestCase):
 
+class ConfigTestBase(unittest.TestCase):
     def _opendb(self, s):
         return ZODB.config.databaseFromString(s)
 
+    def tearDown(self):
+        if getattr(self, "storage", None) is not None:
+            self.storage.cleanup()
+
     def _test(self, s):
         db = self._opendb(s)
-        self.storage = db.storage
+        self.storage = db._storage
         # Do something with the database to make sure it works
         cn = db.open()
         rt = cn.root()
@@ -56,26 +59,28 @@
             """)
 
     def test_file_config1(self):
+        path = tempfile.mktemp()
         self._test(
             """
             <zodb>
               <filestorage>
-                path Data.fs
+                path %s
               </filestorage>
             </zodb>
-            """)
+            """ % path)
 
     def test_file_config2(self):
+        path = tempfile.mktemp()
         cfg = """
         <zodb>
           <filestorage>
-            path Data.fs
+            path %s
             create false
             read-only true
           </filestorage>
         </zodb>
-        """
-        self.assertRaises(ZODB.POSException.ReadOnlyError, self._test, cfg)
+        """ % path
+        self.assertRaises(ReadOnlyError, self._test, cfg)
 
     def test_demo_config(self):
         cfg = """
@@ -110,54 +115,116 @@
         </zodb>
         """
         config, handle = ZConfig.loadConfigFile(getDbSchema(), StringIO(cfg))
-        self.assertEqual(config.database.config.storage.config.blob_dir,
+        self.assertEqual(config.database[0].config.storage.config.blob_dir,
                          None)
         self.assertRaises(ClientDisconnected, self._test, cfg)
 
         cfg = """
         <zodb>
           <zeoclient>
-            blob-dir blobs
+            blob-dir /tmp
             server localhost:56897
             wait false
           </zeoclient>
         </zodb>
         """
         config, handle = ZConfig.loadConfigFile(getDbSchema(), StringIO(cfg))
-        self.assertEqual(
-            os.path.abspath(config.database.config.storage.config.blob_dir),
-            os.path.abspath('blobs'))
+        self.assertEqual(config.database[0].config.storage.config.blob_dir,
+                         '/tmp')
         self.assertRaises(ClientDisconnected, self._test, cfg)
 
-def db_connection_pool_timeout():
+def database_xrefs_config():
+    r"""
+    >>> db = ZODB.config.databaseFromString(
+    ...    "<zodb>\n<mappingstorage>\n</mappingstorage>\n</zodb>\n")
+    >>> db.xrefs
+    True
+    >>> db = ZODB.config.databaseFromString(
+    ...    "<zodb>\nallow-implicit-cross-references true\n"
+    ...    "<mappingstorage>\n</mappingstorage>\n</zodb>\n")
+    >>> db.xrefs
+    True
+    >>> db = ZODB.config.databaseFromString(
+    ...    "<zodb>\nallow-implicit-cross-references false\n"
+    ...    "<mappingstorage>\n</mappingstorage>\n</zodb>\n")
+    >>> db.xrefs
+    False
     """
-Test that the database pool timeout option works:
 
+def multi_atabases():
+    r"""If there are multiple codb sections -> multidatabase
+
     >>> db = ZODB.config.databaseFromString('''
-    ...     <zodb>
-    ...       <mappingstorage/>
-    ...     </zodb>
+    ... <zodb>
+    ...    <mappingstorage>
+    ...    </mappingstorage>
+    ... </zodb>
+    ... <zodb Foo>
+    ...    <mappingstorage>
+    ...    </mappingstorage>
+    ... </zodb>
+    ... <zodb>
+    ...    database-name Bar
+    ...    <mappingstorage>
+    ...    </mappingstorage>
+    ... </zodb>
     ... ''')
-    >>> db.pool._timeout == 1<<31
-    True
+    >>> sorted(db.databases)
+    ['', 'Bar', 'foo']
 
-    >>> db = ZODB.config.databaseFromString('''
-    ...     <zodb>
-    ...       pool-timeout 600
-    ...       <mappingstorage/>
-    ...     </zodb>
-    ... ''')
-    >>> db.pool._timeout == 600
+    >>> db.database_name
+    ''
+    >>> db.databases[db.database_name] is db
     True
+    >>> db.databases['foo'] is not db
+    True
+    >>> db.databases['Bar'] is not db
+    True
+    >>> db.databases['Bar'] is not db.databases['foo']
+    True
 
+    Can't have repeats:
+
+    >>> ZODB.config.databaseFromString('''
+    ... <zodb 1>
+    ...    <mappingstorage>
+    ...    </mappingstorage>
+    ... </zodb>
+    ... <zodb 1>
+    ...    <mappingstorage>
+    ...    </mappingstorage>
+    ... </zodb>
+    ... <zodb 1>
+    ...    <mappingstorage>
+    ...    </mappingstorage>
+    ... </zodb>
+    ... ''') # doctest: +NORMALIZE_WHITESPACE
+    Traceback (most recent call last):
+    ...
+    ConfigurationSyntaxError:
+    section names must not be re-used within the same container:'1' (line 9)
+
+    >>> ZODB.config.databaseFromString('''
+    ... <zodb>
+    ...    <mappingstorage>
+    ...    </mappingstorage>
+    ... </zodb>
+    ... <zodb>
+    ...    <mappingstorage>
+    ...    </mappingstorage>
+    ... </zodb>
+    ... ''') # doctest: +NORMALIZE_WHITESPACE
+    Traceback (most recent call last):
+    ...
+    ValueError: database_name '' already in databases
+
     """
 
-
 def test_suite():
     suite = unittest.TestSuite()
+    suite.addTest(doctest.DocTestSuite())
     suite.addTest(unittest.makeSuite(ZODBConfigTest))
     suite.addTest(unittest.makeSuite(ZEOConfigTest))
-    suite.addTest(doctest.DocTestSuite())
     return suite
 
 



More information about the Zodb-checkins mailing list