Пример #1
0
    async def __call__(self):
        """ data input : { 'interface': 'INTERFACE' }"""
        registry = await get_registry()
        if registry is None:
            return ErrorResponse("BadRequest",
                                 _("Not in a container request"),
                                 status=412)

        data = await self.request.json()
        interface = data.get("interface", None)
        initial_values = data.get("initial_values", {})
        if interface is None:
            return ErrorResponse("InvalidRequest",
                                 "Non existent Interface",
                                 status=412)

        iObject = import_class(interface)
        registry.register_interface(iObject)
        config = registry.for_interface(iObject)

        # Initialize values
        # If its defined on the guillotina.schema default will not be overwritten
        #  you will need to PATCH
        for key, field in get_fields(iObject).items():
            if key in initial_values and getattr(config, key,
                                                 _marker) == _marker:
                # We don't have a value
                config[key] = initial_values[key]

        await notify(
            RegistryEditedEvent(self.context, registry,
                                {interface: initial_values}))

        return Response(status=201)
Пример #2
0
    async def __call__(self):
        """ data input : { 'interface': 'INTERFACE' }"""
        if not hasattr(self.request, 'container_settings'):
            return ErrorResponse('BadRequest', _("Not in a container request"))

        data = await self.request.json()
        interface = data.get('interface', None)
        initial_values = data.get('initial_values', {})
        if interface is None:
            return ErrorResponse('InvalidRequest', 'Non existent Interface')

        registry = self.request.container_settings
        iObject = import_class(interface)
        registry.register_interface(iObject)
        config = registry.for_interface(iObject)

        # Initialize values
        # If its defined on the guillotina.schema default will not be overwritten
        #  you will need to PATCH
        for key, field in get_fields(iObject).items():
            if key in initial_values and getattr(config, key,
                                                 _marker) == _marker:
                # We don't have a value
                config[key] = initial_values[key]

        return Response(response={}, status=201)
Пример #3
0
    async def get_schema(self, schema, context, result, behavior):
        read_permissions = merged_tagged_value_dict(schema, read_permission.key)
        schema_serial = {}
        for name, field in get_fields(schema).items():

            if not self.check_permission(read_permissions.get(name)):
                continue

            if behavior:
                # omit/include for behaviors need full name
                dotted_name = schema.__identifier__ + '.' + name
            else:
                dotted_name = name

            if ('*' not in self.include and (dotted_name in self.omit or (
                    len(self.include) > 0 and (
                        dotted_name not in self.include and
                        schema.__identifier__ not in self.include)))):
                # make sure the fields aren't filtered
                continue

            value = await self.serialize_field(context, field)
            if not behavior:
                result[name] = value
            else:
                schema_serial[name] = value

        if behavior and len(schema_serial) > 0:
            result[schema.__identifier__] = schema_serial
Пример #4
0
    async def get_schema(self, schema, context, result, behavior):
        read_permissions = merged_tagged_value_dict(schema,
                                                    read_permission.key)
        schema_serial = {}
        for name, field in get_fields(schema).items():

            if not self.check_permission(read_permissions.get(name)):
                continue

            if behavior:
                # omit/include for behaviors need full name
                dotted_name = schema.__identifier__ + '.' + name
            else:
                dotted_name = name

            if ('*' not in self.include
                    and (dotted_name in self.omit or
                         (len(self.include) > 0 and
                          (dotted_name not in self.include
                           and schema.__identifier__ not in self.include)))):
                # make sure the fields aren't filtered
                continue

            value = await self.serialize_field(context, field)
            if not behavior:
                result[name] = value
            else:
                schema_serial[name] = value

        if behavior and len(schema_serial) > 0:
            result[schema.__identifier__] = schema_serial
Пример #5
0
    async def __call__(self):
        """ data input : { 'interface': 'INTERFACE' }"""
        if not hasattr(self.request, 'container_settings'):
            return ErrorResponse(
                'BadRequest',
                _("Not in a container request"),
                status=412)

        data = await self.request.json()
        interface = data.get('interface', None)
        initial_values = data.get('initial_values', {})
        if interface is None:
            return ErrorResponse(
                'InvalidRequest',
                'Non existent Interface',
                status=412)

        registry = self.request.container_settings
        iObject = import_class(interface)
        registry.register_interface(iObject)
        config = registry.for_interface(iObject)

        # Initialize values
        # If its defined on the guillotina.schema default will not be overwritten
        #  you will need to PATCH
        for key, field in get_fields(iObject).items():
            if key in initial_values and getattr(config, key, _marker) == _marker:
                # We don't have a value
                config[key] = initial_values[key]

        return Response(status=201)
Пример #6
0
    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
Пример #7
0
    async def set_schema(
        self,
        schema: Type[Interface],
        obj: IResource,
        data: Dict[str, Any],
        errors: List[Dict[str, Any]],
        validate_all: bool = False,
        behavior: bool = False,
    ):
        write_permissions = merged_tagged_value_dict(schema,
                                                     write_permission.key)
        changed = False
        for name, field in get_fields(schema).items():

            if name in RESERVED_ATTRS:
                continue

            if field.readonly:
                continue

            if behavior:
                found = False
                if data.get(schema.__identifier__):
                    sdata = data[schema.__identifier__]
                    data_value = sdata[name] if name in sdata else None
                    found = True if name in sdata else False
            else:
                data_value = data[name] if name in data else None
                found = True if name in data else False
            if found:

                if not self.check_permission(write_permissions.get(name)):
                    raise Unauthorized("Write permission not allowed")

                try:
                    field = field.bind(obj)
                    value = await self.get_value(field, obj, data_value)
                except ValueError as e:
                    errors.append({
                        "message": "Value error",
                        "field": name,
                        "error": e
                    })
                except ValidationError as e:
                    errors.append(e.json())
                except ValueDeserializationError as e:
                    errors.append({
                        "message": e.message,
                        "field": name,
                        "error": e
                    })
                except Invalid as e:
                    errors.append({
                        "message": e.args[0],
                        "field": name,
                        "error": e
                    })
                else:
                    # record object changes for potential future conflict resolution
                    try:
                        await apply_coroutine(field.set, obj, value)
                        changed = True
                    except ValidationError as e:
                        errors.append(e.json())
                    except ValueDeserializationError as e:
                        errors.append({
                            "message": e.message,
                            "field": name,
                            "error": e
                        })
                    except AttributeError:
                        logger.warning(
                            f"AttributeError setting data on field {name}",
                            exc_info=True)
                    except Exception:
                        logger.warning(
                            f"Unhandled error setting data on field, {schema} {name}",
                            exc_info=True)
                        errors.append({
                            "message":
                            "Unhandled exception",
                            "field":
                            name,
                            "error":
                            ValueDeserializationError(field, value,
                                                      "Unhandled error"),
                        })
            else:
                if validate_all and field.required and getattr(
                        obj, name, None) is None:
                    errors.append({
                        "message": "Required parameter",
                        "field": name,
                        "error": ValueError("Required parameter"),
                    })

        for error in await validate_invariants(schema, obj):
            if isinstance(error, ValidationError):
                errors.append({
                    "message": error.doc(),
                    "value": error.value,
                    "field": error.field_name,
                    "error": error.errors,
                })
            else:
                if len(getattr(error, "args", [])) > 0 and isinstance(
                        error.args[0], str):
                    message = error.args[0]
                else:
                    message = error.__doc__
                errors.append({"message": message, "error": error})

        if changed:
            obj.register()
Пример #8
0
    async def set_schema(self,
                         schema,
                         obj,
                         data,
                         errors,
                         validate_all=False,
                         behavior=False):
        write_permissions = merged_tagged_value_dict(schema,
                                                     write_permission.key)

        for name, field in get_fields(schema).items():
            if name in RESERVED_ATTRS:
                continue

            if field.readonly:
                continue

            if behavior:
                found = False
                if schema.__identifier__ in data:
                    sdata = data[schema.__identifier__]
                    data_value = sdata[name] if name in sdata else None
                    found = True if name in sdata else False
            else:
                data_value = data[name] if name in data else None
                found = True if name in data else False
            if found:

                if not self.check_permission(write_permissions.get(name)):
                    raise Unauthorized('Write permission not allowed')

                try:
                    field = field.bind(obj)
                    value = await self.get_value(field, obj, data_value)
                except ValueError as e:
                    errors.append({
                        'message': 'Value error',
                        'field': name,
                        'error': e
                    })
                except ValidationError as e:
                    errors.append({
                        'message': e.doc(),
                        'field': name,
                        'error': e
                    })
                except ValueDeserializationError as e:
                    errors.append({
                        'message': e.message,
                        'field': name,
                        'error': e
                    })
                except Invalid as e:
                    errors.append({
                        'message': e.args[0],
                        'field': name,
                        'error': e
                    })
                else:
                    # record object changes for potential future conflict resolution
                    try:
                        await notify(BeforeFieldModifiedEvent(field, value))
                        await apply_coroutine(field.set, obj, value)
                    except ValidationError as e:
                        errors.append({
                            'message': e.doc(),
                            'field': name,
                            'error': e
                        })
                    except ValueDeserializationError as e:
                        errors.append({
                            'message': e.message,
                            'field': name,
                            'error': e
                        })
                    except AttributeError:
                        logger.warning(
                            f'AttributeError setting data on field {name}',
                            exc_info=True)
                    except Exception:
                        if not isinstance(getattr(type(obj), name, None),
                                          property):
                            # we can not set data on properties
                            logger.warning(
                                'Error setting data on field, falling back to setattr',
                                exc_info=True)
                            setattr(obj, name, value)
                        else:
                            logger.warning('Error setting data on field',
                                           exc_info=True)
            else:
                if validate_all and field.required and getattr(
                        obj, name, None) is None:
                    errors.append({
                        'message': 'Required parameter',
                        'field': name,
                        'error': ValueError('Required parameter')
                    })

        if validate_all:
            invariant_errors = []
            try:
                schema.validateInvariants(object, invariant_errors)
            except Invalid:
                # Just collect errors
                pass
            validation = [(None, e) for e in invariant_errors]

            if len(validation):
                for error in validation:
                    errors.append({
                        'message': error[1].doc(),
                        'field': error[0],
                        'error': error
                    })
Пример #9
0
 def _callFUT(self, schema):
     from guillotina.schema import get_fields
     return get_fields(schema)
Пример #10
0
 def _callFUT(self, schema):
     from guillotina.schema import get_fields
     return get_fields(schema)
    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
Пример #12
0
    def _init(
        self, resource_class, resource_interface, resource_type, fhir_release, **kw
    ):
        """ """
        if "default" in kw:

            if (
                isinstance(kw["default"], (str, dict)) or kw["default"] is None
            ) is False:
                msg = (
                    "Only dict or string or None is accepted as "
                    "default value but got {0}".format(type(kw["default"]))
                )

                raise Invalid(msg)

        field_attributes = get_fields(IFhirField)

        attribute = field_attributes["resource_class"].bind(self)
        if resource_class is None:
            attribute.validate(resource_class)
            attribute_val = None
        else:
            attribute_val = attribute.from_unicode(resource_class)
        attribute.set(self, attribute_val)

        attribute = field_attributes["resource_interface"].bind(self)
        if resource_interface is None:
            attribute.validate(resource_interface)
            attribute_val = None
        else:
            attribute_val = attribute.from_unicode(resource_interface)
        attribute.set(self, attribute_val)

        attribute = field_attributes["resource_type"].bind(self)
        if resource_type is None:
            attribute.validate(resource_type)
            attribute_val = None
        else:
            attribute_val = attribute.from_unicode(resource_type)
        attribute.set(self, attribute_val)

        attribute = field_attributes["fhir_release"].bind(self)
        if fhir_release is None:
            attribute.validate(fhir_release)
            attribute_val = None
        else:
            attribute_val = attribute.from_unicode(fhir_release)
            # just for ensure correct value
            FHIR_VERSION[attribute_val]
        attribute.set(self, attribute_val)

        if self.resource_type and self.resource_class is not None:
            raise Invalid(
                "Either `resource_class` or `resource_type` value is acceptable! "
                "you cannot provide both!"
            )

        if self.resource_class:
            try:
                klass = import_string(self.resource_class)
                self.ensure_fhir_abstract(klass)

            except ImportError:
                msg = (
                    "Invalid FHIR Resource class `{0}`! "
                    "Please check the module or class name."
                ).format(self.resource_class)

                return reraise(Invalid, msg)

            if not IFhirResource.implementedBy(klass):

                raise Invalid(
                    "{0!r} must be valid resource class from fhir.resources".format(
                        klass
                    )
                )
            self._resource_class = klass

        if self.resource_type:

            try:
                self._resource_class = implementer(IFhirResource)(
                    lookup_fhir_class(self.resource_type)
                )
            except ImportError:
                msg = "{0} is not valid fhir resource type!".format(self.resource_type)
                return reraise(Invalid, msg)

        if self.resource_interface:
            try:
                klass = implementer(IFhirResource)(
                    import_string(self.resource_interface)
                )
            except ImportError:
                msg = (
                    "Invalid FHIR Resource Interface`{0}`! "
                    "Please check the module or class name."
                ).format(self.resource_interface)
                return reraise(Invalid, msg)

            if not IInterface.providedBy(klass):
                raise WrongType("An interface is required", klass, self.__name__)

            if klass is not IFhirResource and not issubclass(klass, IFhirResource):
                msg = "`{0!r}` must be derived from {1}".format(
                    klass,
                    IFhirResource.__module__ + "." + IFhirResource.__class__.__name__,
                )

                raise Invalid(msg)

            self._resource_interface_class = klass
Пример #13
0
    def _init(self, resource_class, resource_interface, resource_type, **kw):
        """ """

        if "default" in kw:

            if (isinstance(kw["default"],
                           (str, dict)) or kw["default"] is None) is False:
                msg = ("Only dict or string or None is accepted as "
                       "default value but got {0}".format(type(kw["default"])))

                raise Invalid(msg)

        field_attributes = get_fields(IFhirField)

        attribute = field_attributes['resource_class'].bind(self)
        if resource_class is None:
            attribute.validate(resource_class)
            attribute_val = None
        else:
            attribute_val = attribute.from_unicode(resource_class)
        attribute.set(self, attribute_val)

        attribute = field_attributes['resource_interface'].bind(self)
        if resource_interface is None:
            attribute.validate(resource_interface)
            attribute_val = None
        else:
            attribute_val = attribute.from_unicode(resource_interface)
        attribute.set(self, attribute_val)

        attribute = field_attributes['resource_type'].bind(self)
        if resource_type is None:
            attribute.validate(resource_type)
            attribute_val = None
        else:
            attribute_val = attribute.from_unicode(resource_type)
        attribute.set(self, attribute_val)

        if self.resource_type and self.resource_class is not None:
            raise Invalid(
                "Either `resource_class` or `resource_type` value is acceptable! you cannot provide both!"
            )

        if self.resource_class:
            try:
                klass = import_string(self.resource_class)
            except ImportError:
                msg = "Invalid FHIR Resource class `{0}`! Please check the module or class name.".format(
                    self.resource_class)

                t, v, tb = sys.exc_info()
                try:
                    reraise(Invalid(msg), None, tb)
                finally:
                    del t, v, tb

            if not IFhirResource.implementedBy(klass):

                raise Invalid(
                    "{0!r} must be valid resource class from fhir.resources".
                    format(klass))
            self._resource_class = klass

        if self.resource_type:

            try:
                self._resource_class = resource_type_to_resource_cls(
                    self.resource_type)
            except ImportError:
                msg = "{0} is not valid fhir resource type!".format(
                    self.resource_type)
                t, v, tb = sys.exc_info()
                try:
                    reraise(Invalid(msg), None, tb)
                finally:
                    del t, v, tb
                raise Invalid(msg)

        if self.resource_interface:
            try:
                klass = import_string(self.resource_interface)
            except ImportError:
                msg = "Invalid FHIR Resource Interface`{0}`! Please check the module or class name.".format(
                    self.resource_interface)
                t, v, tb = sys.exc_info()
                try:
                    reraise(Invalid(msg), None, tb)
                finally:
                    del t, v, tb

            if not IInterface.providedBy(klass):
                raise WrongType("An interface is required", klass,
                                self.__name__)

            if klass is not IFhirResource and not issubclass(
                    klass, IFhirResource):
                msg = "`{0!r}` must be derived from {1}".format(
                    klass,
                    IFhirResource.__module__ + "." +
                    IFhirResource.__class__.__name__,
                )

                raise Invalid(msg)

            self._resource_interface_class = klass
Пример #14
0
    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
    async def __call__(self):
        result = {'type': self.field_type}
        # caching the field_attributes here improves performance dramatically
        if self.field.__class__ in FIELDS_CACHE:
            field_attributes = FIELDS_CACHE[self.field.__class__].copy()
        else:
            field_attributes = {}
            for schema in implementedBy(self.field.__class__).flattened():
                field_attributes.update(get_fields(schema))
            FIELDS_CACHE[self.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(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 = get_multi_adapter(
                    (value, self.field, self.request),
                    ISchemaFieldSerializeToJson)
                text = await serializer()
            elif value is not None and (force
                                        or value != self.field.missing_value):
                text = json_compatible(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 = get_multi_adapter(
                    (self.field.schema, self.request), ISchemaSerializeToJson)
                result['properties'] = await schema_serializer()
        return result
Пример #16
0
    async def set_schema(
            self, schema, obj, data, errors,
            validate_all=False, behavior=False):
        write_permissions = merged_tagged_value_dict(schema, write_permission.key)

        for name, field in get_fields(schema).items():

            if field.readonly:
                continue

            if behavior:
                found = False
                if schema.__identifier__ in data:
                    sdata = data[schema.__identifier__]
                    data_value = sdata[name] if name in sdata else None
                    found = True if name in sdata else False
            else:
                data_value = data[name] if name in data else None
                found = True if name in data else False

            f = schema.get(name)
            if found:

                if not self.check_permission(write_permissions.get(name)):
                    continue

                try:
                    value = await self.get_value(f, obj, data_value)
                except ValueError as e:
                    errors.append({
                        'message': e.message, 'field': name, 'error': e})
                except ValidationError as e:
                    errors.append({
                        'message': e.doc(), 'field': name, 'error': e})
                except ValueDeserializationError as e:
                    errors.append({
                        'message': e.message, 'field': name, 'error': e})
                except Invalid as e:
                    errors.append({
                        'message': e.args[0], 'field': name, 'error': e})
                else:
                    # record object changes for potential future conflict resolution
                    try:
                        await apply_coroutine(field.set, obj, value)
                    except Exception:
                        logger.warning(
                            'Error setting data on field, falling back to setattr',
                            exc_info=True)
                        setattr(obj, name, value)
            else:
                if f.required and not hasattr(obj, name):
                    errors.append({
                        'message': 'Required parameter', 'field': name,
                        'error': ValueError('Required parameter')})

        if validate_all:
            invariant_errors = []
            try:
                schema.validateInvariants(object, invariant_errors)
            except Invalid:
                # Just collect errors
                pass
            validation = [(None, e) for e in invariant_errors]

            if len(validation):
                for e in validation:
                    errors.append({
                        'message': e[1].doc(),
                        'field': e[0],
                        'error': e
                    })
Пример #17
0
    async def set_schema(
            self, schema, obj, data, errors,
            validate_all=False, behavior=False):
        write_permissions = merged_tagged_value_dict(schema, write_permission.key)

        for name, field in get_fields(schema).items():
            if name in RESERVED_ATTRS:
                continue

            if field.readonly:
                continue

            if behavior:
                found = False
                if schema.__identifier__ in data:
                    sdata = data[schema.__identifier__]
                    data_value = sdata[name] if name in sdata else None
                    found = True if name in sdata else False
            else:
                data_value = data[name] if name in data else None
                found = True if name in data else False
            if found:

                if not self.check_permission(write_permissions.get(name)):
                    raise Unauthorized('Write permission not allowed')

                try:
                    field = field.bind(obj)
                    value = await self.get_value(field, obj, data_value)
                except ValueError as e:
                    errors.append({
                        'message': 'Value error', 'field': name, 'error': e})
                except ValidationError as e:
                    errors.append({
                        'message': e.doc(), 'field': name, 'error': e})
                except ValueDeserializationError as e:
                    errors.append({
                        'message': e.message, 'field': name, 'error': e})
                except Invalid as e:
                    errors.append({
                        'message': e.args[0], 'field': name, 'error': e})
                else:
                    # record object changes for potential future conflict resolution
                    try:
                        await apply_coroutine(field.set, obj, value)
                    except ValidationError as e:
                        errors.append({
                            'message': e.doc(), 'field': name, 'error': e})
                    except ValueDeserializationError as e:
                        errors.append({
                            'message': e.message, 'field': name, 'error': e})
                    except AttributeError:
                        logger.warning(
                            f'AttributeError setting data on field {name}', exc_info=True)
                    except Exception:
                        if not isinstance(getattr(type(obj), name, None), property):
                            # we can not set data on properties
                            logger.warning(
                                'Error setting data on field, falling back to setattr',
                                exc_info=True)
                            setattr(obj, name, value)
                        else:
                            logger.warning(
                                'Error setting data on field', exc_info=True)
            else:
                if validate_all and field.required and getattr(obj, name, None) is None:
                    errors.append({
                        'message': 'Required parameter', 'field': name,
                        'error': ValueError('Required parameter')})

        if validate_all:
            invariant_errors = []
            try:
                schema.validateInvariants(object, invariant_errors)
            except Invalid:
                # Just collect errors
                pass
            validation = [(None, e) for e in invariant_errors]

            if len(validation):
                for error in validation:
                    errors.append({
                        'message': error[1].doc(),
                        'field': error[0],
                        'error': error
                    })