Пример #1
0
def create_schema_name(schema=None, name_schema=None):
    if name_schema:
        if schema_not_in_registry(name_schema):
            raise ValueError(
                NO_SCHEMA_FOUND_ERROR.format(schema_name=name_schema))
        cls_schema = class_registry.get_class(name_schema)
        schema = cls_schema()
    elif schema:
        schema = schema if isinstance(schema, Schema) else schema()
        cls_schema = type(schema)
    else:
        raise ValueError(NO_ARGS_ERROR)

    if not isinstance(schema, Schema):
        raise TypeError(INVALID_SCHEMA_TYPE)

    modifiers = []
    for modifier in MODIFIERS:
        attribute = getattr(schema, modifier)
        if attribute:
            modifiers.append(f"{modifier}={attribute}")
    modifiers_str = ",".join(modifiers)
    if modifiers_str:
        modifiers_str = f"({modifiers_str})"
    name_cls_schema = resolver(cls_schema)
    return f"{name_cls_schema}{modifiers_str}"
Пример #2
0
    def schema(self):
        """The nested Schema object.

        .. versionchanged:: 1.0.0
            Renamed from `serializer` to `schema`
        """
        # Ensure that only parameter is a tuple
        if isinstance(self.only, basestring):
            only = (self.only, )
        else:
            only = self.only
        if not self.__schema:
            if isinstance(self.nested, SchemaABC):
                self.__schema = self.nested
            elif isinstance(self.nested, type) and \
                    issubclass(self.nested, SchemaABC):
                self.__schema = self.nested(many=self.many,
                        only=only, exclude=self.exclude)
            elif isinstance(self.nested, basestring):
                if self.nested == _RECURSIVE_NESTED:
                    parent_class = self.parent.__class__
                    self.__schema = parent_class(many=self.many, only=only,
                            exclude=self.exclude)
                else:
                    schema_class = class_registry.get_class(self.nested)
                    self.__schema = schema_class(many=self.many,
                            only=only, exclude=self.exclude)
            else:
                raise ValueError('Nested fields must be passed a '
                                 'Schema, not {0}.'.format(self.nested.__class__))
        self.__schema.ordered = getattr(self.parent, 'ordered', False)
        # Inherit context from parent
        self.__schema.context.update(getattr(self.parent, 'context', {}))
        return self.__schema
Пример #3
0
    def schema(self):
        """The nested Schema object.

        .. versionchanged:: 1.0.0
            Renamed from `serializer` to `schema`
        """
        # Ensure that only parameter is a tuple
        if isinstance(self.only, basestring):
            only = (self.only, )
        else:
            only = self.only
        if not self.__schema:
            if isinstance(self.nested, SchemaABC):
                self.__schema = self.nested
            elif isinstance(self.nested, type) and \
                    issubclass(self.nested, SchemaABC):
                self.__schema = self.nested(many=self.many,
                        only=only, exclude=self.exclude)
            elif isinstance(self.nested, basestring):
                if self.nested == _RECURSIVE_NESTED:
                    parent_class = self.parent.__class__
                    self.__schema = parent_class(many=self.many, only=only,
                            exclude=self.exclude)
                else:
                    schema_class = class_registry.get_class(self.nested)
                    self.__schema = schema_class(many=self.many,
                            only=only, exclude=self.exclude)
            else:
                raise ValueError('Nested fields must be passed a '
                                 'Schema, not {0}.'.format(self.nested.__class__))
        self.__schema.ordered = getattr(self.parent, 'ordered', False)
        # Inherit context from parent
        self.__schema.context.update(getattr(self.parent, 'context', {}))
        return self.__schema
Пример #4
0
    def schema(self):
        only = getattr(self, 'only', None)
        exclude = getattr(self, 'exclude', ())
        context = getattr(self, 'context', {})

        if isinstance(self.__schema, SchemaABC):
            return self.__schema
        if isinstance(self.__schema, type) and issubclass(
                self.__schema, SchemaABC):
            self.__schema = self.__schema(only=only,
                                          exclude=exclude,
                                          context=context)
            return self.__schema
        if isinstance(self.__schema, basestring):
            if self.__schema == _RECURSIVE_NESTED:
                parent_class = self.parent.__class__
                self.__schema = parent_class(
                    only=only,
                    exclude=exclude,
                    context=context,
                    include_data=self.parent.include_data)
            else:
                schema_class = class_registry.get_class(self.__schema)
                self.__schema = schema_class(only=only,
                                             exclude=exclude,
                                             context=context)
            return self.__schema
        else:
            raise ValueError(('A Schema is required to serialize a nested '
                              'relationship with include_data'))
Пример #5
0
    def _from_nested_schema(self, obj, field):
        if isinstance(field.nested, basestring):
            nested = get_class(field.nested)
        else:
            nested = field.nested

        if isclass(nested) and issubclass(nested, Schema):
            only = field.only
            exclude = field.exclude
            nested_instance = nested(only=only, exclude=exclude)
        else:
            nested_instance = nested

        wrapped_nested = self.__class__(nested=True)
        wrapped_dumped = wrapped_nested.dump(nested_instance)

        # NOTE: doubled up to maintain backwards compatibility
        metadata = field.metadata.get("metadata", {})
        metadata.update(field.metadata)

        for md_key, md_val in metadata.items():
            if md_key == "metadata":
                continue
            wrapped_dumped[md_key] = md_val

        if field.many:
            wrapped_dumped = {
                "type": "array" if field.required else ["array", "null"],
                "items": wrapped_dumped,
            }

        return wrapped_dumped
Пример #6
0
 def schema(self):
     if not self.__schema:
         context = getattr(self.parent, 'context', self.metadata.get('context', {}))
         if isinstance(self.nested, SchemaABC):
             self.__schema = self.nested
             self.__schema.context = getattr(self.__schema, 'context', {})
             self.__schema.context.update(context)
         else:
             if isinstance(self.nested, type) and issubclass(self.nested, SchemaABC):
                 schema_class = self.nested
             elif not isinstance(self.nested, basestring):
                 raise ValueError(
                     'Nested fields must be passed a '
                     'Schema, not {0}.'.format(self.nested.__class__),
                 )
             elif self.nested == 'self':
                 schema_class = self.parent.__class__
             else:
                 schema_class = class_registry.get_class(self.nested)
             self.__schema = schema_class(
                 many=self.many,
                 only=self.only, exclude=self.exclude, context=context,
                 load_only=self._nested_normalized_option('load_only'),
                 dump_only=self._nested_normalized_option('dump_only'),
             )
         self.__schema.ordered = getattr(self.parent, 'ordered', False)
     return self.__schema
Пример #7
0
 def schema_description(self):
     """Document the schema."""
     fields = {}
     links = self.fields['links'].schema if 'links' in self.fields else None
     for k, v in self.fields.items():
         type = v.container if isinstance(v, ma.List) else v
         d = {
             'type': type.__class__.__name__.lower(),
             'required': v.required,
             'read-only': v.dump_only,
             'list': isinstance(v, ma.List) or (isinstance(v, Nested) and v.many)
         }
         if k in self.translated_fields:
             d['type'] = 'translation'
         if k in self.nested_fields:
             if isinstance(self.fields[k].nested, str):
                 nested_schema = class_registry.get_class(self.fields[k].nested)
             else:
                 nested_schema = self.fields[k].nested
             nested_schema = nested_schema(
                 only=self.fields[k].only,
                 exclude=self.fields[k].exclude
             )
             d.update(nested_schema.schema_description)
         if k in self.related_fields + self.related_lists:
             if links and 'related' in links and k in links['related']:
                 link = self.fields['links'].schema['related'][k]
                 d['doc'] = url_for('api.resourcedoc', _external=True, **link.params)
             else:
                 d['doc'] = False
         fields[k] = d
     list_url = False
     if links and 'list' in links:
         list_url = url_for(links['list'].endpoint, **links['list'].params)
     return {'fields': fields, 'link': list_url}
Пример #8
0
def response_for_exception(
    exception: Union[Exception, Type[Exception]],
    status_code: str,
) -> dict:
    """ Generates an exception schema. """
    detail_message = getattr(exception, 'detail', 'Internal server error')
    status_code = str(getattr(exception, 'status_code', status_code or 500))
    exc_name = exception.__class__.__name__ if isinstance(
        exception, Exception) else exception.__name__

    schema_cls_name = f'{exc_name}-{status_code}'
    detail_schema_cls_name = f'{schema_cls_name}-detail'
    try:
        schema_cls = class_registry.get_class(schema_cls_name)
    except RegistryError:
        detail_schema_cls = type(
            detail_schema_cls_name, (BaseExceptionSchema, ), {
                'detail':
                ma_fields.String(validate=validate.OneOf([detail_message]))
            })

        schema_cls = type(
            schema_cls_name, (BaseExceptionSchema, ),
            {'errors': ma_fields.List(ma_fields.Nested(detail_schema_cls))})

    return {
        'content': {
            CONTENT_TYPE_HEADER: {
                'schema': schema_cls,
            }
        },
        'description': 'Example error response'
    }
    def schema(self):
        context = getattr(self.parent, 'context', {})

        if isinstance(self._only, basestring):
            only = (self._only, )
        else:
            only = self._only

        if not self.__schema:
            if isinstance(self._nested, SchemaABC):
                self.__schema = self._nested
                self.__schema.context.update(context)
            elif isinstance(self._nested, type) and \
                    issubclass(self._nested, SchemaABC):
                self.__schema = self._nested(many=self._many, only=only,
                                             exclude=self._exclude,
                                             context=context)

            elif isinstance(self._nested, basestring):
                if self._nested == fields._RECURSIVE_NESTED:
                    parent_class = self.parent.__class__
                    self.__schema = parent_class(
                        many=self._many, only=only, exclude=self._exclude,
                        context=context)
                else:
                    schema_class = class_registry.get_class(self._nested)
                    self.__schema = schema_class(
                        many=self._many, only=only, exclude=self._exclude,
                        context=context)
            else:
                raise ValueError('Nested fields must be passed a '
                                 'Schema, not {0}.'.format(
                                    self._nested.__class__))

        return self.__schema
Пример #10
0
    def schema(self):
        only = getattr(self, "only", None)
        exclude = getattr(self, "exclude", ())
        context = getattr(self, "context", {})

        if isinstance(self.__schema, SchemaABC):
            return self.__schema
        if isinstance(self.__schema, type) and issubclass(self.__schema, SchemaABC):
            self.__schema = self.__schema(only=only, exclude=exclude, context=context)
            return self.__schema
        if isinstance(self.__schema, (str, bytes)):
            if self.__schema == _RECURSIVE_NESTED:
                parent_class = self.parent.__class__
                self.__schema = parent_class(
                    only=only,
                    exclude=exclude,
                    context=context,
                    include_data=self.parent.include_data,
                )
            else:
                schema_class = class_registry.get_class(self.__schema)
                self.__schema = schema_class(
                    only=only, exclude=exclude, context=context
                )
            return self.__schema
        else:
            raise ValueError(
                "A Schema is required to serialize a nested "
                "relationship with include_data"
            )
Пример #11
0
def resolve_schema_cls(schema):
    """
    """
    if isinstance(schema, type) and issubclass(schema, BaseSchema):
        return schema
    if isinstance(schema, BaseSchema):
        return type(schema)
    return class_registry.get_class(schema)
Пример #12
0
    def schema(self):
        """The nested Schema object.

        This method was copied from marshmallow and modified to support multiple different nested schemes.
        """
        if not self._schema:
            # Inherit context from parent.
            context = getattr(self.parent, "context", {})
            self._schema = {"from": {}, "to": {}}
            for nest in self.nested:
                if isinstance(nest, SchemaABC):
                    rdf_type = str(normalize_type(nest.opts.rdf_type))
                    model = nest.opts.model
                    if not rdf_type or not model:
                        raise ValueError("Both rdf_type and model need to be set on the schema for nested to work")
                    _schema = copy.copy(nest)
                    _schema.context.update(context)
                    # Respect only and exclude passed from parent and re-initialize fields
                    set_class = _schema.set_class
                    if self.only is not None:
                        if self._schema.only is not None:
                            original = _schema.only
                        else:  # only=None -> all fields
                            original = _schema.fields.keys()
                        _schema.only = set_class(self.only).intersection(original)
                    if self.exclude:
                        original = _schema.exclude
                        _schema.exclude = set_class(self.exclude).union(original)
                    _schema._init_fields()
                    self._schema["from"][rdf_type] = _schema
                    self._schema["to"][model] = _schema
                else:
                    if isinstance(nest, type) and issubclass(nest, SchemaABC):
                        schema_class = nest
                    elif not isinstance(nest, (str, bytes)):
                        raise ValueError("Nested fields must be passed a " "Schema, not {}.".format(nest.__class__))
                    elif nest == "self":
                        ret = self
                        while not isinstance(ret, SchemaABC):
                            ret = ret.parent
                        schema_class = ret.__class__
                    else:
                        schema_class = class_registry.get_class(nest)

                    rdf_type = str(normalize_type(schema_class.opts.rdf_type))
                    model = schema_class.opts.model
                    if not rdf_type or not model:
                        raise ValueError("Both rdf_type and model need to be set on the schema for nested to work")
                    self._schema["from"][rdf_type] = schema_class(
                        many=False,
                        only=self.only,
                        exclude=self.exclude,
                        context=context,
                        load_only=self._nested_normalized_option("load_only"),
                        dump_only=self._nested_normalized_option("dump_only"),
                    )
                    self._schema["to"][model] = self._schema["from"][rdf_type]
        return self._schema
Пример #13
0
def validated(request):
    schema = request.schema
    if schema is not None:
        json_body = request.json_body
        if isinstance(schema,(str,type)):
            if isinstance(schema, str):
                schema = class_registry.get_class(schema)
            change_dict_keys(json_body, to_snake_case)
        return schema().load(json_body)
Пример #14
0
 def schema(self):
     """The nested Schema object
     """
     if isinstance(self.nested, str):
         schema_class = class_registry.get_class(self.nested, True)
         if schema_class:
             if isinstance(schema_class, list):
                 schema_class = schema_class[-1]
             return schema_class(many=self.many)
     return super().schema
Пример #15
0
 def schemas(self):
     if not self._schemas:
         self._schemas = []
         for candidate, schema in self.candidates:
             # Inherit context from parent.
             context = getattr(self.parent, "context", {})
             if isinstance(schema, SchemaABC):
                 schema.many = False
                 schema.context.update(context)
                 # Respect only and exclude passed from parent and
                 # re-initialize fields
                 set_class = schema.set_class
                 if self.only is not None:
                     if schema.only is not None:
                         original = schema.only
                     else:  # only=None -> all fields
                         original = schema.fields.keys()
                     schema.only = set_class(
                         self.only).intersection(original)
                 if self.exclude:
                     original = schema.exclude
                     schema.exclude = set_class(
                         self.exclude).union(original)
                 # ensure sub-schemas won't convert into `lists`
                 schema.many = False
                 schema._init_fields()
                 self._schemas.append((candidate, schema))
             else:
                 if isinstance(schema, type) and issubclass(
                         schema, SchemaABC):
                     schema_class = schema
                 elif not isinstance(schema, (str, bytes)):
                     raise ValueError("Polymorphic fields must be passed a "
                                      "Schema, not {}.".format(
                                          schema.__class__))
                 elif schema == "self":
                     ret = self
                     while not isinstance(ret, SchemaABC):
                         ret = ret.parent
                     schema_class = ret.__class__
                 else:
                     schema_class = class_registry.get_class(schema)
                 self._schemas.append(
                     (candidate,
                      schema_class(
                          many=False,
                          only=self.only,
                          exclude=self.exclude,
                          context=context,
                          load_only=self._nested_normalized_option(
                              "load_only"),
                          dump_only=self._nested_normalized_option(
                              "dump_only"),
                      )))
     return self._schemas
Пример #16
0
    def schema(self):
        """The nested Schema object.

        .. versionchanged:: 1.0.0
            Renamed from `serializer` to `schema`
        """
        if not self.__schema:
            # Ensure that only parameter is a tuple
            if isinstance(self.only, basestring):
                only = (self.only,)
            else:
                only = self.only

            # Inherit context from parent.
            context = getattr(self.parent, "context", {})
            if isinstance(self.nested, SchemaABC):
                self.__schema = self.nested
                self.__schema.context.update(context)
            elif isinstance(self.nested, type) and issubclass(self.nested, SchemaABC):
                self.__schema = self.nested(
                    many=self.many,
                    only=only,
                    exclude=self.exclude,
                    context=context,
                    load_only=self._nested_normalized_option("load_only"),
                    dump_only=self._nested_normalized_option("dump_only"),
                )
            elif isinstance(self.nested, basestring):
                if self.nested == _RECURSIVE_NESTED:
                    parent_class = self.parent.__class__
                    self.__schema = parent_class(
                        many=self.many,
                        only=only,
                        exclude=self.exclude,
                        context=context,
                        load_only=self._nested_normalized_option("load_only"),
                        dump_only=self._nested_normalized_option("dump_only"),
                    )
                else:
                    schema_class = class_registry.get_class(self.nested)
                    self.__schema = schema_class(
                        many=self.many,
                        only=only,
                        exclude=self.exclude,
                        context=context,
                        load_only=self._nested_normalized_option("load_only"),
                        dump_only=self._nested_normalized_option("dump_only"),
                    )
            else:
                raise ValueError(
                    "Nested fields must be passed a "
                    "Schema, not {0}.".format(self.nested.__class__)
                )
            self.__schema.ordered = getattr(self.parent, "ordered", False)
        return self.__schema
Пример #17
0
    def _from_nested_schema(self, obj, field):
        """Support nested field."""
        if isinstance(field.nested, basestring):
            nested = get_class(field.nested)
        else:
            nested = field.nested

        if isclass(nested) and issubclass(nested, Schema):
            name = nested.__name__
            only = field.only
            exclude = field.exclude
            nested_cls = nested
            nested_instance = nested(only=only, exclude=exclude)
        else:
            nested_cls = nested.__class__
            name = nested_cls.__name__
            nested_instance = nested

        outer_name = obj.__class__.__name__
        # If this is not a schema we've seen, and it's not this schema (checking this for recursive schemas),
        # put it in our list of schema defs
        if name not in self._nested_schema_classes and name != outer_name:
            wrapped_nested = self.__class__(nested=True)
            wrapped_dumped = dot_data_backwards_compatible(
                wrapped_nested.dump(nested_instance))

            wrapped_dumped[
                "additionalProperties"] = _resolve_additional_properties(
                    nested_cls)

            self._nested_schema_classes[name] = wrapped_dumped

            self._nested_schema_classes.update(
                wrapped_nested._nested_schema_classes)

        # and the schema is just a reference to the def
        schema = {"type": "object", "$ref": "#/definitions/{}".format(name)}

        # NOTE: doubled up to maintain backwards compatibility
        metadata = field.metadata.get("metadata", {})
        metadata.update(field.metadata)

        for md_key, md_val in metadata.items():
            if md_key in ("metadata", "name"):
                continue
            schema[md_key] = md_val

        if field.many:
            schema = {
                "type": "array" if field.required else ["array", "null"],
                "items": schema,
            }

        return schema
Пример #18
0
    def _from_nested_schema(self, obj, field):
        """Support nested field."""
        if isinstance(field.nested, basestring):
            nested = get_class(field.nested)
        else:
            nested = field.nested

        name = nested.__name__
        outer_name = obj.__class__.__name__
        only = field.only
        exclude = field.exclude

        # If this is not a schema we've seen, and it's not this schema,
        # put it in our list of schema defs
        if name not in self._nested_schema_classes and name != outer_name:
            wrapped_nested = self.__class__(nested=True)
            wrapped_dumped = wrapped_nested.dump(
                nested(only=only, exclude=exclude)
            )

            # Handle change in return value type between Marshmallow
            # versions 2 and 3.
            if marshmallow.__version__.split('.', 1)[0] >= '3':
                self._nested_schema_classes[name] = wrapped_dumped
            else:
                self._nested_schema_classes[name] = wrapped_dumped.data
            self._nested_schema_classes.update(
                wrapped_nested._nested_schema_classes
            )

        # and the schema is just a reference to the def
        schema = {
            'type': 'object',
            '$ref': '#/definitions/{}'.format(name)
        }

        # NOTE: doubled up to maintain backwards compatibility
        metadata = field.metadata.get('metadata', {})
        metadata.update(field.metadata)

        for md_key, md_val in metadata.items():
            if md_key == 'metadata':
                continue
            schema[md_key] = md_val

        if field.many:
            schema = {
                'type': ["array"] if field.required else ['array', 'null'],
                'items': schema,
            }

        return schema
Пример #19
0
    def handle_nested_fields(self, data):
        """Expand (if needed) primary keys of nested related resources into a
        nested representation before loading a resource.

        Only single nested fields are handled. Attempting to update a
        collection of nested fields will raise a ValidationError.

        Example (assuming `category` is a nested field):

        >>> handle_nested_fields({ 'id': 1, 'name': 'Chair', 'category': 1 })
        {
            'id': 1,
            'name': 'Chair',
            'category': {
                'id': 1 ,
                'name': 'Furniture'
            }
        }
        """
        model = self.Meta.model
        if not hasattr(model, "nested_fields"):
            return data

        for field_name, config in model.nested_fields.items():
            if field_name not in data:
                continue

            if isinstance(data[field_name], dict):
                # Nested field is already expanded.
                continue

            related_field = self._declared_fields[field_name]
            related_schema = class_registry.get_class(related_field.nested)
            related_model = related_schema.Meta.model

            if config["many"]:
                model_name = model.__name__
                related_model_name = related_model.__name__
                error_msg = (
                    f"Cannot update relationship through the `{model_name}` model. "
                    f"An alternative is to direclty manipulate `{related_model_name}` objects."
                )
                raise ValidationError(error_msg, field_names=[field_name])

            pk = data[field_name]
            related = related_model.query.get(pk)
            related_data, _ = related_schema().dump(related)
            for k in related_field.exclude:
                related_data.pop(k)
            data[field_name] = related_data

        return data
 def get_schema(self, name):
     context = getattr(self.parent, "context", {})
     schema_class = class_registry.get_class(name)
     schema = schema_class(
         many=self.many,
         only=self.only,
         exclude=self.exclude,
         context=context,
         load_only=self._nested_normalized_option("load_only"),
         dump_only=self._nested_normalized_option("dump_only"),
     )
     schema.ordered = getattr(self.parent, "ordered", False)
     return schema
Пример #21
0
    def _from_nested_schema(self, obj, field):
        """patch in context for nested field"""
        if isinstance(field.nested, (str, bytes)):
            nested = get_class(field.nested)
        else:
            nested = field.nested

        if isclass(nested) and issubclass(nested, Schema):
            only = field.only
            exclude = field.exclude
            context = getattr(field.parent, "context", {})
            field.nested = nested(only=only, exclude=exclude, context=context)
        return super()._from_nested_schema(obj, field)
Пример #22
0
    def schema(self):
        """The nested Schema object.

        .. versionchanged:: 1.0.0
            Renamed from `serializer` to `schema`.
        """
        if not self._schema:
            if callable(self.nested) and not isinstance(self.nested, type):
                nested = self.nested()
            else:
                nested = self.nested

            if isinstance(nested, SchemaABC):
                self._schema = copy.copy(nested)
                self._schema.context = getattr(self._schema, 'context') or {}
                self._schema.context.update(self.extra_context)
                # Respect only and exclude passed from parent and re-initialize fields
                set_class = self._schema.set_class
                if self.only is not None:
                    if self._schema.only is not None:
                        original = self._schema.only
                    else:  # only=None -> all fields
                        original = self._schema.fields.keys()
                    self._schema.only = set_class(
                        self.only) & set_class(original)
                if self.exclude:
                    original = self._schema.exclude
                    self._schema.exclude = set_class(
                        self.exclude) | set_class(original)
                self._schema._init_fields()
            else:
                if isinstance(nested, type) and issubclass(nested, SchemaABC):
                    schema_class = nested
                elif not isinstance(nested, (str, bytes)):
                    raise ValueError("`Nested` fields must be passed a "
                                     "`Schema`, not {}.".format(
                                         nested.__class__))
                elif nested == "self":
                    schema_class = self.root.__class__
                else:
                    schema_class = class_registry.get_class(nested)
                self._schema = schema_class(
                    many=self.many,
                    only=self.only,
                    exclude=self.exclude,
                    context=self.extra_context,
                    load_only=self._nested_normalized_option("load_only"),
                    dump_only=self._nested_normalized_option("dump_only"),
                )
        return self._schema
Пример #23
0
def create_entrypoint(func, schema_class=''):
    """ Create a new entry class.
    """
    funcmeta = inspect_function(func)
    if isinstance(schema_class, str):
        schema_class = ma_class_registry.get_class(
            schema_class)  # <-- fetch schema class here

    return _RegistryEntry(
        func=func,
        args=funcmeta['args'],
        name=funcmeta['name'],
        schema_class=schema_class(),
    )
Пример #24
0
 def schema(self):
     if not self.__schema and self._schema_arg:
         if isinstance(self._schema_arg, SchemaABC):
             self.__schema = self._schema_arg
         elif isinstance(self._schema_arg, type) and issubclass(self._schema_arg, SchemaABC):
             self.__schema = self._schema_arg
         elif isinstance(self._schema_arg, str):
             if self._schema_arg == 'self':
                 self.__schema = self.parent.__class__
             else:
                 self.__schema = class_registry.get_class(self._schema_arg)
         else:
             raise ValueError('Nested fields must be passed a Schema, not {0}.'.format(self.nested.__class__))
     return self.__schema
 def schema(self):
     if isinstance(self.related_schema, SchemaABC):
         self.__schema = self.related_schema
     elif (isinstance(self.related_schema, type) and
             issubclass(self.related_schema, SchemaABC)):
         self.__schema = self.related_schema
     elif isinstance(self.related_schema, basestring):
         if self.related_schema == 'self':
             parent_class = self.parent.__class__
             self.__schema = parent_class
         else:
             schema_class = class_registry.get_class(self.related_schema)
             self.__schema = schema_class
     return self.__schema
Пример #26
0
 def schema(self):
     if isinstance(self.__schema, SchemaABC):
         return self.__schema
     if isinstance(self.__schema, type) and issubclass(self.__schema, SchemaABC):
         self.__schema = self.__schema()
         return self.__schema
     if isinstance(self.__schema, basestring):
         if self.__schema == _RECURSIVE_NESTED:
             parent_class = self.parent.__class__
             self.__schema = parent_class(many=self.many)
         else:
             schema_class = class_registry.get_class(self.__schema)
             self.__schema = schema_class()
         return self.__schema
Пример #27
0
    def _from_nested_schema(self, obj, field):
        """Support nested field."""
        if isinstance(field.nested, basestring):
            nested = get_class(field.nested)
        elif isinstance(field.schema, ModelSchema):
            nested = Nested(field.schema.schema.__class__).nested
            nested.__name__ = field.nested.__name__
        else:
            nested = field.nested

        name = nested.__name__
        outer_name = obj.__class__.__name__
        only = field.only
        exclude = field.exclude

        # If this is not a schema we've seen, and it's not this schema,
        # put it in our list of schema defs
        if name not in self._nested_schema_classes and name != outer_name:
            wrapped_nested = AnyBlokJSONSchema(nested=True)
            wrapped_dumped = wrapped_nested.dump(
                nested(only=only, exclude=exclude, context=obj.context)
            )
            self._nested_schema_classes[name] = wrapped_dumped
            self._nested_schema_classes.update(
                wrapped_nested._nested_schema_classes
            )

        # and the schema is just a reference to the def
        schema = {
            'type': 'object',
            '$ref': '#/definitions/{}'.format(name)
        }

        # NOTE: doubled up to maintain backwards compatibility
        metadata = field.metadata.get('metadata', {})
        metadata.update(field.metadata)

        for md_key, md_val in metadata.items():
            if md_key == 'metadata':
                continue
            schema[md_key] = md_val

        if field.many:
            schema = {
                'type': ["array"] if field.required else ['array', 'null'],
                'items': schema,
            }

        return schema
Пример #28
0
    def _get_schema(cls, current_schema: SchemaABC, obj: str):
        """
        Получаем схему на которую ссылается Nested
        :param current_schema: схема изначальная
        :param obj: поле в current_schema
        :return:
        """
        related_schema_cls = get_related_schema(current_schema, obj)

        if isinstance(related_schema_cls, SchemaABC):
            related_schema_cls = related_schema_cls.__class__
        elif isinstance(related_schema_cls, str):
            related_schema_cls = class_registry.get_class(related_schema_cls)

        return related_schema_cls
Пример #29
0
    def _from_nested_schema(self, obj, field):
        """Support nested field."""
        if isinstance(field.nested, basestring):
            nested = get_class(field.nested)
        else:
            nested = field.nested

        name = nested.__name__
        outer_name = obj.__class__.__name__

        # If this is not a schema we've seen, and it's not this schema,
        # put it in our list of schema defs
        if name not in self._nested_schema_classes and name != outer_name:
            wrapped_nested = JSONSchema(nested=True)
            wrapped_dumped = wrapped_nested.dump(
                nested()
            )
            self._nested_schema_classes[name] = wrapped_dumped.data
            self._nested_schema_classes.update(
                wrapped_nested._nested_schema_classes
            )

        # and the schema is just a reference to the def
        schema = {
            'type': 'object',
            '$ref': '#/definitions/{}'.format(name)
        }

        # NOTE: doubled up to maintain backwards compatibility
        metadata = field.metadata.get('metadata', {})
        metadata.update(field.metadata)

        if metadata.get('description'):
            schema['description'] = (
                metadata.get('description')
            )

        if metadata.get('title'):
            schema['title'] = metadata.get('title')

        if field.many:
            schema = {
                'type': ["array"] if field.required else ['array', 'null'],
                'items': schema,
            }

        return schema
Пример #30
0
 def schema_class(self):
     """The Schema object.
     """
     if not self.__schema_class:
         # 延后载入的数据类型
         if isinstance(self.unload_schema, basestring):
             if self.unload_schema == _RECURSIVE_NESTED:
                 parent_class = get_schema_for_field(self).__class__
                 self.__schema_class = parent_class
             else:
                 schema_class = class_registry.get_class(self.unload_schema)
                 self.__schema_class = schema_class
         else:
             raise ValueError('Related fields must be passed a '
                              'Schema, not {0}.'.format(
                                  self.unload_schema.__class__))
     return self.__schema_class
Пример #31
0
 def schema(self):
     if isinstance(self.__schema, SchemaABC):
         return self.__schema
     if isinstance(self.__schema, type) and issubclass(self.__schema, SchemaABC):
         self.__schema = self.__schema()
         return self.__schema
     if isinstance(self.__schema, basestring):
         if self.__schema == _RECURSIVE_NESTED:
             parent_class = self.parent.__class__
             self.__schema = parent_class(include_data=self.parent.include_data)
         else:
             schema_class = class_registry.get_class(self.__schema)
             self.__schema = schema_class()
         return self.__schema
     else:
         raise ValueError(('A Schema is required to serialize a nested '
                           'relationship with include_data'))
Пример #32
0
    def eagerload_includes(self, query, qs):
        """Use eagerload feature of sqlalchemy to optimize data retrieval for include querystring parameter

        :param Query query: sqlalchemy queryset
        :param QueryStringManager qs: a querystring manager to retrieve information from url
        :return Query: the query with includes eagerloaded
        """
        for include in qs.include:
            joinload_object = None

            if '.' in include:
                current_schema = self.resource.schema
                for obj in include.split('.'):
                    try:
                        field = get_model_field(current_schema, obj)
                    except Exception as e:
                        raise InvalidInclude(str(e))

                    if joinload_object is None:
                        joinload_object = joinedload(field, innerjoin=True)
                    else:
                        joinload_object = joinload_object.joinedload(
                            field, innerjoin=True)

                    related_schema_cls = get_related_schema(
                        current_schema, obj)

                    if isinstance(related_schema_cls, SchemaABC):
                        related_schema_cls = related_schema_cls.__class__
                    else:
                        related_schema_cls = class_registry.get_class(
                            related_schema_cls)

                    current_schema = related_schema_cls
            else:
                try:
                    field = get_model_field(self.resource.schema, include)
                except Exception as e:
                    raise InvalidInclude(str(e))

                joinload_object = joinedload(field, innerjoin=True)

            query = query.options(joinload_object)

        return query
    def get_schema(self, name):
        context = getattr(self.parent, "context", {})
        schema_class = class_registry.get_class(name)

        # Class registry can return a list if multiple classes with the same
        # name are registered. We shouldn't do that so lets assert it.
        # and make mypy happy :-)
        assert not isinstance(schema_class, list)

        schema = schema_class(
            many=self.many,
            only=self.only,
            exclude=self.exclude,
            context=context,
            load_only=self._nested_normalized_option("load_only"),
            dump_only=self._nested_normalized_option("dump_only"),
        )
        schema.ordered = getattr(self.parent, "ordered", False)
        return schema
Пример #34
0
    def _from_nested_schema(self, _, field):
        """Support nested field.

        :param obj:
        :param field:

        """
        if isinstance(field.nested, (str, bytes)):
            nested = get_class(field.nested)
        else:
            nested = field.nested

        if isclass(nested) and issubclass(nested, Schema):
            only = field.only
            exclude = field.exclude
            nested_instance = nested(only=only, exclude=exclude)
        else:
            nested_instance = nested

        # If this is not a schema we've seen, and it's not this schema (checking this for recursive schemas),
        # put it in our list of schema defs
        wrapped_nested = self.__class__(nested=True)
        wrapped_dumped = wrapped_nested.dump(nested_instance)

        # and the schema is just a reference to the def
        schema = wrapped_dumped

        # NOTE: doubled up to maintain backwards compatibility
        metadata = field.metadata.get("metadata", {})
        metadata.update(field.metadata)

        for md_key, md_val in metadata.items():
            if md_key in ("metadata", "name"):
                continue
            schema[md_key] = md_val

        if field.many:
            schema = {
                "type": "array" if field.required else ["array", "null"],
                "items": schema,
            }

        return schema
Пример #35
0
    def __call__(self,value,system):
        request = system['request']
        request.response.content_type = 'application/json'
        response_schema = request.response_schema

        many = False
        instance = value
        if(isinstance(value, list)):
            many = True
            if len(value) > 0:
                instance = value[0]
            else:
                instance = None
        if response_schema is not None and isinstance(instance, (Schema, Base)):
            if isinstance(response_schema,str):
                response_schema = class_registry.get_class(request.response_schema)
            res = response_schema().dump(value, many=many)
            change_dict_keys(res,to_camel_case)
            return json.dumps(res)
        else:
            return json.dumps(value)
Пример #36
0
    def _from_nested_schema(cls, field):
        if isinstance(field.nested, basestring):
            nested = get_class(field.nested)
        else:
            nested = field.nested
        schema = cls().dump(nested()).data

        if field.metadata.get('metadata', {}).get('description'):
            schema['description'] = (
                field.metadata['metadata'].get('description')
            )

        if field.metadata.get('metadata', {}).get('title'):
            schema['title'] = field.metadata['metadata'].get('title')

        if field.many:
            schema = {
                'type': ["array"] if field.required else ['array', 'null'],
                'items': schema,
            }

        return schema
Пример #37
0
def _from_nested_schema(field):
    only = field.only
    exclude = field.exclude
    # `marshmallow.fields.Nested` keyword argument `only` expects
    # a string, iterable, or `None`, but `marshmallow.Schema` keyword
    # argument `only` accepts an iterable. Convert from string to
    # a tuple.
    if isinstance(only, basestring):
        only = (only,)
    # `field.nested` can be declared as a subclass of
    # `marshmallow.Schema` or an instance of `basestring`. If the latter,
    # then the subclass should be available via
    # `marshmallow.class_registry`
    try:
        nested_schema = field.nested(only=only, exclude=exclude)
    except TypeError:  # field.nested is a basestring
        nested_schema = get_class(field.nested)(only=only, exclude=exclude)
    schema = JSONSchema().dump(nested_schema).data
    if field.many:
        schema = {
            'type': ["array"] if field.required else ['array', 'null'],
            'items': schema
        }
    return schema
Пример #38
0
def test_multiple_classes_with_all():
    # Import a class with the same name
    from .foo_serializer import FooSerializer as FooSerializer1  # noqa

    classes = class_registry.get_class('FooSerializer', all=True)
    assert len(classes) == 2