Skip to content

Commit

Permalink
refactor: rename is_subclass_of to is_subtype_of. (#19)
Browse files Browse the repository at this point in the history
* refactor: rename `is_subclass_of` to `is_subtype_of`.

We already to more than just a simple `issubclass` test on the inputs so this is more appropriate.

Also, future planning for supporting use such as `TypeView(Literal[3]).is_subtype_of(Literal[3, 4])`, and similar.

* fix: extend renaming to `has_inner_subtype_of`

* fix: rename tests
  • Loading branch information
peterschutt authored May 17, 2024
1 parent e7e1064 commit 6752fd9
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 26 deletions.
24 changes: 12 additions & 12 deletions tests/test_type_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,22 +255,22 @@ def test_parsed_type_is_optional_predicate() -> None:
assert TypeView(Union[int, str]).is_optional is False


def test_parsed_type_is_subclass_of() -> None:
def test_parsed_type_is_subtype_of() -> None:
"""Test ParsedType.is_type_of."""
assert TypeView(bool).is_subclass_of(int) is True
assert TypeView(bool).is_subclass_of(str) is False
assert TypeView(Union[int, str]).is_subclass_of(int) is False
assert TypeView(list[int]).is_subclass_of(list) is True
assert TypeView(list[int]).is_subclass_of(int) is False
assert TypeView(Optional[int]).is_subclass_of(int) is False
assert TypeView(Union[bool, int]).is_subclass_of(int) is True
assert TypeView(bool).is_subtype_of(int) is True
assert TypeView(bool).is_subtype_of(str) is False
assert TypeView(Union[int, str]).is_subtype_of(int) is False
assert TypeView(list[int]).is_subtype_of(list) is True
assert TypeView(list[int]).is_subtype_of(int) is False
assert TypeView(Optional[int]).is_subtype_of(int) is False
assert TypeView(Union[bool, int]).is_subtype_of(int) is True


def test_parsed_type_has_inner_subclass_of() -> None:
def test_parsed_type_has_inner_subtype_of() -> None:
"""Test ParsedType.has_type_of."""
assert TypeView(list[int]).has_inner_subclass_of(int) is True
assert TypeView(list[int]).has_inner_subclass_of(str) is False
assert TypeView(list[Union[int, str]]).has_inner_subclass_of(int) is False
assert TypeView(list[int]).has_inner_subtype_of(int) is True
assert TypeView(list[int]).has_inner_subtype_of(str) is False
assert TypeView(list[Union[int, str]]).has_inner_subtype_of(int) is False


def test_parsed_type_equality() -> None:
Expand Down
28 changes: 14 additions & 14 deletions type_lens/type_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,12 @@ def is_forward_ref(self) -> bool:
@property
def is_mapping(self) -> bool:
"""Whether the annotation is a mapping or not."""
return self.is_subclass_of(Mapping)
return self.is_subtype_of(Mapping)

@property
def is_tuple(self) -> bool:
"""Whether the annotation is a ``tuple`` or not."""
return self.is_subclass_of(tuple)
return self.is_subtype_of(tuple)

@property
def is_variadic_tuple(self) -> bool:
Expand Down Expand Up @@ -123,7 +123,7 @@ def is_optional(self) -> bool:
@property
def is_collection(self) -> bool:
"""Whether the annotation is a collection type or not."""
return self.is_subclass_of(Collection)
return self.is_subtype_of(Collection)

@property
def is_none_type(self) -> bool:
Expand All @@ -138,40 +138,40 @@ def is_literal(self) -> bool:
@property
def is_non_string_collection(self) -> bool:
"""Whether the annotation is a non-string collection type or not."""
return self.is_collection and not self.is_subclass_of((str, bytes))
return self.is_collection and not self.is_subtype_of((str, bytes))

def is_subclass_of(self, cl: type[Any] | tuple[type[Any], ...]) -> bool:
"""Whether the annotation is a subclass of the given type.
def is_subtype_of(self, typ: Any | tuple[Any, ...], /) -> bool:
"""Whether the annotation is a subtype of the given type.
Where ``self.annotation`` is a union type, this method will return ``True`` when all members of the union are
a subtype of ``cl``, otherwise, ``False``.
Args:
cl: The type to check, or tuple of types. Passed as 2nd argument to ``issubclass()``.
typ: The type to check, or tuple of types. Passed as 2nd argument to ``issubclass()``.
Returns:
Whether the annotation is a subtype of the given type(s).
"""
if self.origin:
if self.origin in UNION_TYPES:
return all(t.is_subclass_of(cl) for t in self.inner_types)
return all(t.is_subtype_of(typ) for t in self.inner_types)

return self.origin not in UNION_TYPES and issubclass(self.origin, cl)
return self.origin not in UNION_TYPES and issubclass(self.origin, typ)

if self.annotation is AnyStr:
return issubclass(str, cl) or issubclass(bytes, cl)
return self.annotation is not Any and not self.is_type_var and issubclass(self.annotation, cl)
return issubclass(str, typ) or issubclass(bytes, typ)
return self.annotation is not Any and not self.is_type_var and issubclass(self.annotation, typ)

def has_inner_subclass_of(self, cl: type[Any] | tuple[type[Any], ...]) -> bool:
def has_inner_subtype_of(self, typ: type[Any] | tuple[type[Any], ...]) -> bool:
"""Whether any generic args are a subclass of the given type.
Args:
cl: The type to check, or tuple of types. Passed as 2nd argument to ``issubclass()``.
typ: The type to check, or tuple of types. Passed as 2nd argument to ``issubclass()``.
Returns:
Whether any of the type's generic args are a subclass of the given type.
"""
return any(t.is_subclass_of(cl) for t in self.inner_types)
return any(t.is_subtype_of(typ) for t in self.inner_types)

def strip_optional(self) -> TypeView:
if not self.is_optional:
Expand Down

0 comments on commit 6752fd9

Please sign in to comment.