def test_portalTypeToSchemaName_with_schema_and_prefix(self): self.assertEqual( 'prefix_0_type_0_schema', schema.portalTypeToSchemaName('type', 'schema', 'prefix')) self.assertEqual('prefix_0_type', schema.portalTypeToSchemaName('type', '', 'prefix')) self.assertEqual( 'prefix_0_type_1_one_2_two', schema.portalTypeToSchemaName('type one.two', '', 'prefix'))
def test_portalTypeToSchemaName_with_schema_and_prefix(self): self.assertEqual( 'prefix_0_type_0_schema', schema.portalTypeToSchemaName('type', 'schema', 'prefix') ) self.assertEqual( 'prefix_0_type', schema.portalTypeToSchemaName('type', '', 'prefix') ) self.assertEqual( 'prefix_0_type_1_one_2_two', schema.portalTypeToSchemaName('type one.two', '', 'prefix') )
def test_named_schema(self): # Mock schema model class IDummy(Interface): dummy = zope.schema.TextLine(title=u"Dummy") class INamedDummy(Interface): named = zope.schema.TextLine(title=u"Named") mock_model = Model({u"": IDummy, u"named": INamedDummy}) # Mock FTI fti_mock = self.mocker.mock(DexterityFTI) fti_mock.lookupModel() self.mocker.result(mock_model) self.mock_utility(fti_mock, IDexterityFTI, u'testtype') self.mocker.replay() factory = schema.SchemaModuleFactory() schemaName = schema.portalTypeToSchemaName('testtype', schema=u"named", prefix='site') klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) # only default schema gets this: self.assertFalse(klass.isOrExtends(IDexteritySchema)) self.assertFalse(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual('plone.dexterity.schema.generated', klass.__module__) self.assertEqual(('named', ), tuple(zope.schema.getFieldNames(klass)))
def test_dynamic_schema_refreshed_on_modify_model_file(self): portal_type = u"testtype" fti = DexterityFTI(portal_type) class INew(Interface): title = zope.schema.TextLine(title=u"title") model_dummy = Model({u"": INew}) fti.lookupModel = Mock(return_value=model_dummy) self.create_dummy() site_dummy = self.create_dummy( getPhysicalPath=lambda: ('', 'siteid') ) self.mock_utility(site_dummy, ISiteRoot) class IBlank1(Interface): pass # Set source interface schemaName = portalTypeToSchemaName(fti.getId()) setattr(plone.dexterity.schema.generated, schemaName, IBlank1) # Sync this with schema ftiModified( fti, ObjectModifiedEvent( fti, DexterityFTIModificationDescription('model_file', '') ) ) self.assertTrue('title' in IBlank1) self.assertTrue(IBlank1['title'].title == u"title")
def test_concrete_default_schema(self): # Mock schema model class IDummy(Interface): dummy = zope.schema.TextLine(title=u"Dummy") mock_model = Model({u"": IDummy}) # Mock FTI fti_mock = self.mocker.mock(DexterityFTI) fti_mock.lookupModel() self.mocker.result(mock_model) self.mock_utility(fti_mock, IDexterityFTI, u'testtype') self.mocker.replay() factory = schema.SchemaModuleFactory() schemaName = schema.portalTypeToSchemaName('testtype', prefix='site') klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) self.assertTrue(klass.isOrExtends(IDexteritySchema)) self.assertTrue(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual('plone.dexterity.schema.generated', klass.__module__) self.assertEqual(('dummy',), tuple(zope.schema.getFieldNames(klass)))
def test_named_schema(self): # Mock schema model class IDummy(Interface): dummy = zope.schema.TextLine(title=u"Dummy") class INamedDummy(Interface): named = zope.schema.TextLine(title=u"Named") mock_model = Model({u"": IDummy, u"named": INamedDummy}) # Mock FTI fti_mock = Mock(spec=DexterityFTI) fti_mock.lookupModel = Mock(return_value=mock_model) self.mock_utility(fti_mock, IDexterityFTI, u'testtype') factory = schema.SchemaModuleFactory() schemaName = schema.portalTypeToSchemaName( 'testtype', schema=u"named", prefix='site' ) klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) # only default schema gets this: self.assertFalse(klass.isOrExtends(IDexteritySchema)) self.assertFalse(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual('plone.dexterity.schema.generated', klass.__module__) self.assertEqual(('named',), tuple(zope.schema.getFieldNames(klass)))
def ftiModified(object, event): """When an FTI is modified, re-sync and invalidate the schema, if necessary. """ if not IDexterityFTI.providedBy(event.object): return fti = event.object portal_type = fti.getId() mod = {} for desc in event.descriptions: if IDexterityFTIModificationDescription.providedBy(desc): mod[desc.attribute] = desc.oldValue # If the factory utility name was modified, we may get an orphan if one # was registered as a local utility to begin with. If so, remove the # orphan. if 'factory' in mod: old_factory = mod['factory'] site_manager = getGlobalSiteManager() # Remove previously registered factory, if no other type uses it. unregister_factory(old_factory, site_manager) # Register a new local factory if one doesn't exist already new_factory_utility = queryUtility(IFactory, name=fti.factory) if new_factory_utility is None: site_manager.registerUtility(DexterityFactory(portal_type), IFactory, fti.factory, info='plone.dexterity.dynamic') # Determine if we need to invalidate the schema at all if 'behaviors' in mod \ or 'schema' in mod \ or 'model_source' in mod \ or 'model_file' in mod \ or 'schema_policy' in mod: # Determine if we need to re-sync a dynamic schema if ((fti.model_source or fti.model_file) and ('model_source' in mod or 'model_file' in mod or 'schema_policy' in mod)): schemaName = portalTypeToSchemaName(portal_type) schema = getattr(plone.dexterity.schema.generated, schemaName) model = fti.lookupModel() sync_bases = 'schema_policy' in mod syncSchema(model.schema, schema, overwrite=True, sync_bases=sync_bases) notify(SchemaInvalidatedEvent(portal_type))
def test_portalTypeToSchemaName_looks_up_portal_for_prefix(self): portal_mock = Mock() portal_mock.getPhysicalPath = Mock( return_value=['', 'foo', 'portalid']) self.mock_utility(portal_mock, ISiteRoot) self.assertEqual('foo_4_portalid_0_type', schema.portalTypeToSchemaName('type'))
def test_portalTypeToSchemaName_looks_up_portal_for_prefix(self): portal_mock = self.mocker.mock() self.expect(portal_mock.getPhysicalPath()).result(("", "foo", "portalid")) self.mock_utility(portal_mock, ISiteRoot) self.replay() self.assertEqual("foo_4_portalid_0_type", schema.portalTypeToSchemaName("type"))
def ftiModified(object, event): """When an FTI is modified, re-sync and invalidate the schema, if necessary. """ if not IDexterityFTI.providedBy(event.object): return fti = event.object portal_type = fti.getId() mod = {} for desc in event.descriptions: if IDexterityFTIModificationDescription.providedBy(desc): mod[desc.attribute] = desc.oldValue # If the factory utility name was modified, we may get an orphan if one # was registered as a local utility to begin with. If so, remove the # orphan. if 'factory' in mod: old_factory = mod['factory'] site = getUtility(ISiteRoot) site_manager = getSiteManager(site) # Remove previously registered factory, if no other type uses it. unregister_factory(old_factory, site_manager) # Register a new local factory if one doesn't exist already new_factory_utility = queryUtility(IFactory, name=fti.factory) if new_factory_utility is None: site_manager.registerUtility( DexterityFactory(portal_type), IFactory, fti.factory, info='plone.dexterity.dynamic' ) # Determine if we need to invalidate the schema at all if 'behaviors' in mod \ or 'schema' in mod \ or 'model_source' in mod \ or 'model_file' in mod \ or 'schema_policy' in mod: # Determine if we need to re-sync a dynamic schema if (fti.model_source or fti.model_file) \ and ('model_source' in mod or 'model_file' in mod or 'schema_policy' in mod): schemaName = portalTypeToSchemaName(portal_type) schema = getattr(plone.dexterity.schema.generated, schemaName) model = fti.lookupModel() sync_bases = 'schema_policy' in mod syncSchema(model.schema, schema, overwrite=True, sync_bases=sync_bases) notify(SchemaInvalidatedEvent(portal_type))
def test_portalTypeToSchemaName_looks_up_portal_for_prefix(self): portal_mock = Mock() portal_mock.getPhysicalPath = Mock(return_value=['', 'foo', 'portalid']) self.mock_utility(portal_mock, ISiteRoot) self.assertEqual( 'foo_4_portalid_0_type', schema.portalTypeToSchemaName('type') )
def test_portalTypeToSchemaName_looks_up_portal_for_prefix(self): portal_mock = self.mocker.mock() self.expect(portal_mock.getPhysicalPath()).result( ('', 'foo', 'portalid')) self.mock_utility(portal_mock, ISiteRoot) self.replay() self.assertEqual('foo_4_portalid_0_type', schema.portalTypeToSchemaName('type'))
def test_lookupSchema_with_nonexistant_schema(self): """ Tests the case where a dexterity type is not removed cleanly from the fti, but the code has been removed. """ fti = DexterityFTI(u"testtype") fti.schema = 'model.wont.be.imported' portal = self.create_dummy(getPhysicalPath=lambda: ('', 'site')) self.mock_utility(portal, ISiteRoot) schemaName = portalTypeToSchemaName(fti.getId()) setattr(plone.dexterity.schema.generated, schemaName, ITestSchema) self.assertEqual(ITestSchema, fti.lookupSchema()) delattr(plone.dexterity.schema.generated, schemaName)
def test_portalTypeToSchemaName_looks_up_portal_for_prefix(self): portal_mock = self.mocker.mock() self.expect( portal_mock.getPhysicalPath() ).result(('', 'foo', 'portalid')) self.mock_utility(portal_mock, ISiteRoot) self.replay() self.assertEqual( 'foo_4_portalid_0_type', schema.portalTypeToSchemaName('type') )
def test_transient_schema(self): # No IDexterityFTI registered factory = schema.SchemaModuleFactory() schemaName = schema.portalTypeToSchemaName('testtype', prefix='site') klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) self.assertTrue(klass.isOrExtends(IDexteritySchema)) self.assertTrue(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual('plone.dexterity.schema.generated', klass.__module__) self.assertEqual((), tuple(zope.schema.getFields(klass)))
def test_lookupSchema_with_dynamic_schema(self): fti = DexterityFTI(u"testtype") fti.schema = None # use dynamic schema portal = self.create_dummy(getPhysicalPath=lambda: ('', 'site')) self.mock_utility(portal, ISiteRoot) schemaName = portalTypeToSchemaName(fti.getId()) setattr(plone.dexterity.schema.generated, schemaName, ITestSchema) self.assertEqual(ITestSchema, fti.lookupSchema()) # cleanup delattr(plone.dexterity.schema.generated, schemaName)
def test_transient_schema_made_concrete(self): factory = schema.SchemaModuleFactory() schemaName = schema.portalTypeToSchemaName("testtype", prefix="site") # No IDexterityFTI registered klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) self.assertTrue(klass.isOrExtends(IDexteritySchema)) self.assertTrue(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual("plone.dexterity.schema.generated", klass.__module__) self.assertEqual((), tuple(zope.schema.getFields(klass))) # Calling it again gives the same result klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) self.assertTrue(klass.isOrExtends(IDexteritySchema)) self.assertTrue(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual("plone.dexterity.schema.generated", klass.__module__) self.assertEqual((), tuple(zope.schema.getFields(klass))) # Now register a mock FTI and try again class IDummy(Interface): dummy = zope.schema.TextLine(title=u"Dummy") mock_model = Model({u"": IDummy}) fti_mock = self.mocker.mock(DexterityFTI) fti_mock.lookupModel() self.mocker.result(mock_model) self.mock_utility(fti_mock, IDexterityFTI, u"testtype") self.mocker.replay() klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) self.assertTrue(klass.isOrExtends(IDexteritySchema)) self.assertTrue(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual("plone.dexterity.schema.generated", klass.__module__) # Now we get the fields from the FTI's model self.assertEqual(("dummy",), tuple(zope.schema.getFieldNames(klass)))
def test_transient_schema_made_concrete(self): factory = schema.SchemaModuleFactory() schemaName = schema.portalTypeToSchemaName('testtype', prefix='site') # No IDexterityFTI registered klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) self.assertTrue(klass.isOrExtends(IDexteritySchema)) self.assertTrue(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual('plone.dexterity.schema.generated', klass.__module__) self.assertEqual((), tuple(zope.schema.getFields(klass))) # Calling it again gives the same result klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) self.assertTrue(klass.isOrExtends(IDexteritySchema)) self.assertTrue(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual('plone.dexterity.schema.generated', klass.__module__) self.assertEqual((), tuple(zope.schema.getFields(klass))) # Now register a mock FTI and try again class IDummy(Interface): dummy = zope.schema.TextLine(title=u"Dummy") mock_model = Model({u"": IDummy}) fti_mock = self.mocker.mock(DexterityFTI) fti_mock.lookupModel() self.mocker.result(mock_model) self.mock_utility(fti_mock, IDexterityFTI, u'testtype') self.mocker.replay() klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) self.assertTrue(klass.isOrExtends(IDexteritySchema)) self.assertTrue(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual('plone.dexterity.schema.generated', klass.__module__) # Now we get the fields from the FTI's model self.assertEqual(('dummy', ), tuple(zope.schema.getFieldNames(klass)))
def test_dynamic_schema_refreshed_on_modify_schema_policy(self): portal_type = u"testtype" fti = DexterityFTI(portal_type) class INew(Interface): title = zope.schema.TextLine(title=u"title") class IBlank3(Interface): pass class TestSchemaPolicy(DexteritySchemaPolicy): def bases(self, schemaName, tree): return (INew,) gsm = getGlobalSiteManager() policy = TestSchemaPolicy() gsm.registerUtility( policy, plone.supermodel.interfaces.ISchemaPolicy, name=u"test" ) site_dummy = self.create_dummy( getPhysicalPath=lambda: ('', 'siteid') ) self.mock_utility(site_dummy, ISiteRoot) # Set source interface schemaName = portalTypeToSchemaName(fti.getId()) setattr(plone.dexterity.schema.generated, schemaName, IBlank3) original = getattr(plone.dexterity.schema.generated, schemaName) self.assertNotIn(INew, original.__bases__) self.assertNotIn('title', original) # Set new schema_policy fti.schema_policy = "test" # Sync this with schema ftiModified( fti, ObjectModifiedEvent( fti, DexterityFTIModificationDescription('schema_policy', '') ) ) updated = getattr(plone.dexterity.schema.generated, schemaName) self.assertIn('title', updated) self.assertIn(INew, updated.__bases__)
def test_dynamic_schema_refreshed_on_modify_model_source(self): portal_type = u"testtype" fti = DexterityFTI(portal_type) class INew(Interface): title = zope.schema.TextLine(title=u"title") model_dummy = Model({u"": INew}) fti.lookupModel = Mock(return_value=model_dummy) self.create_dummy() site_dummy = self.create_dummy( getPhysicalPath=lambda: ('', 'siteid') ) self.mock_utility(site_dummy, ISiteRoot) # b/c of zope.interface does not support hashing of the same class multiple times # we need to postfix with a unique number # see https://github.com/zopefoundation/zope.interface/issues/216#issuecomment-701332380 class IBlank2(Interface): pass # Set source interface schemaName = portalTypeToSchemaName(fti.getId()) setattr(plone.dexterity.schema.generated, schemaName, IBlank2) # Sync this with schema ftiModified( fti, ObjectModifiedEvent( fti, DexterityFTIModificationDescription('model_source', '') ) ) self.assertTrue('title' in IBlank2) self.assertTrue(IBlank2['title'].title == u"title")
def lookupSchema(self): schema = None # If a specific schema is given, use it if self.schema: try: schema = utils.resolveDottedName(self.schema) except ImportError: logging.warning( 'Schema {0:s} set for type {1:s} cannot be resolved'. format(self.schema, self.getId())) # fall through to return a fake class with no # fields so that end user code doesn't break if schema: return schema # Otherwise, look up a dynamic schema. This will query the model for # an unnamed schema if it is the first time it is looked up. # See schema.py schemaName = portalTypeToSchemaName(self.getId()) return getattr(plone.dexterity.schema.generated, schemaName)
def test_concrete_schema_not_refreshed_on_modify_schema(self): portal_type = u"testtype" fti = DexterityFTI(portal_type) class IBlank4(Interface): pass class INew(Interface): title = zope.schema.TextLine(title=u"title") model_dummy = Model({u"": INew}) fti.lookupModel = Mock(return_value=model_dummy) site_dummy = self.create_dummy( getPhysicalPath=lambda: ('', 'siteid') ) self.mock_utility(site_dummy, ISiteRoot) # Set schema to something so that hasDynamicSchema is false fti.schema = IBlank4.__identifier__ assert not fti.hasDynamicSchema # Set source for dynamic FTI - should not be used schemaName = portalTypeToSchemaName(fti.getId()) setattr(plone.dexterity.schema.generated, schemaName, IBlank4) # Sync should not happen now ftiModified( fti, ObjectModifiedEvent( fti, DexterityFTIModificationDescription('schema', '') ) ) self.assertFalse('title' in IBlank4)
def test_concrete_default_schema(self): # Mock schema model class IDummy(Interface): dummy = zope.schema.TextLine(title=u"Dummy") mock_model = Model({u"": IDummy}) # Mock FTI fti_mock = Mock(spec=DexterityFTI) fti_mock.lookupModel = Mock(return_value=mock_model) self.mock_utility(fti_mock, IDexterityFTI, u'testtype') factory = schema.SchemaModuleFactory() schemaName = schema.portalTypeToSchemaName('testtype', prefix='site') klass = factory(schemaName, schema.generated) self.assertTrue(isinstance(klass, InterfaceClass)) self.assertTrue(klass.isOrExtends(IDexteritySchema)) self.assertTrue(IContentType.providedBy(klass)) self.assertEqual(schemaName, klass.__name__) self.assertEqual('plone.dexterity.schema.generated', klass.__module__) self.assertEqual(('dummy', ), tuple(zope.schema.getFieldNames(klass)))
def lookupSchema(self): schema = None # If a specific schema is given, use it if self.schema: try: schema = utils.resolveDottedName(self.schema) except ImportError: logging.warning( u"Schema %s set for type %s cannot be resolved" % (self.schema, self.getId()) ) # fall through to return a fake class with no # fields so that end user code doesn't break if schema: return schema # Otherwise, look up a dynamic schema. This will query the model for # an unnamed schema if it is the first time it is looked up. # See schema.py schemaName = portalTypeToSchemaName(self.getId()) return getattr(plone.dexterity.schema.generated, schemaName)
def test_ct_productimg_schema(self): fti = queryUtility(IDexterityFTI, name='ProductIMG') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('ProductIMG') self.assertEqual(schema_name, schema.getName())
def test_ct_navassistantcards_schema(self): fti = queryUtility(IDexterityFTI, name='NavAssistantCards') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('NavAssistantCards') self.assertEqual(schema_name, schema.getName())
def test_ct_crop_container_schema(self): fti = queryUtility(IDexterityFTI, name='CropContainer') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('CropContainer') self.assertEqual(schema_name, schema.getName())
def test_ct_embed_content_schema(self): fti = queryUtility(IDexterityFTI, name='EmbedContent') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('EmbedContent') self.assertEqual(schema_name, schema.getName())
def test_ct_diseases_schema(self): fti = queryUtility(IDexterityFTI, name='Diseases') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('Diseases') self.assertEqual(schema_name, schema.getName())
def test_ct_youtube_schema(self): fti = queryUtility(IDexterityFTI, name='Youtube') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('Youtube') self.assertEqual(schema_name, schema.getName())
def test_ct_folderish_animation_schema(self): fti = queryUtility(IDexterityFTI, name='FolderishAnimation') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('FolderishAnimation') self.assertEqual(schema_name, schema.getName())
def test_ct_solution_service_schema(self): fti = queryUtility(IDexterityFTI, name='Solution Service') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('Solution Service') self.assertEqual(schema_name, schema.getName())
def test_ct_lerneinheit_schema(self): fti = queryUtility(IDexterityFTI, name='Lerneinheit') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('Lerneinheit') self.assertEqual(schema_name, schema.getName())
def test_ct_o_c_d_s_document_schema(self): fti = queryUtility(IDexterityFTI, name='OCDS Document') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('OCDS Document') self.assertEqual(schema_name, schema.getName())
def test_ct_zhkathauthor_schema(self): fti = queryUtility(IDexterityFTI, name='zhkathauthor') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('zhkathauthor') self.assertEqual(schema_name, schema.getName())
def test_ct_datagrid_demo_type_schema(self): fti = queryUtility(IDexterityFTI, name='DatagridDemoType') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('DatagridDemoType') self.assertEqual(schema_name, schema.getName())
def test_ct_cool_view_schema(self): fti = queryUtility(IDexterityFTI, name='Cool View') schema = fti.lookupSchema() schema_name = portalTypeToSchemaName('Cool View') self.assertEqual(schema_name, schema.getName())
def test_portalTypeToSchemaName_with_schema_and_prefix(self): self.assertEqual("prefix_0_type_0_schema", schema.portalTypeToSchemaName("type", "schema", "prefix")) self.assertEqual("prefix_0_type", schema.portalTypeToSchemaName("type", "", "prefix")) self.assertEqual("prefix_0_type_1_one_2_two", schema.portalTypeToSchemaName("type one.two", "", "prefix"))