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 load_single_entry(self, value, partial): """Loads a single nested entry from its schema.""" type_ = normalize_type(value["@type"]) schema = self.schema["from"][str(type_)] if not schema: ValueError("Type {} not found in {}.{}".format(value["@type"], type(self.parent), self.data_key)) return schema.load(value, unknown=self.unknown, partial=partial)
def _serialize(self, obj: typing.Union[_T, typing.Iterable[_T]], *, many: bool = False): """Serialize ``obj`` to jsonld.""" if many and obj is not None: return [ self._serialize(d, many=False) for d in typing.cast(typing.Iterable[_T], obj) ] if isinstance(obj, Proxy): proxy_schema = obj.__proxy_schema__ if (not obj.__proxy_initialized__ and isinstance(proxy_schema, type(self)) and proxy_schema.flattened == self.flattened): # if proxy was not accessed and we use the same schema, return original data return obj.__proxy_original_data__ # resolve Proxy object obj = obj.__wrapped__ ret = self.dict_class() for attr_name, field_obj in self.dump_fields.items(): value = field_obj.serialize(attr_name, obj, accessor=self.get_attribute) if value is missing: continue key = field_obj.data_key if field_obj.data_key is not None else attr_name reverse = getattr(field_obj, "reverse", False) if reverse: if "@reverse" not in ret: ret["@reverse"] = self.dict_class() ret["@reverse"][key] = value else: ret[key] = value if "@id" not in ret or not ret["@id"]: ret["@id"] = self.opts.id_generation_strategy(ret, obj) # add type rdf_type = self.opts.rdf_type if not rdf_type: raise ValueError("No class type specified for schema") ret["@type"] = normalize_type(rdf_type) if self.flattened and self._top_level: ret = jsonld.flatten(ret) return ret
def load_single_entry(self, value, partial): """Loads a single nested entry from its schema.""" type_ = normalize_type(value["@type"]) schema = self.schema["from"][str(type_)] if not schema: ValueError("Type {} not found in {}.{}".format( value["@type"], type(self.parent), self.data_key)) if not schema._all_objects and self.root._all_objects: schema._all_objects = self.root._all_objects schema._reversed_properties = self.root._reversed_properties if schema.lazy: return Proxy( lambda: schema.load( value, unknown=self.unknown, partial=partial), schema, value) return schema.load(value, unknown=self.unknown, partial=partial)
def _serialize(self, obj: typing.Union[_T, typing.Iterable[_T]], *, many: bool = False): """Serialize ``obj`` to jsonld.""" if many and obj is not None: return [ self._serialize(d, many=False) for d in typing.cast(typing.Iterable[_T], obj) ] ret = self.dict_class() for attr_name, field_obj in self.dump_fields.items(): value = field_obj.serialize(attr_name, obj, accessor=self.get_attribute) if value is missing: continue key = field_obj.data_key if field_obj.data_key is not None else attr_name reverse = getattr(field_obj, "reverse", False) if reverse: if "@reverse" not in ret: ret["@reverse"] = self.dict_class() ret["@reverse"][key] = value else: ret[key] = value # add type rdf_type = self.opts.rdf_type if not rdf_type: raise ValueError("No class type specified for schema") ret["@type"] = normalize_type(rdf_type) if self.flattened: ret = jsonld.flatten(ret) return ret