I'm looking for a function that can say if a type annotation is a subset of another.
It could be in the standard library or 3rd-party. Since type-checkers such as mypy and pytype have solved this problem, I assume there is some function that can do this, but couldn't find it.
e.g. a function f
such that:
from typing import *
f(Sequence, List) # True
f(Sequence[str], List) # False
f(Iterable[str], List[str]) # True
f(List[str], Iterable[str]) # False
f(str, str) # True
f(int, str) # False
issubclass
works for actual types and simple type annotations,
issubclass(str, str) # True
issubclass(int, str) # False
issubclass(list, Sequence) # True
issubclass(Iterable, Sequence) # False
issubclass(Sequence, Iterable) # True
but not for generics:
issubclass(List[str], Iterable[str])
TypeError: Subscripted generics cannot be used with class and instance checks
The high-level goal is be able to, given two functions, determine if they can be composed.
Ended up implementing this myself for the common use cases (Optional
, Union
, Callable
, Tuple
and simple types all work).
pip install gamla
then usage is:
import gamla
def test_is_subtype():
for x, y in [
[FrozenSet[str], FrozenSet[str]],
[str, Any],
[Tuple[str, ...], Tuple[str, ...]],
[Set[str], Collection[str]],
[List, Sequence],
[Union[int, str], Union[int, str]],
[str, Union[int, str]],
[Union[List, Set], Collection],
]:
assert gamla.is_subtype(x, y)
def test_not_is_subtype():
for x, y in [
[FrozenSet[int], FrozenSet[str]],
[str, FrozenSet[str]],
[Collection, FrozenSet],
[Tuple[str, ...], Tuple[int, ...]],
[Union[int, str], int],
[Any, str],
[List, Union[int, str]],
[Union[int, str, List], Union[int, str]],
]:
assert not gamla.is_subtype(x, y)