def test_schema_lookup_default_view(self): # Context and request class IMarker(IDexterityContent): pass context_mock = self.create_dummy(portal_type=u'testtype') alsoProvides(context_mock, IMarker) request_mock = TestRequest() # FTI fti_mock = DexterityFTI(u"testtype") fti_mock.lookupSchema = Mock(return_value=ISchema) fti_mock.behaviors = (IBehaviorOne.__identifier__, IBehaviorTwo.__identifier__, IBehaviorThree.__identifier__) self.mock_utility(fti_mock, IDexterityFTI, name=u"testtype") from plone.behavior.interfaces import IBehavior from plone.behavior.registration import BehaviorRegistration registration = BehaviorRegistration( title=u"Test Behavior 1", description=u"Provides test behavior", interface=IBehaviorOne, marker=None, factory=None) self.mock_utility(registration, IBehavior, IBehaviorOne.__identifier__) registration = BehaviorRegistration( title=u"Test Behavior 2", description=u"Provides test behavior", interface=IBehaviorTwo, marker=None, factory=None) self.mock_utility(registration, IBehavior, IBehaviorTwo.__identifier__) registration = BehaviorRegistration( title=u"Test Behavior 3", description=u"Provides test behavior", interface=IBehaviorThree, marker=None, factory=None) self.mock_utility(registration, IBehavior, IBehaviorThree.__identifier__) # Form view = DefaultView(context_mock, request_mock) view.portal_type = u"testtype" self.assertEqual(ISchema, view.schema) # we expect here only formfieldprovider! self.assertEqual((IBehaviorOne, IBehaviorTwo), tuple(view.additionalSchemata)) # When we register our own IBehaviorAssignable we can # influence what goes into the additionalSchemata. self.mock_adapter(NoBehaviorAssignable, IBehaviorAssignable, [IMarker]) additionalSchemata = tuple(view.additionalSchemata) self.assertEqual(tuple(), tuple(additionalSchemata))
def test_schema_lookup_add(self): # Context and request context_mock = self.create_dummy(portal_type=u'testtype') request_mock = TestRequest() # FTI fti_mock = DexterityFTI(u"testtype") fti_mock.lookupSchema = Mock(return_value=ISchema) fti_mock.behaviors = (IBehaviorOne.__identifier__, IBehaviorTwo.__identifier__, IBehaviorThree.__identifier__) self.mock_utility(fti_mock, IDexterityFTI, name=u"testtype") from plone.behavior.interfaces import IBehavior from plone.behavior.registration import BehaviorRegistration registration = BehaviorRegistration( title=u"Test Behavior 1", description=u"Provides test behavior", interface=IBehaviorOne, marker=None, factory=None) self.mock_utility(registration, IBehavior, IBehaviorOne.__identifier__) registration = BehaviorRegistration( title=u"Test Behavior 2", description=u"Provides test behavior", interface=IBehaviorTwo, marker=None, factory=None) self.mock_utility(registration, IBehavior, IBehaviorTwo.__identifier__) registration = BehaviorRegistration( title=u"Test Behavior 3", description=u"Provides test behavior", interface=IBehaviorThree, marker=None, factory=None) self.mock_utility(registration, IBehavior, IBehaviorThree.__identifier__) # Form view = DefaultAddForm(context_mock, request_mock) view.portal_type = u"testtype" self.assertEqual(ISchema, view.schema) # we expect here only formfieldprovider! self.assertEqual((IBehaviorOne, IBehaviorTwo), tuple(view.additionalSchemata)) # When we register our own IBehaviorAssignable we can # influence what goes into the additionalSchemata. But in an Addform # this never grips, since its an adapter on context, and contextless # there is always the FTI the only valid source self.mock_adapter(NoBehaviorAssignable, IBehaviorAssignable, [Interface]) self.assertEqual((IBehaviorOne, IBehaviorTwo), tuple(view.additionalSchemata))
def behavior_registrations(self, fti): """all behavior behavior registrations of a given fti passed in as portal_type string (magic see get) returns a tuple with instances of ``plone.behavior.registration.BehaviorRegistration`` instances for the given fti. """ if fti is None: return tuple() registrations = [] for behavior_name in fti.behaviors: registration = queryUtility(IBehavior, name=behavior_name) if registration is None: # BBB - this case should be deprecated in v 3.0 log.warning( 'No behavior registration found for behavior named: "{0}"' ' - trying fallback lookup..."'.format(behavior_name)) try: schema_interface = resolve(behavior_name) except (ValueError, ImportError): log.error( "Error resolving behavior {0}".format(behavior_name)) continue registration = BehaviorRegistration( title=behavior_name, description="bbb fallback lookup", interface=schema_interface, marker=None, factory=None) registrations.append(registration) return tuple(registrations)
def test_repeated_subtypes_lookup(self): fti = DexterityFTI(u"testtype") self.mock_utility(fti, IDexterityFTI, name=u"testtype") # Mock a test behavior class ITestSchema(Interface): pass class ITestMarker(Interface): pass fti.behaviors = [ITestSchema.__identifier__] from plone.behavior.registration import BehaviorRegistration registration = BehaviorRegistration( title=u"Test Behavior", description=u"Provides test behavior", interface=ITestSchema, marker=ITestMarker, factory=None ) from plone.behavior.interfaces import IBehavior self.mock_utility( registration, IBehavior, ITestSchema.__identifier__ ) s1 = SCHEMA_CACHE.subtypes(u"testtype") s2 = SCHEMA_CACHE.subtypes(u"testtype") self.assertTrue(s1[0] is s2[0] is ITestMarker)
def test_repeated_behavior_registration_lookup(self): fti = DexterityFTI(u"testtype") self.mock_utility(fti, IDexterityFTI, name=u"testtype") # Mock a test behavior class ITestBehavior(Interface): pass fti.behaviors = [ITestBehavior.__identifier__] from plone.behavior.registration import BehaviorRegistration registration = BehaviorRegistration( title=u"Test Behavior", description=u"Provides test behavior", interface=Interface, marker=ITestBehavior, factory=None ) from plone.behavior.interfaces import IBehavior self.mock_utility( registration, IBehavior, ITestBehavior.__identifier__ ) r1 = SCHEMA_CACHE.behavior_registrations(u'testtype') r2 = SCHEMA_CACHE.behavior_registrations(u'testtype') self.assertTrue(r1[0] is r2[0] is registration)
def test_repeated_behavior_registration_lookup(self): # FTI mock fti_mock = self.mocker.proxy(DexterityFTI(u"testtype")) self.mock_utility(fti_mock, IDexterityFTI, name=u"testtype") # Mock a test behavior class ITestBehavior(Interface): pass self.expect(fti_mock.behaviors).result([ITestBehavior.__identifier__]) from plone.behavior.registration import BehaviorRegistration registration = BehaviorRegistration( title=u"Test Behavior", description=u"Provides test behavior", interface=Interface, marker=ITestBehavior, factory=None) from plone.behavior.interfaces import IBehavior self.mock_utility(registration, IBehavior, ITestBehavior.__identifier__) self.replay() r1 = SCHEMA_CACHE.behavior_registrations(u'testtype') r2 = SCHEMA_CACHE.behavior_registrations(u'testtype') self.assertTrue(r1[0] is r2[0] is registration)
def test_getSize(self): class SizedValue(str): def getSize(self): return len(self) class ITest(Interface): field1 = zope.schema.TextLine() class ITestBehavior(Interface): field2 = zope.schema.TextLine() alsoProvides(ITestBehavior, IFormFieldProvider) self.mock_adapter(DexterityBehaviorAssignable, IBehaviorAssignable, (IDexterityContent, )) fti_mock = DexterityFTI(u'testtype') fti_mock.lookupSchema = Mock(return_value=ITest) fti_mock.behaviors = ['test_behavior'] self.mock_utility(fti_mock, IDexterityFTI, name=u"testtype") behavior_reg = BehaviorRegistration(u"Test Behavior", "", ITestBehavior, ITestBehavior, None) self.mock_utility(behavior_reg, IBehavior, name="test_behavior") item = Item('item') item.portal_type = 'testtype' item.field1 = SizedValue('1') item.field2 = SizedValue('22') self.assertEqual(3, item.getSize())
def behaviorDirective(_context, title, provides, description=None, marker=None, factory=None, for_=None): if marker is None and factory is None: marker = provides if factory is None and marker is not None and marker is not provides: raise ConfigurationError( u"You cannot specify a different 'marker' and 'provides' if " u"there is no adapter factory for the provided interface.") # Instantiate the real factory if it's the schema-aware type. We do # this here so that the for_ interface may take this into account. if factory is not None and ISchemaAwareFactory.providedBy(factory): factory = factory(provides) # Attempt to guess the factory's adapted interface and use it as the for_ if for_ is None and factory is not None: adapts = getattr(factory, '__component_adapts__', None) if adapts: if len(adapts) != 1: raise ConfigurationError( u"The factory cannot be declared a multi-adapter.") for_ = adapts[0] else: for_ = Interface elif for_ is None: for_ = Interface registration = BehaviorRegistration(title=title, description=description, interface=provides, marker=marker, factory=factory) adapter_factory = BehaviorAdapterFactory(registration) utility(_context, provides=IBehavior, name=provides.__identifier__, component=registration) if factory is not None: adapter(_context, factory=(adapter_factory, ), provides=provides, for_=(for_, ))
def test_item(self): # Mock schema model class ITestSchema(Interface): test = zope.schema.TextLine(title=u"Test") ITestSchema.setTaggedValue(READ_PERMISSIONS_KEY, dict(test='zope2.View', foo='foo.View')) from plone.autoform.interfaces import IFormFieldProvider @provider(IFormFieldProvider) class ITestBehavior(Interface): test2 = zope.schema.TextLine(title=u"Test") ITestBehavior.setTaggedValue(READ_PERMISSIONS_KEY, dict(test2='zope2.View', foo2='foo.View')) # Mock a test behavior from plone.behavior.registration import BehaviorRegistration registration = BehaviorRegistration( title=u"Test Behavior", description=u"Provides test behavior", interface=ITestBehavior, marker=Interface, factory=None) from plone.behavior.interfaces import IBehavior self.mock_utility(registration, IBehavior, ITestBehavior.__identifier__) from plone.dexterity.behavior import DexterityBehaviorAssignable from plone.dexterity.interfaces import IDexterityContent from plone.behavior.interfaces import IBehaviorAssignable self.mock_adapter(DexterityBehaviorAssignable, IBehaviorAssignable, (IDexterityContent, )) # Mock FTI fti_mock = self.mocker.proxy(DexterityFTI(u"testtype")) self.mock_utility(fti_mock, IDexterityFTI, u'testtype') # Mock permissions self.mock_utility(Permission(u'zope2.View', u"View"), IPermission, u'zope2.View') self.mock_utility(Permission(u'foo.View', u"View foo"), IPermission, u'foo.View') # Content item item = Item('test') item.portal_type = u"testtype" item.test = u"foo" item.foo = u"bar" # mock security manager securityManager_mock = self.mocker.mock() getSecurityManager_mock = self.mocker.replace( 'AccessControl.getSecurityManager') # expectations # run 1 # lookupSchema is always called twice: cache and __providedBy__ self.expect(fti_mock.lookupSchema()).result(ITestSchema) self.expect(fti_mock.behaviors).result(tuple()) self.expect(securityManager_mock.checkPermission("View", item)).result(False) # run 2 self.expect(fti_mock.lookupSchema()).result(ITestSchema) self.expect(fti_mock.behaviors).result(tuple()) self.expect(securityManager_mock.checkPermission("View foo", item)).result(True) # run 3 self.expect(fti_mock.lookupSchema()).result(ITestSchema) self.expect(fti_mock.behaviors).result(tuple()) # # run 4 self.expect(fti_mock.lookupSchema()).result(ITestSchema) self.expect(fti_mock.behaviors).result([ITestBehavior.__identifier__]) self.expect(securityManager_mock.checkPermission("View", item)).result(True) # # run 5 self.expect(fti_mock.lookupSchema()).result(None) self.expect(fti_mock.behaviors).result([ITestBehavior.__identifier__]) self.expect(securityManager_mock.checkPermission("View", item)).result(True) # for all 5 runs self.expect( getSecurityManager_mock()).result(securityManager_mock).count(4) self.mocker.replay() # run 1: schema and no behavior access to schema protected attribute SCHEMA_CACHE.clear() self.assertFalse( item.__allow_access_to_unprotected_subobjects__('test', u"foo")) # # run 2: schema and no behavior access to known non schema attribute SCHEMA_CACHE.clear() self.assertTrue( item.__allow_access_to_unprotected_subobjects__('foo', u"bar")) # # run 3: schema and no behavior, unknown attributes are allowed SCHEMA_CACHE.clear() self.assertTrue( item.__allow_access_to_unprotected_subobjects__( 'random', u"stuff")) # # run 4: schema and behavior SCHEMA_CACHE.clear() self.assertTrue( item.__allow_access_to_unprotected_subobjects__('test2', u"foo2")) # run 5: no schema but behavior SCHEMA_CACHE.clear() self.assertTrue( item.__allow_access_to_unprotected_subobjects__('test2', u"foo2"))
def test_provided_by_behavior_subtype_invalidation(self): # Dummy type class MyItem(Item): pass # Fake data manager class FauxDataManager(object): def setstate(self, obj): pass def oldstate(self, obj, tid): pass def register(self, obj): pass # Dummy instance item = MyItem(id=u'id') item.portal_type = 'testtype' # Without a persistence jar, the _p_changed check doesn't work. In # this case, the cache is a bit slower. item._p_jar = FauxDataManager() # Dummy schema class ISchema(Interface): foo = zope.schema.TextLine(title=u"foo", default=u"foo_default") bar = zope.schema.TextLine(title=u"bar") # Schema is not implemented by class or provided by instance self.assertFalse(ISchema.implementedBy(MyItem)) self.assertFalse(ISchema.providedBy(item)) # Behaviors - one with a marker and one without class IBehavior1(Interface): pass behavior1 = BehaviorRegistration(u"Behavior1", "", IBehavior1, None, None) self.mock_utility(behavior1, IBehavior, name="behavior1") class IBehavior2(Interface): pass class IMarker2(Interface): pass behavior2 = BehaviorRegistration(u"Behavior2", "", IBehavior2, IMarker2, None) self.mock_utility(behavior2, IBehavior, name="behavior2") class IBehavior3(Interface): pass class IMarker3(Interface): pass behavior3 = BehaviorRegistration(u"Behavior3", "", IBehavior3, IMarker3, None) self.mock_utility(behavior3, IBehavior, name="behavior3") self.mock_adapter(DexterityBehaviorAssignable, IBehaviorAssignable, (IDexterityContent, )) # FTI mock fti_mock = Mock(wraps=DexterityFTI(u"testtype")) fti_mock.lookupSchema = Mock(return_value=ISchema) self.mock_utility(fti_mock, IDexterityFTI, name=u"testtype") # start clean SCHEMA_CACHE.invalidate('testtype') fti_mock.behaviors = ['behavior1', 'behavior2'] # implementedBy does not look into the fti self.assertFalse(ISchema.implementedBy(MyItem)) # Main schema as looked up in FTI is now provided by item ... self.assertTrue(ISchema.providedBy(item)) # Behaviors with its behavior or if provided merker as looked up in # FTI is now provided by item ... self.assertFalse(IBehavior1.providedBy(item)) self.assertTrue(IMarker2.providedBy(item)) self.assertFalse(IMarker3.providedBy(item)) # If we now invalidate the schema cache, we should get the # SECOND set of behaviors (which includes behavior3) SCHEMA_CACHE.invalidate('testtype') fti_mock.behaviors = ['behavior1', 'behavior2', 'behavior3'] # Main schema as looked up in FTI is now provided by item ... self.assertTrue(ISchema.providedBy(item)) # Behaviors with its behavior or if provided merker as looked up in # FTI is now provided by item ... self.assertFalse(IBehavior1.providedBy(item)) self.assertTrue(IMarker2.providedBy(item)) self.assertTrue(IMarker3.providedBy(item)) # If the _v_ attribute cache does not work, then we'd expect to have # to look up the schema more than once (since we invalidated) # the cache. This is not the case, as evidenced by .count(1) above. self.assertTrue(ISchema.providedBy(item)) self.assertFalse(IBehavior1.providedBy(item)) self.assertTrue(IMarker2.providedBy(item)) self.assertTrue(IMarker3.providedBy(item))
def test_provided_by_behavior_subtype(self): # Dummy type class MyItem(Item): pass class IMarkerCustom(Interface): pass # Fake data manager class FauxDataManager(object): def setstate(self, obj): pass def oldstate(self, obj, tid): pass def register(self, obj): pass # Dummy instance item = MyItem(id=u'id') item.portal_type = 'testtype' # Without a persistence jar, the _p_changed check doesn't work. In # this case, the cache is a bit slower. item._p_jar = FauxDataManager() # Dummy schema class ISchema(Interface): foo = zope.schema.TextLine(title=u"foo", default=u"foo_default") bar = zope.schema.TextLine(title=u"bar") # Schema is not implemented by class or provided by instance self.assertFalse(ISchema.implementedBy(MyItem)) self.assertFalse(ISchema.providedBy(item)) # Behaviors - one with a subtype and one without self.mock_adapter(DexterityBehaviorAssignable, IBehaviorAssignable, (IDexterityContent, )) class IBehavior1(Interface): pass behavior1 = BehaviorRegistration(u"Behavior1", "", IBehavior1, None, None) self.mock_utility(behavior1, IBehavior, name="behavior1") class IBehavior2(Interface): baz = zope.schema.TextLine(title=u"baz", default=u"baz") class IMarker2(Interface): pass behavior2 = BehaviorRegistration(u"Behavior2", "", IBehavior2, IMarker2, None) self.mock_utility(behavior2, IBehavior, name="behavior2") # FTI mock fti_mock = Mock(wraps=DexterityFTI(u"testtype")) fti_mock.lookupSchema = Mock(return_value=ISchema) fti_mock.behaviors = ['behavior1', 'behavior2'] self.mock_utility(fti_mock, IDexterityFTI, name=u"testtype") alsoProvides(fti_mock, IDexterityFTI) # start clean SCHEMA_CACHE.clear() # implementedBy does not look into the fti self.assertFalse(ISchema.implementedBy(MyItem)) # Main schema as looked up in FTI is now provided by item ... self.assertTrue(ISchema.providedBy(item)) # behavior1 does not provide a marker, the schema interface # is NOT used as a marker self.assertFalse(IBehavior1.providedBy(item)) # behavior2 provides a marker, so it is used as a marker self.assertTrue(IMarker2.providedBy(item)) # Subtypes provide field defaults. self.assertEqual(u"baz", getattr(item, "baz", None)) # We also need to ensure that the _v_ attribute doesn't hide any # interface set directly on the instance with alsoProvides() or # directlyProvides(). This is done by clearing the cache when these # are invoked. alsoProvides(item, IMarkerCustom) self.assertTrue(IMarkerCustom.providedBy(item)) # after directly setting an interface the main-schema and behavior # interfaces are still there self.assertTrue(ISchema.providedBy(item)) self.assertFalse(IBehavior1.providedBy(item)) self.assertTrue(IMarker2.providedBy(item))
def test_provided_by_behavior_subtype_invalidation(self): # Dummy type class MyItem(Item): pass # Fake data manager class FauxDataManager(object): def setstate(self, obj): pass def oldstate(self, obj, tid): pass def register(self, obj): pass # Dummy instance item = MyItem(id=u'id') item.portal_type = 'testtype' # Without a persistence jar, the _p_changed check doesn't work. In # this case, the cache is a bit slower. item._p_jar = FauxDataManager() # Dummy schema class ISchema(Interface): foo = zope.schema.TextLine(title=u"foo", default=u"foo_default") bar = zope.schema.TextLine(title=u"bar") # Schema is not implemented by class or provided by instance self.assertEquals(False, ISchema.implementedBy(MyItem)) self.assertEquals(False, ISchema.providedBy(item)) # Behaviors - one with a subtype and one without class IBehavior1(Interface): pass class IBehavior2(Interface): pass class IBehavior3(Interface): pass class ISubtype1(Interface): pass class ISubtype2(Interface): pass behavior1 = BehaviorRegistration(u"Behavior1", "", IBehavior1, None, None) behavior2 = BehaviorRegistration(u"Behavior2", "", IBehavior2, ISubtype1, None) behavior3 = BehaviorRegistration(u"Behavior3", "", IBehavior3, ISubtype2, None) self.mock_utility(behavior1, IBehavior, name="behavior1") self.mock_utility(behavior2, IBehavior, name="behavior2") self.mock_utility(behavior3, IBehavior, name="behavior3") # FTI mock fti_mock = self.mocker.proxy(DexterityFTI(u"testtype")) self.expect(fti_mock.lookupSchema()).result(ISchema).count( 2) # twice, since we invalidate # First time around, we have only these behaviors self.expect(fti_mock.behaviors).result(['behavior1', 'behavior2']).count(1) # Second time around, we add another one self.expect(fti_mock.behaviors).result( ['behavior1', 'behavior2', 'behavior3']).count(1) self.mock_utility(fti_mock, IDexterityFTI, name=u"testtype") self.replay() self.assertEquals(False, ISchema.implementedBy(MyItem)) # Schema as looked up in FTI is now provided by item ... self.assertEquals(True, ISubtype1.providedBy(item)) self.assertEquals(False, ISubtype2.providedBy(item)) self.assertEquals(True, ISchema.providedBy(item)) # If the _v_ attribute cache does not work, then we'd expect to have # to look up the schema more than once (since we invalidated) # the cache. This is not the case, as evidenced by .count(1) above. self.assertEquals(True, ISubtype1.providedBy(item)) self.assertEquals(False, ISubtype2.providedBy(item)) self.assertEquals(True, ISchema.providedBy(item)) # If we now invalidate the schema cache, we should get the second set # of behaviors SCHEMA_CACHE.invalidate('testtype') # Schema as looked up in FTI is now provided by item ... self.assertEquals(True, ISubtype1.providedBy(item)) self.assertEquals(True, ISubtype2.providedBy(item)) self.assertEquals(True, ISchema.providedBy(item)) # If the _v_ attribute cache does not work, then we'd expect to have # to look up the schema more than once (since we invalidated) # the cache. This is not the case, as evidenced by .count(1) above. self.assertEquals(True, ISubtype1.providedBy(item)) self.assertEquals(True, ISubtype2.providedBy(item)) self.assertEquals(True, ISchema.providedBy(item))
def test_provided_by_behavior_subtype(self): # Dummy type class MyItem(Item): pass # Fake data manager class FauxDataManager(object): def setstate(self, obj): pass def oldstate(self, obj, tid): pass def register(self, obj): pass # Dummy instance item = MyItem(id=u'id') item.portal_type = 'testtype' # Without a persistence jar, the _p_changed check doesn't work. In # this case, the cache is a bit slower. item._p_jar = FauxDataManager() # Dummy schema class ISchema(Interface): foo = zope.schema.TextLine(title=u"foo", default=u"foo_default") bar = zope.schema.TextLine(title=u"bar") class IMarker(Interface): pass # Schema is not implemented by class or provided by instance self.assertEquals(False, ISchema.implementedBy(MyItem)) self.assertEquals(False, ISchema.providedBy(item)) # Behaviors - one with a subtype and one without class IBehavior1(Interface): pass class IBehavior2(Interface): pass class ISubtype(Interface): baz = zope.schema.TextLine(title=u"baz", default=u"baz") behavior1 = BehaviorRegistration(u"Behavior1", "", IBehavior1, None, None) behavior2 = BehaviorRegistration(u"Behavior2", "", IBehavior2, ISubtype, None) self.mock_utility(behavior1, IBehavior, name="behavior1") self.mock_utility(behavior2, IBehavior, name="behavior2") # FTI mock fti_mock = self.mocker.proxy(DexterityFTI(u"testtype")) self.expect(fti_mock.lookupSchema()).result(ISchema).count(1) self.expect(fti_mock.behaviors).result(['behavior1', 'behavior2']).count(1) self.mock_utility(fti_mock, IDexterityFTI, name=u"testtype") self.replay() self.assertEquals(False, ISchema.implementedBy(MyItem)) # Schema as looked up in FTI is now provided by item ... self.assertEquals(True, ISubtype.providedBy(item)) self.assertEquals(True, ISchema.providedBy(item)) # If the _v_ attribute cache does not work, then we'd expect to have # to look up the schema more than once (since we invalidated) # the cache. This is not the case, as evidenced by .count(1) above. self.assertEquals(True, ISubtype.providedBy(item)) self.assertEquals(True, ISchema.providedBy(item)) # Subtypes provide field defaults. self.assertEquals(u"baz", getattr(item, "baz", None)) # We also need to ensure that the _v_ attribute doesn't hide any # interface set directly on the instance with alsoProvides() or # directlyProvides(). This is done by clearing the cache when these # are invoked. alsoProvides(item, IMarker) self.assertEquals(True, IMarker.providedBy(item)) self.assertEquals(True, ISubtype.providedBy(item)) self.assertEquals(True, ISchema.providedBy(item))
def test_item(self): # Mock schema model class ITestSchema(Interface): test = zope.schema.TextLine(title=u"Test") ITestSchema.setTaggedValue(READ_PERMISSIONS_KEY, dict(test='zope2.View', foo='foo.View')) from plone.autoform.interfaces import IFormFieldProvider @provider(IFormFieldProvider) class ITestBehavior(Interface): test2 = zope.schema.TextLine(title=u"Test") ITestBehavior.setTaggedValue(READ_PERMISSIONS_KEY, dict(test2='zope2.View', foo2='foo.View')) # Mock a test behavior from plone.behavior.registration import BehaviorRegistration registration = BehaviorRegistration( title=u"Test Behavior", description=u"Provides test behavior", interface=ITestBehavior, marker=Interface, factory=None) from plone.behavior.interfaces import IBehavior self.mock_utility(registration, IBehavior, ITestBehavior.__identifier__) from plone.dexterity.behavior import DexterityBehaviorAssignable from plone.dexterity.interfaces import IDexterityContent from plone.behavior.interfaces import IBehaviorAssignable self.mock_adapter(DexterityBehaviorAssignable, IBehaviorAssignable, (IDexterityContent, )) # Mock FTI fti_mock = DexterityFTI(u"testtype") fti_mock.behaviors = () fti_mock.lookupSchema = Mock(return_value=ITestSchema) self.mock_utility(fti_mock, IDexterityFTI, u'testtype') # Mock permissions self.mock_utility(Permission(u'zope2.View', u"View"), IPermission, u'zope2.View') self.mock_utility(Permission(u'foo.View', u"View foo"), IPermission, u'foo.View') # Content item item = Item('test') item.portal_type = u"testtype" item.test = u"foo" item.foo = u"bar" # mock security manager security_manager_mock = Mock() from AccessControl import getSecurityManager self.patch_global(getSecurityManager, return_value=security_manager_mock) # run 1: schema and no behavior access to schema protected attribute security_manager_mock.checkPermission = Mock(return_value=False) SCHEMA_CACHE.clear() self.assertFalse( item.__allow_access_to_unprotected_subobjects__('test', u"foo")) security_manager_mock.checkPermission.assert_called_with('View', item) # run 2: schema and no behavior access to known non schema attribute security_manager_mock.checkPermission = Mock(return_value=True) SCHEMA_CACHE.clear() self.assertTrue( item.__allow_access_to_unprotected_subobjects__('foo', u"bar")) security_manager_mock.checkPermission.assert_called_with( 'View foo', item) # run 3: schema and no behavior, unknown attributes are allowed SCHEMA_CACHE.clear() self.assertTrue( item.__allow_access_to_unprotected_subobjects__( 'random', u"stuff")) # run 4: schema and behavior security_manager_mock.checkPermission = Mock(return_value=True) fti_mock.behaviors = [ITestBehavior.__identifier__] SCHEMA_CACHE.clear() self.assertTrue( item.__allow_access_to_unprotected_subobjects__('test2', u"foo2")) security_manager_mock.checkPermission.assert_called_with('View', item) # run 5: no schema but behavior security_manager_mock.checkPermission = Mock(return_value=True) fti_mock.lookupSchema = Mock(return_value=None) SCHEMA_CACHE.clear() self.assertTrue( item.__allow_access_to_unprotected_subobjects__('test2', u"foo2")) security_manager_mock.checkPermission.assert_called_with('View', item)
def behaviorDirective(_context, title, provides, name=None, description=None, marker=None, factory=None, for_=None): if marker is None and factory is None: marker = provides if marker is not None and factory is None and marker is not provides: raise ConfigurationError( u"You cannot specify a different 'marker' and 'provides' if " u"there is no adapter factory for the provided interface.") # Instantiate the real factory if it's the schema-aware type. We do # this here so that the for_ interface may take this into account. if factory is not None and ISchemaAwareFactory.providedBy(factory): factory = factory(provides) registration = BehaviorRegistration( title=title, description=description, interface=provides, marker=marker, factory=factory, name=name, ) # behavior registration by provides interface identifier utility(_context, provides=IBehavior, name=provides.__identifier__, component=registration) if name is not None: # for convinience we register with a given name utility(_context, provides=IBehavior, name=name, component=registration) if factory is None: if for_ is not None: logger.warn( u"Specifying 'for' in behavior '{0}' if no 'factory' is given " u"has no effect and is superfluous.".format(title)) # w/o factory we're done here return if for_ is None: # Attempt to guess the factory's adapted interface and use it as # the 'for_'. # Fallback to '*' (=Interface). adapts = getattr(factory, '__component_adapts__', None) or [Interface] if len(adapts) != 1: raise ConfigurationError( u"The factory can not be declared as multi-adapter.") for_ = adapts[0] adapter_factory = BehaviorAdapterFactory(registration) adapter(_context, factory=(adapter_factory, ), provides=provides, for_=(for_, ))
def behaviorDirective(_context, title, provides, name=None, description=None, marker=None, factory=None, for_=None, name_only=False): if marker is None and factory is None: # a schema only behavior means usually direct attribute settings on the # object itself, so the object itself provides the interface. # so we mark with the provides. marker = provides if marker is not None and factory is None and marker is not provides: raise ConfigurationError( u'You cannot specify a different \'marker\' and \'provides\' if ' u'there is no adapter factory for the provided interface.') if name_only and name is None: raise ConfigurationError( u'If you decide to only register by \'name\', a name must ' u'be given.') # Instantiate the real factory if it's the schema-aware type. We do # this here so that the for_ interface may take this into account. if factory is not None and ISchemaAwareFactory.providedBy(factory): factory = factory(provides) # the behavior registration hold all information about the behavior. registration = BehaviorRegistration( title=title, description=description, interface=provides, marker=marker, factory=factory, name=name, ) # the behavior registration can be looked up as a named utility. # the name of the utility is either the full dotted path of the interface # it provides... if not name_only: # behavior registration by provides interface identifier utility(_context, provides=IBehavior, name=provides.__identifier__, component=registration) if name is not None: # .. or if given, we register with a given (short) name. # Advantage is, we can have more than one implementations of a # behavior on one object (if a factory is used). # This is handy for certain use cases. utility(_context, provides=IBehavior, name=name, component=registration) if factory is None: if for_ is not None: logger.warn( u'Specifying \'for\' in behavior \'{0}\' if no \'factory\' is ' u'given has no effect and is superfluous.'.format(title)) # w/o factory we're done here: schema only behavior return if for_ is None: for_ = _detect_for(factory, marker) adapter_factory = BehaviorAdapterFactory(registration) adapter(_context, factory=(adapter_factory, ), provides=provides, for_=(for_, ))