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}"
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
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'))
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
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
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}
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
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" )
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)
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
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)
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
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
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
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
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
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
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)
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
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(), )
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
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
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
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
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
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
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'))
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
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
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)
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
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
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