Skip to content

erdantic.typing_utils

get_depth1_bases

get_depth1_bases(tp: type) -> List[type]

Returns depth-1 base classes of a type.

Source code in erdantic/typing_utils.py
63
64
65
66
def get_depth1_bases(tp: type) -> List[type]:
    """Returns depth-1 base classes of a type."""
    bases_of_bases = {bb for b in tp.__mro__[1:] for bb in b.__mro__[1:]}
    return [b for b in tp.__mro__[1:] if b not in bases_of_bases]

get_recursive_args

get_recursive_args(tp: _TypeForm) -> List[_TypeForm]

Recursively finds leaf-node types of possibly-nested generic type.

Source code in erdantic/typing_utils.py
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
def get_recursive_args(tp: _TypeForm) -> List[_TypeForm]:
    """Recursively finds leaf-node types of possibly-nested generic type."""

    def recurse(t: _TypeForm) -> Iterator[_TypeForm]:
        if isinstance(t, str):
            raise _UnevaluatedForwardRefError(forward_ref=t)
        elif isinstance(t, ForwardRef):
            if t.__forward_evaluated__:
                t = t.__forward_value__  # type: ignore [assignment]
            else:
                raise _UnevaluatedForwardRefError(forward_ref=t.__forward_arg__)

        if get_origin(t) is Literal:
            yield t
            return

        args = get_args(t)
        if args:
            for arg in args:
                yield from recurse(arg)
        else:
            yield t

    return list(recurse(tp))

is_collection_type_of

is_collection_type_of(tp: _TypeForm, target: type) -> bool

Given a type annotation, returns True if it represents a collection of many elements of the target type.

Parameters:

Name Type Description Default
tp Union[type, GenericAlias]

Type annotation.

required
target type

Type to check for many-ness of.

required

Returns:

Type Description
bool

Result of check.

Source code in erdantic/typing_utils.py
35
36
37
38
39
40
41
42
43
44
45
46
47
def is_collection_type_of(tp: _TypeForm, target: type) -> bool:
    """Given a type annotation, returns True if it represents a collection of many elements of the
    target type.

    Args:
        tp (Union[type, GenericAlias]): Type annotation.
        target (type): Type to check for many-ness of.

    Returns:
        bool: Result of check.
    """
    root = parse_type_tree(tp)
    return _walk_type_tree(root, target)

is_nullable_type

is_nullable_type(tp: _TypeForm) -> bool

Given a type annotation, returns True if it is a union with None as a possible option, such as typing.Optional.

Parameters:

Name Type Description Default
tp Union[type, GenericAlias]

Type annotation.

required

Returns:

Type Description
bool

Result of check.

Source code in erdantic/typing_utils.py
50
51
52
53
54
55
56
57
58
59
60
def is_nullable_type(tp: _TypeForm) -> bool:
    """Given a type annotation, returns True if it is a union with None as a possible option,
    such as typing.Optional.

    Args:
        tp (Union[type, GenericAlias]): Type annotation.

    Returns:
        bool: Result of check.
    """
    return get_origin(tp) is Union and type(None) in get_args(tp)

repr_type_with_mro

repr_type_with_mro(obj: Any) -> str

Return MRO of object if it has one. Otherwise return its repr.

Source code in erdantic/typing_utils.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
def repr_type_with_mro(obj: Any) -> str:
    """Return MRO of object if it has one. Otherwise return its repr."""

    def _full_name(tp: type) -> str:
        module = tp.__module__
        return f"{module}.{tp.__qualname__}".replace("builtins.", "")

    if hasattr(obj, "__mro__"):
        mro = ", ".join(_full_name(m) for m in obj.__mro__)
        return f"<mro ({mro})>"
    return repr(obj)