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
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)
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
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
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)