Skip to content

Commit

Permalink
Improve performance
Browse files Browse the repository at this point in the history
  • Loading branch information
mciszczon committed Jan 16, 2023
1 parent 01774eb commit 3addf2d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 15 deletions.
6 changes: 2 additions & 4 deletions dacite/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,8 @@ def _build_value(type_: Type, data: Any, config: Config) -> Any:
data = _build_value_for_collection(collection=type_, data=data, config=config)
elif cache(is_dataclass)(type_) and isinstance(data, Mapping):
data = from_dict(data_class=type_, data=data, config=config)
elif is_generic_subclass(type_) and is_dataclass(get_origin(type_)):
origin = get_origin(type_)
assert origin is not None
data = from_dict(data_class=origin, data=data, config=config)
elif is_generic_subclass(type_) and cache(is_dataclass)(get_origin(type_)):
data = from_dict(data_class=get_origin(type_), data=data, config=config)
for cast_type in config.cast:
if is_subclass(type_, cast_type):
if is_generic_collection(type_):
Expand Down
46 changes: 35 additions & 11 deletions dacite/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,13 @@ def is_valid_generic_class(value: Any, type_: Type) -> bool:
origin = get_origin(type_)
if not (origin and isinstance(value, origin)):
return False
type_hints = get_type_hints(type(value))
type_hints = cache(get_type_hints)(type(value))
for field_name, field_type in type_hints.items():
if isinstance(field_type, TypeVar):
return (
any(isinstance(getattr(value, field_name), arg) for arg in get_args(type_)) if get_args(type_) else True
)
args = get_args(type_)
return True if not args else any(isinstance(getattr(value, field_name, None), arg) for arg in args)
else:
return is_instance(value, type_)
return isinstance(value, type_)
return True


Expand All @@ -121,6 +120,31 @@ def extract_init_var(type_: Type) -> Union[Type, Any]:
return Any


@cache
def get_constraints(type_: TypeVar) -> Optional[Any]:
return type_.__constraints__


@cache
def is_constrained(type_: TypeVar) -> bool:
return hasattr(type_, "__constraints__") and get_constraints(type_)


@cache
def get_bound(type_: TypeVar) -> Optional[Any]:
return type_.__bound__


@cache
def is_bound(type_: TypeVar) -> bool:
return hasattr(type_, "__bound__") and get_bound(type_)


@cache
def is_generic_bound(type_: TypeVar) -> bool:
return is_bound(type_) and get_bound(type_) is not None and is_generic(get_bound(type_))


def is_instance(value: Any, type_: Type) -> bool:
try:
# As described in PEP 484 - section: "The numeric tower"
Expand Down Expand Up @@ -164,13 +188,13 @@ def is_instance(value: Any, type_: Type) -> bool:
elif isclass(type(type_)) and is_generic_alias(type(type_)):
return is_valid_generic_class(value, type_)
elif isinstance(type_, TypeVar):
if hasattr(type_, "__constraints__") and type_.__constraints__:
if is_constrained(type_):
return any(is_instance(value, t) for t in type_.__constraints__)
if hasattr(type_, "__bound__") and type_.__bound__:
if isinstance(type_.__bound__, tuple):
return any(is_instance(value, t) for t in type_.__bound__)
if type_.__bound__ is not None and is_generic(type_.__bound__):
return isinstance(value, extract_generic(type_.__bound__))
if is_bound(type_):
if isinstance(get_bound(type_), tuple):
return any(isinstance(value, t) for t in get_bound(type_))
if is_generic_bound(type_):
return isinstance(value, extract_generic(get_bound(type_)))
return True
elif is_type_generic(type_):
return is_subclass(value, extract_generic(type_)[0])
Expand Down

0 comments on commit 3addf2d

Please sign in to comment.