Exemple #1
0
    def __new__(mcs, name, bases, attrs):
        model_attrs = {attr_name: attr
                       for attr_name, attr in attrs.items()
                       if is_model_attribute(attr_name, attr)}

        model_class = super(ModelMeta, mcs).__new__(mcs, name, bases, model_attrs)

        schema_base = getattr(model_class, '_schema_class', Schema)

        schema_attrs = {attr_name: attr
                        for attr_name, attr in attrs.items()
                        if is_schema_attribute(attr_name, attr)}

        for attr_name, attr in attrs.items():
            try:
                if issubclass(attr, ModelABC):
                    schema_attrs[attr_name] = Nested(attr._schema_class)
            except TypeError:
                pass

        _schema_class = SchemaMeta('%sSchema' % name, (schema_base,), schema_attrs)

        model_class._schema_class = _schema_class

        return model_class
Exemple #2
0
def attrs_schema(cls: Type,
                 field_for_attr_hook: Optional[FIELD_FOR_ATTR_HOOK] = None,
                 make_object: bool = True):
    """
    This function takes class and returns generated Schema for it.

    :param cls:
    :param field_for_attr_hook: Function that creates fields for attributes
    :param make_object: Function that creates class from dict
    :return:
    """
    def field_for_attr(cls: type, attribute: attr.Attribute, tp: type,
                       field_kwargs: Mapping[str, Any]):
        field = get_marshmallow_opt(attribute, MARSHMALLOW_FIELD_OPT)
        if field:
            return field

        field_kwargs = {
            "required":
            attribute.default is attr.NOTHING,
            "allow_none":
            True,
            **field_kwargs,
            **get_marshmallow_opt(attribute, MARSHMALLOW_KWARGS_OPT, {}), ATTRIBUTE:
            attribute
        }

        for hook in _FIELD_FOR_ATTR_HOOKS + [field_for_attr_hook]:
            if hook:
                res = hook(cls, attribute, tp, field_kwargs, field_for_attr)
                if res:
                    return res

        return _default_field_for_attribute(cls, attribute, tp, field_kwargs,
                                            field_for_attr)

    fields = {
        name: field_for_attr(cls, attribute, attribute.type, {})
        for name, attribute in attr.fields_dict(cls).items() if attribute.init
        and not get_marshmallow_opt(attribute, MARSHMALLOW_SKIP_OPT)
    }

    @post_load
    def make_object_func(self, data, **kwargs):
        return cls(**data)

    if make_object:
        fields["make_object"] = make_object_func
    fields.update({
        name: getattr(cls, name)
        for l in SchemaMeta.resolve_hooks(cls).values() for name in l
    })

    meta = getattr(cls, "Meta", None)
    if meta:
        fields["Meta"] = meta

    return type("Schema", (marshmallow.Schema, ), fields)
def schema(_schema_dict=None, **kwargs):
    _schema_dict = dict(_schema_dict or kwargs)  # create copy for changes

    for key, value in _schema_dict.items():
        if isinstance(value, dict):
            _schema_dict[key] = nested_schema(value)

    # Passing empty string prevents class from getting added
    # to marshmallow's class registry, thus saving memory
    return SchemaMeta(str(''), (Schema,), _schema_dict)
Exemple #4
0
 def get_declared_fields(mcs, klass, cls_fields, inherited_fields, dict_cls):
     """
     Updates declared fields with fields converted from the SQLAlchemy model
     passed as the `model` class Meta option.
     """
     opts = klass.opts
     converter = opts.model_converter(schema_cls=klass)
     base_fields = _BaseModelSerializerMetaclass.get_declared_fields(
         klass, cls_fields, inherited_fields, dict_cls)
     declared_fields = mcs.get_fields(converter, opts, base_fields, dict_cls)
     if declared_fields is not None:  # prevents sphinx from blowing up
         declared_fields.update(base_fields)
     return declared_fields
Exemple #5
0
def parse_param(schema=None,
                schema_class=None,
                target="params",
                init_args={},
                load_args={}):
    """
    Decorator for checking and parsing request parameters.

    Args:
        schema: Schema instances to be used for deserializing.
        schema_class: Schema class to be used for deserializing.
            Can be a class derived from Schema class or a dictionary of class members.
            In the latter class, a class derived from Schema class will be created from given dictionary.
        target: Name of the attribute to be set on request data object (g).
        init_args: Parameters used to initialize a schema instance.
            Only valid when a schema class is passed in.
        load_args: Parameters used to deserialize requests.
    Returns:
        A decorator which does request parameters checking and deserializing before calling decorated view.
    """
    # Build schema from schema class
    if schema == None:
        # Build schema class from dictionary
        if isinstance(schema_class, dict):
            schema_class = SchemaMeta("ParamSchema", (Schema, ), schema_class)
        # Illegal schema class type
        elif not issubclass(schema_class, Schema):
            raise TypeError(
                "schema_class must be a dictionary or derived from Schema class."
            )
        schema = schema_class(**init_args)
    # Decorator
    def decorator(func):
        # Save parsed result into target variable
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            setattr(g, target,
                    load_data(schema, request.get_json(), **load_args))
            return func(*args, **kwargs)

        return wrapper

    return decorator
Exemple #6
0
    def get_declared_fields(mcs, klass, cls_fields, inherited_fields, dict_cls):
        prefix = klass.opts.prefix
        cls_fields = [(prefix + n, v) for n, v in cls_fields]
        inherited_fields = [(prefix + n, v) for n, v in inherited_fields]

        return MMSchemaMeta.get_declared_fields(klass, cls_fields, inherited_fields, dict_cls)