[Zope-CVS] CVS: Products/DBTab - CHANGES.txt:1.9 DBTab.py:1.11 MountedObject.py:1.6 dbtab.conf.in:1.8
Shane Hathaway
shane@zope.com
Fri, 18 Apr 2003 22:15:30 -0400
Update of /cvs-repository/Products/DBTab
In directory cvs.zope.org:/tmp/cvs-serv8943
Modified Files:
CHANGES.txt DBTab.py MountedObject.py dbtab.conf.in
Log Message:
Using the product registry turned out to be a bad idea, since objects might
need to be constructed before Zope finishes initialization (for example,
if you're using DBTab to share session data.) So container_factory was
renamed container_class and you can now create instances of a certain class
in order to mount a database. The class constructor must accept one
argument, the ID of the object.
=== Products/DBTab/CHANGES.txt 1.8 => 1.9 ===
--- Products/DBTab/CHANGES.txt:1.8 Wed Apr 16 15:59:24 2003
+++ Products/DBTab/CHANGES.txt Fri Apr 18 22:15:29 2003
@@ -6,7 +6,7 @@
- Removed import of AdaptableStorage. Argument converters now work
when you specify the full module of a storage class.
- - You can now specify a container_factory to generate folderish
+ - You can now specify a container_class to generate folderish
objects other than standard folders when mounting a new database.
See dbtab.conf.in.
=== Products/DBTab/DBTab.py 1.10 => 1.11 ===
--- Products/DBTab/DBTab.py:1.10 Wed Apr 16 15:59:24 2003
+++ Products/DBTab/DBTab.py Fri Apr 18 22:15:29 2003
@@ -51,7 +51,7 @@
# Mount options
mount_paths = None # ((virtual_path, real_root, real_path),)
- container_factory = None # string: "product_name:factory_name"
+ container_class = None # string: "module_name:class_name"
# Other options
class_factory = None
@@ -174,7 +174,7 @@
# Read string parameters
for key in (
- 'class_factory', 'container_factory',
+ 'class_factory', 'container_class',
):
if args.has_key(key):
setattr(self, key, args[key])
@@ -235,13 +235,13 @@
return self.open_at_startup
def getMountParams(self, mount_path):
- """Returns (real_root, real_path, container_factory) for a virtual
+ """Returns (real_root, real_path, container_class) for a virtual
mount path.
"""
if self.mount_paths:
for (virtual_path, real_root, real_path) in self.mount_paths:
if virtual_path == mount_path:
- return (real_root, real_path, self.container_factory)
+ return (real_root, real_path, self.container_class)
raise LookupError('Nothing known about mount path %s' % mount_path)
=== Products/DBTab/MountedObject.py 1.5 => 1.6 ===
--- Products/DBTab/MountedObject.py:1.5 Wed Apr 16 15:59:24 2003
+++ Products/DBTab/MountedObject.py Fri Apr 18 22:15:29 2003
@@ -23,7 +23,6 @@
from AccessControl.ZopeGuards import guarded_getattr
from OFS.SimpleItem import SimpleItem
from OFS.Folder import Folder
-from App.FactoryDispatcher import ProductDispatcher
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Mount import MountPoint
@@ -41,38 +40,29 @@
return configuration
-class Trailblazer:
- """Follows Zope paths. If a path is not found, creates it."""
+class SimpleTrailblazer:
+ """Follows Zope paths. If a path is not found, creates a Folder.
- def __init__(self, base, zope_app=None, container_factory=None):
+ Respects Zope security.
+ """
+
+ restricted = 1
+
+ def __init__(self, base):
self.base = base
- if zope_app is None:
- zope_app = base
- self.zope_app = zope_app
- if not container_factory:
- container_factory = 'OFSP:manage_addFolder'
- self.product_name, self.factory_name = container_factory.split(':', 1)
-
- def _construct(self, context, restricted, id):
- """Returns the FactoryDispatcher for context."""
- pd = ProductDispatcher().__of__(context)
- # Make the installed products available to the product dispatcher
- pd._getProducts = self.zope_app._getProducts
- dispatcher = pd[self.product_name]
- if restricted:
- factory = guarded_getattr(dispatcher, self.factory_name)
- factory(id)
- o = context.restrictedTraverse(id)
- else:
- factory = getattr(dispatcher, self.factory_name)
- factory(id)
- o = context.unrestrictedTraverse(id)
+
+ def _construct(self, context, id, final):
+ """Creates and returns the named folder."""
+ dispatcher = guarded_getattr(context, 'manage_addProduct')['OFSP']
+ factory = guarded_getattr(dispatcher, 'manage_addFolder')
+ factory(id)
+ o = context.restrictedTraverse(id)
# Commit a subtransaction to assign the new object to
# the correct database.
get_transaction().commit(1)
return o
- def traverseOrConstruct(self, path, omit_final=0, restricted=1):
+ def traverseOrConstruct(self, path, omit_final=0):
"""Traverses a path, constructing it if necessary."""
container = self.base
parts = filter(None, path.split('/'))
@@ -82,15 +72,49 @@
parts = parts[:-1]
for part in parts:
try:
- if restricted:
+ if self.restricted:
container = container.restrictedTraverse(part)
else:
container = container.unrestrictedTraverse(part)
except (KeyError, AttributeError):
# Try to create a container in this place.
- container = self._construct(container, restricted, part)
+ container = self._construct(container, part)
return container
+
+class CustomTrailblazer (SimpleTrailblazer):
+ """Like SimpleTrailblazer but creates custom objects.
+
+ Does not respect Zope security because this may be invoked before
+ security and products get initialized.
+ """
+
+ restricted = 0
+
+ def __init__(self, base, container_class=None):
+ self.base = base
+ if not container_class:
+ container_class = 'OFS.Folder.Folder'
+ pos = container_class.rfind('.')
+ if pos < 0:
+ raise ValueError("Not a valid container_class: %s" % repr(
+ container_class))
+ self.module_name = container_class[:pos]
+ self.class_name = container_class[pos + 1:]
+
+ def _construct(self, context, id):
+ """Creates and returns the named object."""
+ jar = self.base._p_jar
+ klass = jar.db()._classFactory(jar, self.module_name, self.class_name)
+ obj = klass(id)
+ obj._setId(id)
+ context._setObject(id, obj)
+ obj = context.unrestrictedTraverse(id)
+ # Commit a subtransaction to assign the new object to
+ # the correct database.
+ get_transaction().commit(1)
+ return obj
+
class MountedObject(MountPoint, SimpleItem):
'''A MountPoint with a basic interface for displaying the
@@ -142,17 +166,19 @@
params = self._v_mount_params
if params is None:
params = self._loadMountParams()
- real_root, real_path, container_factory = params
+ real_root, real_path, container_class = params
if real_root is None:
real_root = 'Application'
try:
obj = root[real_root]
except KeyError:
- if container_factory or self._create_mount_points:
+ if container_class or self._create_mount_points:
# Create a database automatically.
from OFS.Application import Application
obj = Application()
root[real_root] = obj
+ # Get it into the database
+ get_transaction().commit(1)
else:
raise
@@ -162,10 +188,9 @@
try:
obj = obj.unrestrictedTraverse(real_path)
except (KeyError, AttributeError):
- if container_factory or self._create_mount_points:
- zopeapp = mount_parent.getPhysicalRoot()
- blazer = Trailblazer(obj, zopeapp, container_factory)
- obj = blazer.traverseOrConstruct(real_path, restricted=0)
+ if container_class or self._create_mount_points:
+ blazer = CustomTrailblazer(obj, container_class)
+ obj = blazer.traverseOrConstruct(real_path)
else:
raise
return obj
@@ -252,7 +277,7 @@
mo._create_mount_points = not not create_mount_points
# Raise an error now if there is any problem.
mo._test(app)
- blazer = Trailblazer(app)
+ blazer = SimpleTrailblazer(app)
container = blazer.traverseOrConstruct(path, omit_final=1)
mo._p_jar = container._p_jar
loaded = mo.__of__(container)
=== Products/DBTab/dbtab.conf.in 1.7 => 1.8 ===
--- Products/DBTab/dbtab.conf.in:1.7 Wed Apr 16 15:59:24 2003
+++ Products/DBTab/dbtab.conf.in Fri Apr 18 22:15:29 2003
@@ -131,7 +131,7 @@
# [Database: Sessions]
# connection_class=LowConflictConnection
# mount_paths=/temp_folder
-# container_factory=OFSP:manage_addFolder
+# container_class=OFS.Folder.Folder
######################################################################
@@ -248,24 +248,24 @@
# mount_paths=/MyApp/MyCalendar:~Calendar/
-## The container_factory parameter lets you choose what kind of
-## objects to create when mounting the database. By default, DBTab
-## makes Folder objects in the mounted database, but you can use this
-## parameter to create PortalFolders or other kinds of objects
-## instead. Its format is <product name>:<factory name>. This
-## parameter is also useful when using volatile data storage such as
-## DemoStorage or MappingStorage. Since the database gets wiped out
-## when the process stops, the mountable object needs to be created
-## again upon restart. If you specify a container_factory, the
+## The container_class parameter lets you choose what kind of objects
+## to create when mounting the database for the first time. By
+## default, DBTab makes Folder objects in the mounted database, but
+## you can use this parameter to create PortalFolders or other kinds
+## of objects instead. Its format is <module name>.<class name>.
+## This parameter is also useful when using volatile data storage such
+## as DemoStorage or MappingStorage. Since the database gets wiped
+## out when the process stops, the mountable object needs to be
+## created again upon restart. If you specify a container_class, the
## mountable object will be created automatically after restart.
-# container_factory=OFSP:manage_addFolder
+# container_class=OFS.Folder.Folder
## Another example:
-# container_factory=CMFCore:manage_addPortalFolder
+# container_class=Products.CMFCore.PortalFolder.PortalFolder
-## Note that container_factory replaces the old auto_create option,
+## Note that container_class replaces the old auto_create option,
## which is deprecated as of DBTab 1.2.
## The class_factory parameter is an advanced option that tells ZODB