[Checkins] SVN: CMF/trunk/C - added support for Zope3 style content type factories

Yvo Schubbe y.2006_ at wcm-solutions.de
Mon May 29 11:55:44 EDT 2006


Log message for revision 68352:
  - added support for Zope3 style content type factories

Changed:
  U   CMF/trunk/CHANGES.txt
  U   CMF/trunk/CMFCore/TypesTool.py
  U   CMF/trunk/CMFCore/tests/base/dummy.py
  U   CMF/trunk/CMFCore/tests/base/security.py
  U   CMF/trunk/CMFCore/tests/test_PortalFolder.py
  U   CMF/trunk/CMFCore/tests/test_TypesTool.py

-=-
Modified: CMF/trunk/CHANGES.txt
===================================================================
--- CMF/trunk/CHANGES.txt	2006-05-29 15:50:49 UTC (rev 68351)
+++ CMF/trunk/CHANGES.txt	2006-05-29 15:55:43 UTC (rev 68352)
@@ -2,7 +2,9 @@
 
   New Features
 
-    -
+    - FactoryTypeInformation: Added support for Zope3 style factories.
+      If the 'product' property of a type info instance is empty the 'factory'
+      property is interpreted as an IFactory name.
 
   Bug Fixes
 

Modified: CMF/trunk/CMFCore/TypesTool.py
===================================================================
--- CMF/trunk/CMFCore/TypesTool.py	2006-05-29 15:50:49 UTC (rev 68351)
+++ CMF/trunk/CMFCore/TypesTool.py	2006-05-29 15:55:43 UTC (rev 68352)
@@ -28,6 +28,9 @@
 from OFS.Folder import Folder
 from OFS.ObjectManager import IFAwareObjectManager
 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+from zope.component import getUtility
+from zope.component import queryUtility
+from zope.component.interfaces import IFactory
 from zope.i18nmessageid import Message
 from zope.interface import implements
 
@@ -329,7 +332,7 @@
             method_id = method_id[0]
         return method_id
 
-InitializeClass( TypeInformation )
+InitializeClass(TypeInformation)
 
 
 class FactoryTypeInformation(TypeInformation):
@@ -346,7 +349,7 @@
         {'id':'product', 'type': 'string', 'mode':'w',
          'label':'Product name'},
         {'id':'factory', 'type': 'string', 'mode':'w',
-         'label':'Product factory method'},
+         'label':'Product factory'},
         ) + TypeInformation._advanced_properties)
 
     product = ''
@@ -402,7 +405,7 @@
         return default
 
     security.declarePublic('isConstructionAllowed')
-    def isConstructionAllowed( self, container ):
+    def isConstructionAllowed(self, container):
         """
         a. Does the factory method exist?
 
@@ -411,9 +414,22 @@
         c. Does the current user have the permission required in
         order to invoke the factory method?
         """
-        m = self._queryFactoryMethod(container)
-        return (m is not None)
+        if self.product:
+            # oldstyle factory
+            m = self._queryFactoryMethod(container)
+            return (m is not None)
 
+        elif container is not None:
+            # newstyle factory
+            m = queryUtility(IFactory, self.factory, None)
+            if m is not None:
+                for d in container.all_meta_types():
+                    if d['name'] == self.content_meta_type:
+                        sm = getSecurityManager()
+                        return sm.checkPermission(d['permission'], container)
+
+        return False
+
     security.declarePrivate('_constructInstance')
     def _constructInstance(self, container, id, *args, **kw):
         """Build a bare instance of the appropriate type.
@@ -422,24 +438,33 @@
 
         Returns the object without calling _finishConstruction().
         """
-        m = self._getFactoryMethod(container, check_security=0)
-
         id = str(id)
 
-        if getattr(aq_base(m), 'isDocTemp', 0):
-            kw['id'] = id
-            newid = m(m.aq_parent, self.REQUEST, *args, **kw)
+        if self.product:
+            # oldstyle factory
+            m = self._getFactoryMethod(container, check_security=0)
+
+            if getattr(aq_base(m), 'isDocTemp', 0):
+                kw['id'] = id
+                newid = m(m.aq_parent, self.REQUEST, *args, **kw)
+            else:
+                newid = m(id, *args, **kw)
+            # allow factory to munge ID
+            newid = newid or id
+
         else:
-            newid = m(id, *args, **kw)
-        # allow factory to munge ID
-        newid = newid or id
+            # newstyle factory
+            factory = getUtility(IFactory, self.factory)
+            obj = factory(id, *args, **kw)
+            rval = container._setObject(id, obj)
+            newid = isinstance(rval, basestring) and rval or id
 
         return container._getOb(newid)
 
-InitializeClass( FactoryTypeInformation )
+InitializeClass(FactoryTypeInformation)
 
 
-class ScriptableTypeInformation( TypeInformation ):
+class ScriptableTypeInformation(TypeInformation):
 
     """ Invokes a script rather than a factory to create the content.
     """
@@ -463,7 +488,7 @@
     #   Agent methods
     #
     security.declarePublic('isConstructionAllowed')
-    def isConstructionAllowed( self, container ):
+    def isConstructionAllowed(self, container):
         """
         Does the current user have the permission required in
         order to construct an instance?
@@ -492,7 +517,7 @@
         id = str(id)
         return constructor(container, id, *args, **kw)
 
-InitializeClass( ScriptableTypeInformation )
+InitializeClass(ScriptableTypeInformation)
 
 
 allowedTypes = [
@@ -716,4 +741,4 @@
         rval.sort()
         return rval
 
-InitializeClass( TypesTool )
+InitializeClass(TypesTool)

Modified: CMF/trunk/CMFCore/tests/base/dummy.py
===================================================================
--- CMF/trunk/CMFCore/tests/base/dummy.py	2006-05-29 15:50:49 UTC (rev 68351)
+++ CMF/trunk/CMFCore/tests/base/dummy.py	2006-05-29 15:55:43 UTC (rev 68352)
@@ -24,6 +24,7 @@
 from zope.app.container.contained import notifyContainerModified
 from zope.app.container.contained import ObjectAddedEvent
 from zope.app.container.contained import ObjectRemovedEvent
+from zope.component.factory import Factory
 from zope.event import notify
 from zope.interface import implements
 
@@ -161,16 +162,19 @@
     def Type( self ):
         return 'Dummy Content Title'
 
+DummyFactory = Factory(DummyContent)
 
-class DummyFactory:
+
+class DummyFactoryDispatcher:
+
     """
-    Dummy Product Factory
+    Dummy Product Factory Dispatcher
     """
     def __init__( self, folder ):
         self._folder = folder
 
     def getId(self):
-        return 'DummyFactory'
+        return 'DummyFactoryDispatcher'
 
     def addFoo( self, id, *args, **kw ):
         if getattr(self._folder, '_prefix', None):
@@ -195,7 +199,8 @@
         self._id = id
 
         if fake_product:
-            self.manage_addProduct = { 'FooProduct' : DummyFactory( self ) }
+            self.manage_addProduct = {
+                                   'FooProduct': DummyFactoryDispatcher(self)}
 
     def _setOb(self, id, object):
         setattr(self, id, object)
@@ -241,7 +246,10 @@
     def contentIds(self):
         return ('user_bar',)
 
+    def all_meta_types(self):
+        return ({'name': 'Dummy', 'permission': 'addFoo'},)
 
+
 class DummySite(DummyFolder):
     """ A dummy portal folder.
     """

Modified: CMF/trunk/CMFCore/tests/base/security.py
===================================================================
--- CMF/trunk/CMFCore/tests/base/security.py	2006-05-29 15:50:49 UTC (rev 68351)
+++ CMF/trunk/CMFCore/tests/base/security.py	2006-05-29 15:55:43 UTC (rev 68352)
@@ -43,6 +43,8 @@
     def checkPermission(self, permission, object, context):
         if permission == 'forbidden permission':
             return 0
+        if permission == 'addFoo':
+            return context.user.allowed(object, ['FooAdder'])
         roles = rolesForPermissionOn(permission, object)
         if isinstance(roles, basestring):
             roles=[roles]

Modified: CMF/trunk/CMFCore/tests/test_PortalFolder.py
===================================================================
--- CMF/trunk/CMFCore/tests/test_PortalFolder.py	2006-05-29 15:50:49 UTC (rev 68351)
+++ CMF/trunk/CMFCore/tests/test_PortalFolder.py	2006-05-29 15:55:43 UTC (rev 68352)
@@ -21,6 +21,8 @@
 import cStringIO
 
 import transaction
+from AccessControl.SecurityManagement import newSecurityManager
+from AccessControl.SecurityManagement import noSecurityManager
 from AccessControl import SecurityManager
 from AccessControl import Unauthorized
 from Acquisition import aq_base
@@ -36,11 +38,9 @@
 from Products.CMFCore.exceptions import BadRequest
 from Products.CMFCore.testing import ConformsToFolder
 from Products.CMFCore.tests.base.dummy import DummyContent
-from Products.CMFCore.tests.base.dummy import DummyFactory
+from Products.CMFCore.tests.base.dummy import DummyFactoryDispatcher
 from Products.CMFCore.tests.base.dummy import DummySite
 from Products.CMFCore.tests.base.dummy import DummyUserFolder
-from Products.CMFCore.tests.base.testcase import newSecurityManager
-from Products.CMFCore.tests.base.testcase import noSecurityManager
 from Products.CMFCore.tests.base.testcase import SecurityTest
 from Products.CMFCore.tests.base.testcase import setUpEvents
 from Products.CMFCore.tests.base.tidata import FTIDATA_CMF15
@@ -92,7 +92,7 @@
 
         self.failIf( 'foo' in f.objectIds() )
 
-        f.manage_addProduct = { 'FooProduct' : DummyFactory(f) }
+        f.manage_addProduct = {'FooProduct': DummyFactoryDispatcher(f)}
         f.invokeFactory( type_name='Dummy Content', id='foo' )
 
         self.failUnless( 'foo' in f.objectIds() )
@@ -1004,9 +1004,6 @@
                                    )
 
     def test_copy_cant_create_target_metatype_not_supported( self ):
-
-        from OFS.CopySupport import CopyError
-
         folder1, folder2 = self._initFolders()
         folder2.all_meta_types = ()
 
@@ -1035,9 +1032,6 @@
         self.failUnless( 'file' in folder2.objectIds() )
 
     def test_move_cant_read_source( self ):
-
-        from OFS.CopySupport import CopyError
-
         folder1, folder2 = self._initFolders()
         folder2.all_meta_types = FILE_META_TYPES
 
@@ -1055,9 +1049,6 @@
                                    )
 
     def test_move_cant_create_target_metatype_not_supported( self ):
-
-        from OFS.CopySupport import CopyError
-
         folder1, folder2 = self._initFolders()
         folder2.all_meta_types = ()
 
@@ -1080,8 +1071,6 @@
         #   If you are running with such a Zope, this test will error out
         #   with an AttributeError (instead of the expected Unauthorized).
         #
-        from OFS.CopySupport import CopyError
-
         folder1, folder2 = self._initFolders()
         folder2.all_meta_types = FILE_META_TYPES
 
@@ -1115,7 +1104,6 @@
         #   allowed.
         #
         from AccessControl.Permissions import delete_objects as DeleteObjects
-        from OFS.CopySupport import CopyError
         from Products.CMFCore.PortalFolder import PortalFolder
         from Products.CMFCore.permissions import AddPortalFolders
 

Modified: CMF/trunk/CMFCore/tests/test_TypesTool.py
===================================================================
--- CMF/trunk/CMFCore/tests/test_TypesTool.py	2006-05-29 15:50:49 UTC (rev 68351)
+++ CMF/trunk/CMFCore/tests/test_TypesTool.py	2006-05-29 15:55:43 UTC (rev 68352)
@@ -28,11 +28,14 @@
 from Products.PythonScripts.PythonScript import PythonScript
 from Products.PythonScripts.standard import html_quote
 from webdav.NullResource import NullResource
+from zope.component import getGlobalSiteManager
+from zope.component.interfaces import IFactory
 from zope.testing.cleanup import cleanUp
 
 from Products.CMFCore.ActionInformation import ActionInformation
 from Products.CMFCore.PortalFolder import PortalFolder
 from Products.CMFCore.tests.base.dummy import DummyFactory
+from Products.CMFCore.tests.base.dummy import DummyFactoryDispatcher
 from Products.CMFCore.tests.base.dummy import DummyFolder
 from Products.CMFCore.tests.base.dummy import DummyObject
 from Products.CMFCore.tests.base.dummy import DummySite
@@ -134,7 +137,7 @@
         s.write(STI_SCRIPT)
 
         f = site._setObject( 'folder', PortalFolder(id='folder') )
-        f.manage_addProduct = { 'FooProduct' : DummyFactory(f) }
+        f.manage_addProduct = { 'FooProduct' : DummyFactoryDispatcher(f) }
         f._owner = (['acl_users'], 'user_foo')
         self.assertEqual( f.getOwner(), acl_users.user_foo )
 
@@ -363,162 +366,113 @@
         self.assertEqual( ti.constructor_path, 'foo_add' )
 
 
-class FTIConstructionTests(unittest.TestCase):
+class FTIConstructionTestCase(unittest.TestCase):
 
-    def setUp( self ):
-        noSecurityManager()
-
-    def _makeInstance(self, id, **kw):
+    def _getTargetClass(self):
         from Products.CMFCore.TypesTool import FactoryTypeInformation
 
-        return FactoryTypeInformation(id, **kw)
+        return FactoryTypeInformation
 
-    def _makeFolder( self, fake_product=0 ):
-        return DummyFolder( fake_product )
+    def _makeOne(self, *args, **kw):
+        return self._getTargetClass()(*args, **kw)
 
-    def test_isConstructionAllowed_wo_Container( self ):
+    def test_isConstructionAllowed_wo_Container(self):
+        self.failIf(self.ti.isConstructionAllowed(None))
 
-        ti = self._makeInstance( 'foo' )
+    def test_isConstructionAllowed_wo_ProductFactory(self):
+        ti = self._makeOne('foo')
+        self.failIf(ti.isConstructionAllowed(self.f))
 
-        self.failIf( ti.isConstructionAllowed( None ) )
-
-        ti = self._makeInstance( 'Foo'
-                               , product='FooProduct'
-                               , factory='addFoo'
-                               )
-
-        self.failIf( ti.isConstructionAllowed( None ) )
-
-    def test_isConstructionAllowed_wo_ProductFactory( self ):
-
-        ti = self._makeInstance( 'foo' )
-
-        folder = self._makeFolder()
-        self.failIf( ti.isConstructionAllowed( folder ) )
-
-        folder = self._makeFolder( fake_product=1 )
-        self.failIf( ti.isConstructionAllowed( folder ) )
-
-    def test_isConstructionAllowed_wo_Security( self ):
-
-        ti = self._makeInstance( 'Foo'
-                               , product='FooProduct'
-                               , factory='addFoo'
-                               )
-        folder = self._makeFolder( fake_product=1 )
-
-        self.failIf( ti.isConstructionAllowed( folder ) )
-
-
-class FTIConstructionTests_w_Roles(unittest.TestCase):
-
-    def tearDown( self ):
+    def test_isConstructionAllowed_wo_Security(self):
         noSecurityManager()
+        self.failIf(self.ti.isConstructionAllowed(self.f))
 
-    def _makeStuff( self, prefix='' ):
-        from Products.CMFCore.TypesTool import FactoryTypeInformation as FTI
+    def test_isConstructionAllowed_for_Omnipotent(self):
+        newSecurityManager(None, OmnipotentUser().__of__(self.f))
+        self.failUnless(self.ti.isConstructionAllowed(self.f))
 
-        ti = FTI( 'Foo'
-                  , product='FooProduct'
-                  , factory='addFoo'
-                  )
-        folder = DummyFolder( fake_product=1,prefix=prefix )
+    def test_isConstructionAllowed_w_Role(self):
+        self.failUnless(self.ti.isConstructionAllowed(self.f))
 
-        return ti, folder
+    def test_isConstructionAllowed_wo_Role(self):
+        newSecurityManager(None, UserWithRoles('FooViewer').__of__(self.f))
+        self.failIf(self.ti.isConstructionAllowed(self.f))
 
-    def test_isConstructionAllowed_for_Omnipotent( self ):
+    def test_constructInstance_wo_Roles(self):
+        newSecurityManager(None, UserWithRoles('FooViewer').__of__(self.f))
+        self.assertRaises(Unauthorized,
+                          self.ti.constructInstance, self.f, 'foo')
 
-        ti, folder = self._makeStuff()
-        newSecurityManager( None
-                          , OmnipotentUser().__of__( folder ) )
-        self.failUnless( ti.isConstructionAllowed( folder ) )
+    def test_constructInstance(self):
+        self.ti.constructInstance(self.f, 'foo')
+        foo = self.f._getOb('foo')
+        self.assertEqual(foo.id, 'foo')
 
-    def test_isConstructionAllowed_w_Role( self ):
-
-        ti, folder = self._makeStuff()
-
-        newSecurityManager( None
-                          , UserWithRoles( 'FooAdder' ).__of__( folder ) )
-        self.failUnless( ti.isConstructionAllowed( folder ) )
-
-    def test_isConstructionAllowed_wo_Role( self ):
-
-        ti, folder = self._makeStuff()
-
-        newSecurityManager( None
-                          , UserWithRoles( 'FooViewer' ).__of__( folder ) )
-
-    def test_constructInstance_wo_Roles( self ):
-
-        ti, folder = self._makeStuff()
-
-        newSecurityManager( None
-                          , UserWithRoles( 'FooViewer' ).__of__( folder ) )
-
-        self.assertRaises( Unauthorized
-                         , ti.constructInstance, folder, 'foo' )
-
-    def test_constructInstance( self ):
-
-        ti, folder = self._makeStuff()
-
-        newSecurityManager( None
-                          , UserWithRoles( 'FooAdder' ).__of__( folder ) )
-
-        ti.constructInstance( folder, 'foo' )
-        foo = folder._getOb( 'foo' )
-        self.assertEqual( foo.id, 'foo' )
-
     def test_constructInstance_private(self):
-        ti, folder = self._makeStuff()
-        newSecurityManager(None,
-                           UserWithRoles('NotAFooAdder').__of__(folder))
-        ti._constructInstance(folder, 'foo')
-        foo = folder._getOb('foo')
+        newSecurityManager(None, UserWithRoles('NotAFooAdder').__of__(self.f))
+        self.ti._constructInstance(self.f, 'foo')
+        foo = self.f._getOb('foo')
         self.assertEqual(foo.id, 'foo')
 
-    def test_constructInstance_w_args_kw( self ):
+    def test_constructInstance_w_args_kw(self):
+        self.ti.constructInstance(self.f, 'bar', 0, 1)
+        bar = self.f._getOb('bar')
+        self.assertEqual(bar.id, 'bar')
+        self.assertEqual(bar._args, (0, 1))
 
-        ti, folder = self._makeStuff()
+        self.ti.constructInstance(self.f, 'baz', frickle='natz')
+        baz = self.f._getOb('baz')
+        self.assertEqual(baz.id, 'baz')
+        self.assertEqual(baz._kw['frickle'], 'natz')
 
-        newSecurityManager( None
-                          , UserWithRoles( 'FooAdder' ).__of__( folder ) )
+        self.ti.constructInstance(self.f, 'bam', 0, 1, frickle='natz')
+        bam = self.f._getOb('bam')
+        self.assertEqual(bam.id, 'bam')
+        self.assertEqual(bam._args, (0, 1))
+        self.assertEqual(bam._kw['frickle'], 'natz')
 
-        ti.constructInstance( folder, 'bar', 0, 1 )
-        bar = folder._getOb( 'bar' )
-        self.assertEqual( bar.id, 'bar' )
-        self.assertEqual( bar._args, ( 0, 1 ) )
 
-        ti.constructInstance( folder, 'baz', frickle='natz' )
-        baz = folder._getOb( 'baz' )
-        self.assertEqual( baz.id, 'baz' )
-        self.assertEqual( baz._kw[ 'frickle' ], 'natz' )
+class FTIOldstyleConstructionTests(FTIConstructionTestCase):
+    
+    def setUp(self):
+        self.f = DummyFolder(fake_product=1)
+        self.ti = self._makeOne('Foo', product='FooProduct', factory='addFoo')
+        newSecurityManager(None, UserWithRoles('FooAdder').__of__(self.f))
 
-        ti.constructInstance( folder, 'bam', 0, 1, frickle='natz' )
-        bam = folder._getOb( 'bam' )
-        self.assertEqual( bam.id, 'bam' )
-        self.assertEqual( bam._args, ( 0, 1 ) )
-        self.assertEqual( bam._kw[ 'frickle' ], 'natz' )
+    def tearDown(self):
+        noSecurityManager()
 
-    def test_constructInstance_w_id_munge( self ):
+    def test_constructInstance_w_id_munge(self):
+        self.f._prefix = 'majyk'
+        self.ti.constructInstance(self.f, 'dust')
+        majyk_dust = self.f._getOb('majyk_dust')
+        self.assertEqual(majyk_dust.id, 'majyk_dust')
 
-        ti, folder = self._makeStuff( 'majyk' )
 
-        newSecurityManager( None
-                          , UserWithRoles( 'FooAdder' ).__of__( folder ) )
+class FTINewstyleConstructionTests(FTIConstructionTestCase, SecurityTest):
 
-        ti.constructInstance( folder, 'dust' )
-        majyk_dust = folder._getOb( 'majyk_dust' )
-        self.assertEqual( majyk_dust.id, 'majyk_dust' )
+    def setUp(self):
+        SecurityTest.setUp(self)
+        gsm = getGlobalSiteManager()
+        gsm.provideUtility(IFactory, DummyFactory, 'test.dummy')
 
+        self.f = DummyFolder()
+        self.ti = self._makeOne('Foo', meta_type='Dummy',
+                                factory='test.dummy')
+        newSecurityManager(None, UserWithRoles('FooAdder').__of__(self.f))
 
+    def tearDown(self):
+        SecurityTest.tearDown(self)
+        cleanUp()
+
+
 def test_suite():
     return unittest.TestSuite((
         unittest.makeSuite(TypesToolTests),
         unittest.makeSuite(FTIDataTests),
         unittest.makeSuite(STIDataTests),
-        unittest.makeSuite(FTIConstructionTests),
-        unittest.makeSuite(FTIConstructionTests_w_Roles),
+        unittest.makeSuite(FTIOldstyleConstructionTests),
+        unittest.makeSuite(FTINewstyleConstructionTests),
         ))
 
 if __name__ == '__main__':



More information about the Checkins mailing list