[CMF-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 CMF-checkins
mailing list