def i18n_persistent_field_adapter(context):
    """Special handling for I18NField fields."""

    if IPersistentField.providedBy(context):
        return context

    ignored = list(DisallowedProperty.uses + StubbornProperty.uses)
    constrained = list(InterfaceConstrainedProperty.uses)
    instance = I18NFieldPersistent.__new__(I18NFieldPersistent)

    context_dict = dict([
        (k, v) for k, v in context.__dict__.items() if k not in ignored
    ])

    for k, iface in constrained:
        v = context_dict.get(k, None)
        if v is not None and v != context.missing_value:
            v = iface(v, None)
            if v is None:
                __traceback_info__ = TRACE.format(k, iface.__identifier__)
                return None
            context_dict[k] = v

    instance.__dict__.update(context_dict)
    return instance
Example #2
0
 def _setField(self, name, field):
     if not IPersistentField.providedBy(field):
         raise ValueError("The record's field must be an IPersistentField.")
     if IFieldRef.providedBy(field):
         if field.recordName not in self._fields:
             raise ValueError("Field reference points to non-existent record")
         self._fields[name] = field.recordName # a pointer, of sorts
     else:
         field.__name__ = 'value'
         self._fields[name] = field
Example #3
0
 def _setField(self, name, field):
     if not IPersistentField.providedBy(field):
         raise ValueError("The record's field must be an IPersistentField.")
     if IFieldRef.providedBy(field):
         if field.recordName not in self._fields:
             raise ValueError("Field reference points to non-existent record")
         self._fields[name] = field.recordName # a pointer, of sorts
     else:
         field.__name__ = 'value'
         self._fields[name] = field
Example #4
0
    def __init__(self, field, value=_marker, _validate=True):

        if _validate and not IPersistentField.providedBy(field):
            raise ValueError("Field is not persistent")

        if value is _marker:
            value = field.default
        else:
            if _validate:
                if value != field.missing_value:
                    bound_field = field.bind(self)
                    bound_field.validate(value)

        # Bypass event notification and setting on the parent
        self._field = field
        self._value = value

        if field.interfaceName:
            alsoProvides(self, IInterfaceAwareRecord)
Example #5
0
    def __init__(self, field, value=_marker, _validate=True):

        if _validate and not IPersistentField.providedBy(field):
            raise ValueError("Field is not persistent")

        if value is _marker:
            value = field.default
        else:
            if _validate:
                if value != field.missing_value:
                    bound_field = field.bind(self)
                    bound_field.validate(value)

        # Bypass event notification and setting on the parent
        self._field = field
        self._value = value

        if field.interfaceName:
            alsoProvides(self, IInterfaceAwareRecord)
Example #6
0
def persistentFieldAdapter(context):
    """Turn a non-persistent field into a persistent one
    """

    if IPersistentField.providedBy(context):
        return context

    # See if we have an equivalently-named field

    class_name = context.__class__.__name__
    persistent_class = getattr(plone.registry.field, class_name, None)
    if persistent_class is None:
        return None

    if not issubclass(persistent_class, context.__class__):
        __traceback_info__ = "Can only clone a field of an equivalent type."
        return None

    ignored = list(DisallowedProperty.uses + StubbornProperty.uses)
    constrained = list(InterfaceConstrainedProperty.uses)

    instance = persistent_class.__new__(persistent_class)

    context_dict = dict([(k, v) for k, v in context.__dict__.items()
                         if k not in ignored])

    for key, iface in constrained:
        value = context_dict.get(key, None)
        if value is None or value == context.missing_value:
            continue
        value = iface(value, None)
        if value is None:
            __traceback_info__ = ("The property `{0}` cannot be adapted to "
                                  "`{1}`.".format(
                                      key,
                                      iface.__identifier__,
                                  ))
            return None
        context_dict[key] = value

    instance.__dict__.update(context_dict)
    return instance
Example #7
0
def persistentFieldAdapter(context):
    """Turn a non-persistent field into a persistent one
    """

    if IPersistentField.providedBy(context):
        return context

    # See if we have an equivalently-named field

    class_name = context.__class__.__name__
    persistent_class = getattr(plone.registry.field, class_name, None)
    if persistent_class is None:
        return None

    if not issubclass(persistent_class, context.__class__):
        __traceback_info__ = "Can only clone a field of an equivalent type."
        return None

    ignored = list(DisallowedProperty.uses + StubbornProperty.uses)
    constrained = list(InterfaceConstrainedProperty.uses)

    instance = persistent_class.__new__(persistent_class)

    context_dict = dict(
        [(k, v) for k, v in context.__dict__.items() if k not in ignored]
    )

    for key, iface in constrained:
        value = context_dict.get(key, None)
        if value is None or value == context.missing_value:
            continue
        value = iface(value, None)
        if value is None:
            __traceback_info__ = (
                "The property `{0}` cannot be adapted to "
                "`{1}`.".format(key, iface.__identifier__,)
            )
            return None
        context_dict[key] = value

    instance.__dict__.update(context_dict)
    return instance
Example #8
0
def i18n_persistent_field_adapter(context):
    """Special handling for I18NField fields."""

    if IPersistentField.providedBy(context):
        return context

    ignored = list(DisallowedProperty.uses + StubbornProperty.uses)
    constrained = list(InterfaceConstrainedProperty.uses)
    instance = I18NFieldPersistent.__new__(I18NFieldPersistent)

    context_dict = dict([(k, v) for k, v in context.__dict__.items()
                         if k not in ignored])

    for k, iface in constrained:
        v = context_dict.get(k, None)
        if v is not None and v != context.missing_value:
            v = iface(v, None)
            if v is None:
                __traceback_info__ = TRACE.format(k, iface.__identifier__)
                return None
            context_dict[k] = v

    instance.__dict__.update(context_dict)
    return instance
Example #9
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 is deprecated, "
                u"it should be replaced with '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)
        __traceback_info__ = 'record name: {0}'.format(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 {0} was marked for deletion, but was not "
                    "found.".format(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 {0} for '
                    'record {1}'.format(interfaceName, name)
                )
                interface = None
                field = None
            except KeyError:
                self.logger.warning(
                    'Interface {0} specified for record %s has '
                    'no field {1}.'.format(interfaceName, name, fieldName)
                )
                interface = None
                field = None
            except TypeError:
                self.logger.warning(
                    "Field {0} in interface {1} specified for record {2} "
                    "cannot be used as a persistent field.".format(
                        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 {0} references field for record {1}, '
                        u'which does not exist'.format(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 {0} used for record {1} is not "
                        "supported.".format(field_type, name)
                    )
                else:
                    field = field_type_handler.read(field_node)
                    if not IPersistentField.providedBy(field):
                        raise TypeError(
                            "Only persistent fields may be imported. {0} used "
                            "for record {1} is invalid.".format(
                                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 {0}. Add a <field /> "
                "element or reference an interface and field name.".format(
                    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 and
                                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)
Example #10
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)
Example #11
0
    def importRecord(self, node):
        
        name = node.get('name', '')
        delete = 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 delete.lower() == 'true':
            if name in self.context.records:
                del self.context.records[name]
                self.logger.info("Deleted 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 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):
                        existing_value.update(value)
                        value = existing_value
                
                existing_record.value = value
        else:
            self.context.records[name] = Record(field, value)