Skip to content

Commit

Permalink
Improve performance by leveraging cache
Browse files Browse the repository at this point in the history
  • Loading branch information
mciszczon committed Jan 16, 2023
1 parent 01774eb commit 0d11d70
Showing 1 changed file with 32 additions and 7 deletions.
39 changes: 32 additions & 7 deletions dacite/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ 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 (
Expand All @@ -121,6 +121,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 +189,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(is_instance(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 0d11d70

Please sign in to comment.