Example #1
0
 def __init__(self, key_type=None, value_type=None, **kw):
     super(Dict, self).__init__(**kw)
     # whine if key_type or value_type is not a field
     if key_type is not None and not IField.providedBy(key_type):
         raise ValueError("'key_type' must be field instance.")
     if value_type is not None and not IField.providedBy(value_type):
         raise ValueError("'value_type' must be field instance.")
     self.key_type = key_type
     self.value_type = value_type
Example #2
0
 def __init__(self, key_type=None, value_type=None, **kw):
     super(Dict, self).__init__(**kw)
     # whine if key_type or value_type is not a field
     if key_type is not None and not IField.providedBy(key_type):
         raise ValueError("'key_type' must be field instance.")
     if value_type is not None and not IField.providedBy(value_type):
         raise ValueError("'value_type' must be field instance.")
     self.key_type = key_type
     self.value_type = value_type
Example #3
0
 async def get_value(self, field: IField, obj: IResource, value: Any) -> Any:
     try:
         if value is not None:
             value = get_adapter(field, IJSONToValue, args=[value, obj])
             if asyncio.iscoroutine(value):
                 value = await value
         field.validate(value)
         return value
     except ComponentLookupError:
         raise ValueDeserializationError(field, value, "Deserializer not found for field")
Example #4
0
 def __init__(self, value_type=None, unique=False, **kw):
     super(AbstractCollection, self).__init__(**kw)
     # whine if value_type is not a field
     if value_type is not None and not IField.providedBy(value_type):
         raise ValueError("'value_type' must be field instance.")
     self.value_type = value_type
     self.unique = unique
Example #5
0
 def __init__(self, value_type=None, unique=False, **kw):
     super(AbstractCollection, self).__init__(**kw)
     # whine if value_type is not a field
     if value_type is not None and not IField.providedBy(value_type):
         raise ValueError("'value_type' must be field instance.")
     self.value_type = value_type
     self.unique = unique
    async def __call__(self):
        result = {'type': self.field_type}
        for schema in implementedBy(self.field.__class__).flattened():
            self.field_attributes.update(getFields(schema))
        for attribute_name in sorted(self.field_attributes.keys()):
            attribute_field = self.field_attributes[attribute_name]
            if attribute_name in self.filtered_attributes:
                continue

            element_name = attribute_field.__name__
            attribute_field = attribute_field.bind(self.field)
            force = (element_name in self.forced_fields)

            value = attribute_field.get(self.field)

            # For 'default', 'missing_value' etc, we want to validate against
            # the imported field type itself, not the field type of the
            # attribute
            if element_name in self.field_type_attributes or \
                    element_name in self.non_validated_field_type_attributes:
                attribute_field = self.field

            text = None
            if isinstance(value, bytes):
                text = value.decode('utf-8')
            elif isinstance(value, str):
                text = value
            elif IField.providedBy(value):
                serializer = getMultiAdapter((value, self.field, self.request),
                                             ISchemaFieldSerializeToJson)
                text = await serializer()
            elif value is not None and (force
                                        or value != self.field.missing_value):
                text = IValueToJson(value)

            # handle i18n
            # if isinstance(value, Message):
            #     child.set(ns('domain', I18N_NAMESPACE), value.domain)
            #     if not value.default:
            #         child.set(ns('translate', I18N_NAMESPACE), '')
            #     else:
            #         child.set(ns('translate', I18N_NAMESPACE), child.text)
            #         child.text = converter.toUnicode(value.default)

            if text:
                if attribute_name == 'value_type':
                    attribute_name = 'items'
                result[attribute_name] = text

        if result['type'] == 'object':
            if IJSONField.providedBy(self.field):
                result['properties'] = self.field.json_schema
            else:
                schema_serializer = getMultiAdapter(
                    (self.field.schema, self.request), ISchemaSerializeToJson)
                result['properties'] = await schema_serializer()
        return result
Example #7
0
def get_fields(schema):
    """Return a dictionary containing all the Fields in a schema.
    """
    from guillotina.schema.interfaces import IField
    fields = {}
    for name in schema:
        attr = schema[name]
        if IField.providedBy(attr):
            fields[name] = attr
    return fields
Example #8
0
 def __init__(self, value_type=None, unique=False, naive=False, **kw):
     super(AbstractCollection, self).__init__(**kw)
     # whine if value_type is not a field
     if value_type is not None and not IField.providedBy(value_type):
         raise ValueError("'value_type' must be field instance.")
     if value_type:
         value_type.__name__ = self.__name__
     self.value_type = value_type
     self.unique = unique
     # naive designates if a field's sub type should be validated or not
     self.naive = naive
Example #9
0
def _validate_fields(schema, value, errors=None):
    if errors is None:
        errors = []
    # Interface can be used as schema property for Object fields that plan to
    # hold values of any type.
    # Because Interface does not include any Attribute, it is obviously not
    # worth looping on its methods and filter them all out.
    if schema is Interface:
        return errors
    # if `value` is part of a cyclic graph, we need to break the cycle to avoid
    # infinite recursion. Collect validated objects in a thread local dict by
    # it's python represenation. A previous version was setting a volatile
    # attribute which didn't work with security proxy
    if id(value) in VALIDATED_VALUES:
        return errors
    VALIDATED_VALUES[id(value)] = True
    # (If we have gotten here, we know that `value` provides an interface
    # other than zope.interface.Interface;
    # iow, we can rely on the fact that it is an instance
    # that supports attribute assignment.)
    try:
        for name in schema.names(all=True):
            if not IMethod.providedBy(schema[name]):
                try:
                    attribute = schema[name]
                    if IChoice.providedBy(attribute):
                        # Choice must be bound before validation otherwise
                        # IContextSourceBinder is not iterable in validation
                        bound = attribute.bind(value)
                        bound.validate(getattr(value, name, None))
                    elif IField.providedBy(attribute):
                        # validate attributes that are fields
                        attribute.validate(getattr(value, name, None))
                except ValidationError as error:
                    errors.append(error)
                except AttributeError as error:
                    # property for the given name is not implemented
                    errors.append(SchemaNotFullyImplemented(error))
    finally:
        del VALIDATED_VALUES[id(value)]
    return errors
Example #10
0
def _validate_fields(schema, value, errors=None):
    if errors is None:
        errors = []
    # Interface can be used as schema property for Object fields that plan to
    # hold values of any type.
    # Because Interface does not include any Attribute, it is obviously not
    # worth looping on its methods and filter them all out.
    if schema is Interface:
        return errors
    # if `value` is part of a cyclic graph, we need to break the cycle to avoid
    # infinite recursion. Collect validated objects in a thread local dict by
    # it's python represenation. A previous version was setting a volatile
    # attribute which didn't work with security proxy
    if id(value) in VALIDATED_VALUES:
        return errors
    VALIDATED_VALUES[id(value)] = True
    # (If we have gotten here, we know that `value` provides an interface
    # other than zope.interface.Interface;
    # iow, we can rely on the fact that it is an instance
    # that supports attribute assignment.)
    try:
        for name in schema.names(all=True):
            if not IMethod.providedBy(schema[name]):
                try:
                    attribute = schema[name]
                    if IChoice.providedBy(attribute):
                        # Choice must be bound before validation otherwise
                        # IContextSourceBinder is not iterable in validation
                        bound = attribute.bind(value)
                        bound.validate(getattr(value, name, None))
                    elif IField.providedBy(attribute):
                        # validate attributes that are fields
                        attribute.validate(getattr(value, name, None))
                except ValidationError as error:
                    errors.append(error)
                except AttributeError as error:
                    # property for the given name is not implemented
                    errors.append(SchemaNotFullyImplemented(error))
    finally:
        del VALIDATED_VALUES[id(value)]
    return errors
    def serialize(self):
        field = self.get_field()
        result = {"type": self.field_type}
        if self.widget is not None:
            result["widget"] = self.widget
        # caching the field_attributes here improves performance dramatically
        if field.__class__ in FIELDS_CACHE:
            field_attributes = FIELDS_CACHE[field.__class__].copy()
        else:
            field_attributes = {}
            for schema in implementedBy(field.__class__).flattened():
                field_attributes.update(get_fields(schema))
            FIELDS_CACHE[field.__class__] = field_attributes
        for attribute_name in sorted(field_attributes.keys()):
            attribute_field = field_attributes[attribute_name]
            if attribute_name in self.filtered_attributes:
                continue

            element_name = attribute_field.__name__
            attribute_field = attribute_field.bind(field)
            force = element_name in self.forced_fields

            value = attribute_field.get(field)

            # For 'default', 'missing_value' etc, we want to validate against
            # the imported field type itself, not the field type of the
            # attribute
            if (
                element_name in self.field_type_attributes
                or element_name in self.non_validated_field_type_attributes
            ):
                attribute_field = field

            text = None
            if isinstance(value, bytes):
                text = value.decode("utf-8")
            elif isinstance(value, str):
                text = value
            elif IField.providedBy(value):
                serializer = get_multi_adapter((value, field, self.request), ISchemaFieldSerializeToJson)
                text = serializer.serialize()
                if "properties" in text:
                    text = text["properties"]
            elif value is not None and (force or value != field.missing_value):
                text = json_compatible(value)

            if text:
                if attribute_name == "value_type":
                    attribute_name = "items"
                result[attribute_name] = text
        if result["type"] == "object":
            if IJSONField.providedBy(field):
                result.update(field.json_schema)
            if IDict.providedBy(field):
                if "properties" not in result:
                    result["properties"] = {}
                if field.value_type:
                    field_serializer = get_multi_adapter(
                        (field.value_type, self.schema, self.request), ISchemaFieldSerializeToJson
                    )
                    result["additionalProperties"] = field_serializer.serialize()
                else:
                    result["additionalProperties"] = True
            elif IObject.providedBy(field):
                schema_serializer = get_multi_adapter((field.schema, self.request), ISchemaSerializeToJson)
                result["properties"] = schema_serializer.serialize()
        if field.extra_values is not None:
            result.update(field.extra_values)
        return result
Example #12
0
def getFieldNames(schema):
    """Return a list of all the Field names in a schema.
    """
    from guillotina.schema.interfaces import IField
    return [name for name in schema if IField.providedBy(schema[name])]
    async def __call__(self):
        field = self.get_field()
        result = {'type': self.field_type}
        # caching the field_attributes here improves performance dramatically
        if field.__class__ in FIELDS_CACHE:
            field_attributes = FIELDS_CACHE[field.__class__].copy()
        else:
            field_attributes = {}
            for schema in implementedBy(field.__class__).flattened():
                field_attributes.update(get_fields(schema))
            FIELDS_CACHE[field.__class__] = field_attributes
        for attribute_name in sorted(field_attributes.keys()):
            attribute_field = field_attributes[attribute_name]
            if attribute_name in self.filtered_attributes:
                continue

            element_name = attribute_field.__name__
            attribute_field = attribute_field.bind(field)
            force = (element_name in self.forced_fields)

            value = attribute_field.get(field)

            # For 'default', 'missing_value' etc, we want to validate against
            # the imported field type itself, not the field type of the
            # attribute
            if element_name in self.field_type_attributes or \
                    element_name in self.non_validated_field_type_attributes:
                attribute_field = field

            text = None
            if isinstance(value, bytes):
                text = value.decode('utf-8')
            elif isinstance(value, str):
                text = value
            elif IField.providedBy(value):
                serializer = get_multi_adapter((value, field, self.request),
                                               ISchemaFieldSerializeToJson)
                text = await serializer()
                if 'properties' in text:
                    text = text['properties']
            elif value is not None and (force or value != field.missing_value):
                text = json_compatible(value)

            if text:
                if attribute_name == 'value_type':
                    attribute_name = 'items'
                result[attribute_name] = text
        if result['type'] == 'object':
            if IJSONField.providedBy(field):
                result['properties'] = field.json_schema
            if IDict.providedBy(field):
                if field.value_type:
                    field_serializer = get_multi_adapter(
                        (field.value_type, self.schema, self.request),
                        ISchemaFieldSerializeToJson)
                    result['additionalProperties'] = await field_serializer()
                else:
                    result['additionalProperties'] = True
            elif IObject.providedBy(field):
                schema_serializer = get_multi_adapter(
                    (field.schema, self.request), ISchemaSerializeToJson)
                result['properties'] = await schema_serializer()
        if field.extra_values is not None:
            result.update(field.extra_values)
        return result
    def serialize(self):
        field = self.get_field()
        result = {'type': self.field_type}
        # caching the field_attributes here improves performance dramatically
        if field.__class__ in FIELDS_CACHE:
            field_attributes = FIELDS_CACHE[field.__class__].copy()
        else:
            field_attributes = {}
            for schema in implementedBy(field.__class__).flattened():
                field_attributes.update(get_fields(schema))
            FIELDS_CACHE[field.__class__] = field_attributes
        for attribute_name in sorted(field_attributes.keys()):
            attribute_field = field_attributes[attribute_name]
            if attribute_name in self.filtered_attributes:
                continue

            element_name = attribute_field.__name__
            attribute_field = attribute_field.bind(field)
            force = (element_name in self.forced_fields)

            value = attribute_field.get(field)

            # For 'default', 'missing_value' etc, we want to validate against
            # the imported field type itself, not the field type of the
            # attribute
            if element_name in self.field_type_attributes or \
                    element_name in self.non_validated_field_type_attributes:
                attribute_field = field

            text = None
            if isinstance(value, bytes):
                text = value.decode('utf-8')
            elif isinstance(value, str):
                text = value
            elif IField.providedBy(value):
                serializer = get_multi_adapter(
                    (value, field, self.request),
                    ISchemaFieldSerializeToJson)
                text = serializer.serialize()
                if 'properties' in text:
                    text = text['properties']
            elif value is not None and (force or value != field.missing_value):
                text = json_compatible(value)

            if text:
                if attribute_name == 'value_type':
                    attribute_name = 'items'
                result[attribute_name] = text
        if result['type'] == 'object':
            if IJSONField.providedBy(field):
                result.update(field.json_schema)
            if IDict.providedBy(field):
                if field.value_type:
                    field_serializer = get_multi_adapter(
                        (field.value_type, self.schema, self.request),
                        ISchemaFieldSerializeToJson)
                    result['additionalProperties'] = field_serializer.serialize()
                else:
                    result['additionalProperties'] = True
            elif IObject.providedBy(field):
                schema_serializer = get_multi_adapter((field.schema, self.request),
                                                      ISchemaSerializeToJson)
                result['properties'] = schema_serializer.serialize()
        if field.extra_values is not None:
            result.update(field.extra_values)
        return result