make safe issubclass

This commit is contained in:
Khaleel Al-Adhami 2024-11-15 17:12:42 -08:00
parent 079cc56f59
commit 7d0a4f7133

View File

@ -778,6 +778,24 @@ StateBases = get_base_class(StateVar)
StateIterBases = get_base_class(StateIterVar) StateIterBases = get_base_class(StateIterVar)
def safe_issubclass(cls: Any, class_or_tuple: Any, /) -> bool:
"""Check if a class is a subclass of another class or a tuple of classes.
Args:
cls: The class to check.
class_or_tuple: The class or tuple of classes to check against.
Returns:
Whether the class is a subclass of the other class or tuple of classes.
"""
try:
return issubclass(cls, class_or_tuple)
except TypeError as e:
raise TypeError(
f"Invalid arguments for issubclass: {cls}, {class_or_tuple}"
) from e
def typehint_issubclass(possible_subclass: Any, possible_superclass: Any) -> bool: def typehint_issubclass(possible_subclass: Any, possible_superclass: Any) -> bool:
"""Check if a type hint is a subclass of another type hint. """Check if a type hint is a subclass of another type hint.
@ -798,7 +816,7 @@ def typehint_issubclass(possible_subclass: Any, possible_superclass: Any) -> boo
if provided_type_origin is None and accepted_type_origin is None: if provided_type_origin is None and accepted_type_origin is None:
# In this case, we are dealing with a non-generic type, so we can use issubclass # In this case, we are dealing with a non-generic type, so we can use issubclass
return issubclass(possible_subclass, possible_superclass) return safe_issubclass(possible_subclass, possible_superclass)
# Remove this check when Python 3.10 is the minimum supported version # Remove this check when Python 3.10 is the minimum supported version
if hasattr(types, "UnionType"): if hasattr(types, "UnionType"):
@ -835,17 +853,17 @@ def typehint_issubclass(possible_subclass: Any, possible_superclass: Any) -> boo
iterable_type = accepted_args[0] if accepted_args else Any iterable_type = accepted_args[0] if accepted_args else Any
if provided_type_origin is None: if provided_type_origin is None:
if not issubclass( if not safe_issubclass(
possible_subclass, (accepted_type_origin or possible_superclass) possible_subclass, (accepted_type_origin or possible_superclass)
): ):
return False return False
if issubclass(possible_subclass, str) and not isinstance( if safe_issubclass(possible_subclass, str) and not isinstance(
iterable_type, TypeVar iterable_type, TypeVar
): ):
return typehint_issubclass(str, iterable_type) return typehint_issubclass(str, iterable_type)
if not issubclass( if not safe_issubclass(
provided_type_origin, (accepted_type_origin or possible_superclass) provided_type_origin, (accepted_type_origin or possible_superclass)
): ):
return False return False
@ -867,7 +885,7 @@ def typehint_issubclass(possible_subclass: Any, possible_superclass: Any) -> boo
return True return True
# Check if the origin of both types is the same (e.g., list for List[int]) # Check if the origin of both types is the same (e.g., list for List[int])
if not issubclass( if not safe_issubclass(
provided_type_origin or possible_subclass, provided_type_origin or possible_subclass,
accepted_type_origin or possible_superclass, accepted_type_origin or possible_superclass,
): ):