Esempio n. 1
0
    def test_export_field_ref(self):

        xml = """\
<registry>
  <record name="test.export.simple">
    <field type="plone.registry.field.TextLine">
      <default>N/A</default>
      <title>Simple record</title>
    </field>
    <value>Sample value</value>
  </record>
  <record name="test.export.simple.override">
    <field ref="test.export.simple" />
    <value>Another value</value>
  </record>
</registry>"""

        self.registry.records['test.export.simple'] = refRecord = \
            Record(field.TextLine(title=u"Simple record", default=u"N/A"),
                   value=u"Sample value")

        self.registry.records['test.export.simple.override'] = \
            Record(FieldRef(refRecord.__name__, refRecord.field),
                   value=u"Another value")

        context = DummyExportContext(self.site)
        exportRegistry(context)

        self.assertEqual('registry.xml', context._wrote[0][0])
        self.assertXmlEquals(xml, context._wrote[0][1])
Esempio n. 2
0
def fix_double_smaxage(context):
    """Fix caching definition.

    plone.resource.maxage has title and description from shared maxage.
    See https://github.com/plone/Products.CMFPlone/issues/1989
    """
    from plone.registry.interfaces import IPersistentField
    from plone.registry.record import Record
    from plone.registry import field
    from plone.registry import FieldRef
    from zope.component import queryAdapter
    registry = getUtility(IRegistry)
    # If these three registry records are not defined,
    # we do no fix.
    maxage = 'plone.app.caching.strongCaching.plone.resource.maxage'
    def_maxage = 'plone.app.caching.strongCaching.maxage'
    def_smaxage = 'plone.app.caching.strongCaching.smaxage'
    for name in (maxage, def_maxage, def_smaxage):
        if name not in registry:
            return
    if registry.records[maxage].field.recordName != def_smaxage:
        # no fix needed
        return
    field_ref = FieldRef(def_maxage, registry.records[def_maxage].field)
    old_value = registry[maxage]
    registry.records[maxage] = Record(field_ref, old_value)
    logger.info('Fixed {} to refer to {}.'.format(maxage, def_maxage))
Esempio n. 3
0
    def applyChanges(self, data):
        """Save changes in the given data dictionary to the registry.
        """

        for key, value in data.items():

            # Lazily create per-ruleset records if necessary
            if key not in self.registry.records:

                # This should only ever happen if we have a not-yet-creted
                # ruleset-specific record
                assert self.rulesetName in key

                # Strip the ruleset name out, leaving the original key - this
                # must exist, otherwise getContent() would not have put it in
                # the data dictionary
                globalKey = self.operation.prefix + \
                    key[len(self.operation.prefix) +
                        len(self.rulesetName) + 1:]
                assert globalKey in self.registry.records

                # Create a new record with a FieldRef
                field = self.registry.records[globalKey].field
                self.registry.records[key] = Record(FieldRef(globalKey, field),
                                                    value)

            else:
                self.registry[key] = value
Esempio n. 4
0
    def test_fieldref_interfaces(self):
        from plone.registry import field, FieldRef
        from plone.registry.interfaces import IFieldRef
        from zope.schema.interfaces import ICollection

        listField = field.List(value_type=field.ASCIILine())
        ref = FieldRef('some.record', listField)

        self.assertTrue(ICollection.providedBy(ref))
        self.assertTrue(IFieldRef.providedBy(ref))
Esempio n. 5
0
 def _getField(self, name):
     field = self._fields.get(name, _MARKER)
     if field is _MARKER:
         return self.parents._getField(name)
     if isinstance(field, basestring):
         recordName = field
         while isinstance(field, basestring):
             recordName = field
             field = self._fields[recordName]
         field = FieldRef(recordName, field)
     return field
Esempio n. 6
0
    def test_lookupOption_override(self):
        provideUtility(Registry(), IRegistry)
        registry = getUtility(IRegistry)

        registry.records['plone.caching.tests.test'] = r = Record(
            field.TextLine(), u'default')
        registry.records['plone.caching.tests.testrule.test'] = Record(
            FieldRef(r.__name__, r.field), u'override')

        result = lookupOption('plone.caching.tests',
                              'testrule',
                              'test',
                              default=_marker)
        self.assertEqual(u'override', result)
Esempio n. 7
0
    def test_fix_double_smaxage(self):
        from plone.registry.interfaces import IRegistry
        from plone.registry.record import Record
        from plone.registry import FieldRef
        from plone.app.upgrade.v50.final import fix_double_smaxage
        # Run the upgrade before plone.app.caching is installed,
        # to check that it does not harm.
        portal_setup = self.layer['portal'].portal_setup
        fix_double_smaxage(portal_setup)
        registry = getUtility(IRegistry)
        maxage = 'plone.app.caching.strongCaching.plone.resource.maxage'
        def_maxage = 'plone.app.caching.strongCaching.maxage'
        def_smaxage = 'plone.app.caching.strongCaching.smaxage'
        # Install default caching profile.
        portal_setup.runAllImportStepsFromProfile(
            'plone.app.caching:default', )
        self.assertTrue(def_maxage in registry)
        self.assertTrue(def_smaxage in registry)
        # Run upgrade.
        fix_double_smaxage(portal_setup)
        # Install the with-caching-proxy settings.
        portal_setup.runAllImportStepsFromProfile(
            'plone.app.caching:with-caching-proxy', )
        # Run upgrade.
        fix_double_smaxage(portal_setup)

        # Old situation had maxage referencing the s-maxage definition:
        field_ref = FieldRef(def_smaxage, registry.records[def_smaxage].field)
        registry.records[maxage] = Record(field_ref, 999)
        self.assertEqual(registry.records[maxage].field.recordName,
                         def_smaxage)
        self.assertEqual(registry[maxage], 999)
        self.assertIn('shared', registry.records[maxage].field.title.lower())
        # Run upgrade.
        fix_double_smaxage(portal_setup)
        # Test that this fixes the reference and keeps the value.
        self.assertEqual(registry.records[maxage].field.recordName, def_maxage)
        self.assertEqual(registry[maxage], 999)
        self.assertNotIn('shared',
                         registry.records[maxage].field.title.lower())
        # Run upgrade.
        fix_double_smaxage(portal_setup)
        self.assertEqual(registry.records[maxage].field.recordName, def_maxage)
        self.assertEqual(registry[maxage], 999)
Esempio n. 8
0
    def importRecord(self, node):
        name = node.get('name', '')
        if node.get('delete') is not None:
            self.logger.warning(u"The 'delete' attribute of <record /> nodes "
                                u"is deprecated, it should be replaced with "
                                u"'remove'.")
        remove = node.get('remove', node.get('delete', 'false'))

        interfaceName = node.get('interface', None)
        fieldName = node.get('field', None)

        if not name and (interfaceName and fieldName):
            prefix = node.get('prefix', None)
            if prefix is None:
                prefix = interfaceName

            name = "%s.%s" % (prefix, fieldName)

        if not name:
            raise NameError("No name given for <record /> node!")

        # Unicode is not supported
        name = str(name)

        # Handle deletion and quit
        if remove.lower() == 'true':
            if name in self.context.records:
                del self.context.records[name]
                self.logger.info("Removed record %s." % name)
            else:
                self.logger.warning(
                    "Record %s was marked for deletion, but was not found." %
                    name)
            return

        # See if we have an existing record
        existing_record = self.context.records.get(name, None)

        interface = None
        field = None
        value = _marker
        value_purge = True

        # If we are given an interface and field name, try to resolve them
        if interfaceName and fieldName:
            try:
                interface = resolve(interfaceName)
                field = IPersistentField(interface[fieldName])
            except ImportError:
                self.logger.warning("Failed to import interface %s for \
                    record %s" % (interfaceName, name))
                interface = None
                field = None
            except KeyError:
                self.logger.warning("Interface %s specified for record %s has \
                    no field %s." % (interfaceName, name, fieldName))
                interface = None
                field = None
            except TypeError:
                self.logger.warning("Field %s in interface %s specified for \
                    record %s cannot be used as a persistent field." %
                                    (fieldName, interfaceName, name))
                interface = None
                field = None

        # Find field and value nodes

        field_node = None
        value_node = None

        for child in node:
            if not isinstance(child.tag, str):
                continue
            elif child.tag.lower() == 'field':
                field_node = child
            elif child.tag.lower() == 'value':
                value_node = child

        # Let field not potentially override interface[fieldName]
        if field_node is not None:
            field_ref = field_node.attrib.get('ref', None)
            if field_ref is not None:
                # We have a field reference
                if field_ref not in self.context:
                    raise KeyError(
                        u"Record %s references field for record %s, \
                        which does not exist" % (name, field_ref))
                ref_record = self.context.records[field_ref]
                field = FieldRef(field_ref, ref_record.field)
            else:
                # We have a standard field
                field_type = field_node.attrib.get('type', None)
                field_type_handler = queryUtility(IFieldExportImportHandler,
                                                  name=field_type)
                if field_type_handler is None:
                    raise TypeError(
                        "Field of type %s used for record %s is not supported."
                        % (field_type, name))
                else:
                    field = field_type_handler.read(field_node)
                    if not IPersistentField.providedBy(field):
                        raise TypeError(
                            "Only persistent fields may be imported. \
                            %s used for record %s is invalid." %
                            (field_type, name))

        if field is not None and not IFieldRef.providedBy(field):

            # Set interface name and fieldName, if applicable
            field.interfaceName = interfaceName
            field.fieldName = fieldName

        # Fall back to existing record if neither a field node nor the
        # interface yielded a field

        change_field = True

        if field is None and existing_record is not None:
            change_field = False
            field = existing_record.field

        if field is None:
            raise ValueError("Cannot find a field for the record %s. Add a \
                <field /> element or reference an interface and field name." %
                             name)

        # Extract the value

        if value_node is not None:
            value_purge = value_node.attrib.get('purge', '').lower() != 'false'
            value = elementToValue(field, value_node, default=_marker)

        # Now either construct or update the record

        if value is _marker:
            value = field.default
            value_purge = True

        if existing_record is not None:
            if change_field:
                existing_record.field = field
            existing_value = existing_record.value
            if change_field or value != existing_value:

                if not value_purge and type(value) == type(existing_value):
                    if isinstance(value, list):
                        value = existing_value + [
                            v for v in value if v not in existing_value
                        ]
                    elif isinstance(value, tuple):
                        value = existing_value + tuple(
                            [v for v in value if v not in existing_value])
                    elif isinstance(value, (
                            set,
                            frozenset,
                    )):
                        value = existing_value.union(value)
                    elif isinstance(value, dict):
                        for key, value in value.items():
                            # check if value is list, if so, let's add
                            # instead of overridding
                            if type(value) == list:
                                if key in existing_value and \
                                        not shouldPurgeList(value_node, key):
                                    existing = existing_value[key]
                                    for item in existing:
                                        # here, we'll remove existing items
                                        # point is that we don't want duplicates
                                        # and don't want to reorder
                                        if item in value:
                                            value.remove(item)
                                    existing.extend(value)
                                    value = existing
                            existing_value[key] = value

                        value = existing_value

                existing_record.value = value
        else:
            self.context.records[name] = Record(field, value)