def test_detect_schema_change(self):
     dummy = self._dummy1
     self.assertTrue(dummy._isSchemaCurrent())
     dummy.__class__.schema = schema2.copy()
     # Reregister the type.  (Not needed in AT <= 1.5.1)
     registerType(Dummy1, 'Archetypes')
     self.assertFalse(dummy._isSchemaCurrent())
     dummy._updateSchema()
     self.assertTrue(dummy._isSchemaCurrent())
    def test_instance_schema_is_harmful(self):
        """Show that having a schema in the instance is harmful.

        schema should be a class attribute, not an instance attribute.

        The only thing this really tests is that for AT >= 1.5.2,
        having a schema attribute on the instance is bad.  In earlier
        ATs this is no problem.  Nothing bad happens due to the
        earlier AT code.  But the newer ATs cannot handle older
        content that has had a schema update already.

        So: if you copy this test to an earlier Archetypes and it
        fails, that is okay really.  But in AT >= 1.5.2 it does *not*
        fail and this means that some code needs be added to migrate
        old content.
        """
        dummy = self._dummy1
        self.assertTrue(dummy._isSchemaCurrent())

        # You can make schema an instance attribute if you want (or if
        # you are not careful).
        self.assertFalse('schema' in dummy.__dict__)
        dummy.schema = dummy.__class__.schema
        self.assertTrue('schema' in dummy.__dict__)
        # The schema has not *really* changed:
        self.assertTrue(dummy._isSchemaCurrent())
        # But the damage has been done, as we will show soon.

        # We give the class of our content a different schema.
        dummy.__class__.schema = schema2.copy()
        # Reregister the type.  (Not needed in AT <= 1.5.1)
        registerType(Dummy1, 'Archetypes')
        # We are not testing the _isSchemaCurrent method here, so we
        # can simply cheat to let the object know that its schema is
        # not current anymore.
        dummy._signature = 'bogus'
        self.assertFalse(dummy._isSchemaCurrent())

        # Our class has a TEXTFIELD2, but our content does not now it
        # yet.  It *does* already have the getter for that field.
        dummy.getTEXTFIELD2
        self.assertRaises(KeyError, dummy.getTEXTFIELD2)

        # No problem, we just need to update the schema of the
        # content.  Might as well do that for all objects, as that is
        # what the user will do in practice.
        dummy._updateSchema()

        # And now we can get our second text field, right?  Wrong.
        # Only the getter is there and it does not work.
        self.assertTrue(hasattr(dummy, 'getTEXTFIELD2'))
        # Actually, the next two tests fail for AT <= 1.5.1, which is
        # actually good.
        self.assertRaises(KeyError, dummy.getTEXTFIELD2)
        self.assertFalse(hasattr(dummy, 'TEXTFIELD2'))

        # And the first field was required in the first schema but not
        # in the second.  This does not show yet.
        self.assertTrue(dummy.getField('TEXTFIELD1').required)

        # This can be fixed by deleting the schema attribute of the
        # instance.
        del dummy.schema
        self.assertFalse(dummy.getField('TEXTFIELD1').required)

        # At first, direct attribute access for the second field still
        # does not work:
        self.assertFalse(hasattr(dummy, 'TEXTFIELD2'))
        # But calling the getter works.
        self.assertEqual(dummy.getTEXTFIELD2(), 'B')
        # And after that call, direct attribute access works too.
        self.assertEqual(dummy.TEXTFIELD2(), 'B')
                                        schemata="default",
                                        sizes=None,
                                        required=True,
                                        primary=True,
                                        widget=field.ImageWidget(
                                            label=_("Infographic"),
                                            description=_("Infographic image"),
                                            i18n_domain='eea',
                                        )), ))


class Infographic(image.ATImage):
    """ Infographic """

    implements(IInfographic)

    meta_type = "Infographic"
    portal_type = "Infographic"
    archetypes_name = "Infographic"

    _at_rename_after_creation = True

    security = ClassSecurityInfo()

    schema = (image.ATImageSchema.copy() + SCHEMA.copy())
    schema["title"].required = True
    schema["relatedItems"].required_for_published = True


registerType(Infographic, PROJECTNAME)
Example #4
0
    def clearDefaultForType(self, type):
        ct = getToolByName(self, TOOL_ID)
        ct.clearDefaultLayoutForType(type)

    def isRegisteredForType(self, type):
        ct = getToolByName(self, TOOL_ID)
        return self in ct.getRegisteredLayoutsForType(type)

    def isDefaultForType(self, type):
        ct = getToolByName(self, TOOL_ID)
        try:
            return self == ct.getDefaultLayoutForType(type)
        except CompositePackError:
            return False


# Prevents from deleting the tool and doesn't call's the base class
# manage_beforeDelete!
#     security.declarePrivate('manage_beforeDelete')
#     def manage_beforeDelete(self, item, container):
#         from OFS.ObjectManager import BeforeDeleteException
#         ct = getToolByName(self, TOOL_ID)
#         if ct.getDefaultLayout() == self.getId():
#             raise BeforeDeleteException, 'cannot unregister default layout'

InitializeClass(Layout)

registerType(SkinMethod, PROJECTNAME)
registerType(Viewlet, PROJECTNAME)
registerType(Layout, PROJECTNAME)
        ''' Just in case we get indexed anyway.'''
        return ''

    def indexObject(self):
        '''composite container is never catalogued'''
        pass

    def reindexObject(self, idxs=[]):
        '''composite container is never catalogued'''
        pass

    def unindexObject(self):
        '''composite container is never catalogued'''
        pass

registerType(PackComposite, PROJECTNAME)

# methods monkeypatched ClassGen

def _setPortalTypeName(self, pt):
    ret = self.__cp__setPortalTypeName__(pt)
    try:
        self.cp_container.initializeSlots()
    except:
        # XXX log something?
        pass
    return ret
_setPortalTypeName.__cp_method__ = True

def manage_afterAdd(self, item, container):
    if getattr(aq_base(self), 'cp_container', None) is None:
        return ''

    def indexObject(self):
        '''composite container is never catalogued'''
        pass

    def reindexObject(self, idxs=[]):
        '''composite container is never catalogued'''
        pass

    def unindexObject(self):
        '''composite container is never catalogued'''
        pass


registerType(PackComposite, PROJECTNAME)

# methods monkeypatched ClassGen


def _setPortalTypeName(self, pt):
    ret = self.__cp__setPortalTypeName__(pt)
    try:
        self.cp_container.initializeSlots()
    except:
        # XXX log something?
        pass
    return ret


_setPortalTypeName.__cp_method__ = True
    def clearDefaultForType(self, type):
        ct = getToolByName(self, TOOL_ID)
        ct.clearDefaultLayoutForType(type)

    def isRegisteredForType(self, type):
        ct = getToolByName(self, TOOL_ID)
        return self in ct.getRegisteredLayoutsForType(type)

    def isDefaultForType(self, type):
        ct = getToolByName(self, TOOL_ID)
        try:
            return self == ct.getDefaultLayoutForType(type)
        except CompositePackError:
            return False

# Prevents from deleting the tool and doesn't call's the base class
# manage_beforeDelete!
#     security.declarePrivate('manage_beforeDelete')
#     def manage_beforeDelete(self, item, container):
#         from OFS.ObjectManager import BeforeDeleteException
#         ct = getToolByName(self, TOOL_ID)
#         if ct.getDefaultLayout() == self.getId():
#             raise BeforeDeleteException, 'cannot unregister default layout'

InitializeClass(Layout)


registerType(SkinMethod, PROJECTNAME)
registerType(Viewlet, PROJECTNAME)
registerType(Layout, PROJECTNAME)