def _to_model(typ: Type[ModelT], data: Any, **kwargs: Any) -> Optional[ModelT]: # called everytime something needs to be converted into a model. typ = remove_optional(typ) if data is not None and not isinstance(data, typ): model = typ.from_data(data, preferred_type=typ) return model if model is not None else data return data
def _is_model(cls: Type) -> Tuple[bool, Optional[Type]]: # Returns (is_model, concrete_type). # concrete type (if available) will be list if it's a list, dict if dict, # etc, then that means it's a List[ModelType], Dict[ModelType] etc, so # we have to deserialize them as such. concrete_type = None try: concrete_type, cls = guess_concrete_type(cls) except TypeError: pass try: cls = remove_optional(cls) return issubclass(cls, ModelT), concrete_type except TypeError: # typing.Any cannot be used with subclass return False, None
def _is_model(cls: Type) -> Tuple[bool, Type, Optional[Type]]: # Returns (is_model, polymorphic_type). # polymorphic type (if available) will be list if it's a list, # dict if dict, etc, then that means it's a List[ModelType], # Dict[ModelType] etc, so # we have to deserialize them as such. polymorphic_type = None try: polymorphic_type, cls = guess_polymorphic_type(cls) except TypeError: pass try: return issubclass(remove_optional(cls), ModelT), cls, polymorphic_type except TypeError: # typing.Any cannot be used with subclass return False, cls, None
def _contribute_field_descriptors( cls, target: Type, options: ModelOptions, parent: FieldDescriptorT = None) -> FieldMap: fields = options.fields defaults = options.defaults date_parser = options.date_parser coerce = options.coerce index = {} secret_fields = set() sensitive_fields = set() personal_fields = set() tagged_fields = set() def add_to_tagged_indices(field: str, tag: Type[Tag]) -> None: if tag.is_secret: options.has_secret_fields = True secret_fields.add(field) if tag.is_sensitive: options.has_sensitive_fields = True sensitive_fields.add(field) if tag.is_personal: options.has_personal_fields = True personal_fields.add(field) options.has_tagged_fields = True tagged_fields.add(field) def add_related_to_tagged_indices(field: str, related_model: Type = None) -> None: if related_model is None: return try: related_options = related_model._options except AttributeError: return if related_options.has_secret_fields: options.has_secret_fields = True secret_fields.add(field) if related_options.has_sensitive_fields: options.has_sensitive_fields = True sensitive_fields.add(field) if related_options.has_personal_fields: options.has_personal_fields = True personal_fields.add(field) if related_options.has_tagged_fields: options.has_tagged_fields = True tagged_fields.add(field) for field, typ in fields.items(): try: default, needed = defaults[field], False except KeyError: default, needed = None, True descr = getattr(target, field, None) if is_optional(typ): target_type = remove_optional(typ) else: target_type = typ if descr is None or not isinstance(descr, FieldDescriptorT): DescriptorType, tag = field_for_type(target_type) if tag: add_to_tagged_indices(field, tag) descr = DescriptorType( field=field, type=typ, model=cls, required=needed, default=default, parent=parent, coerce=coerce, date_parser=date_parser, tag=tag, ) else: descr = descr.clone( field=field, type=typ, model=cls, required=needed, default=default, parent=parent, coerce=coerce, ) descr.on_model_attached() for related_model in descr.related_models: add_related_to_tagged_indices(field, related_model) setattr(target, field, descr) index[field] = descr options.secret_fields = frozenset(secret_fields) options.sensitive_fields = frozenset(sensitive_fields) options.personal_fields = frozenset(personal_fields) options.tagged_fields = frozenset(tagged_fields) return index
def test_remove_optional(input, expected): assert remove_optional(input) == expected