inspection
¶
High-performance, Fine-grained runtime type inspections.
Typical Usage
>>> from typelib.py import inspection
>>> inspection.ismappingtype(dict)
True
>>> inspection.isfixedtupletype(tuple[int, str])
True
args
¶
Get the args supplied to an annotation, normalizing typing.TypeVar
.
Note
TypeVar normalization follows this strategy:
-> If the TypeVar is bound
-----> return the bound type
-> Else If the TypeVar has constraints
-----> return a Union of the constraints
-> Else
-----> return Any
Examples:
>>> from typelib.py import inspection
>>> from typing import Dict, TypeVar, Any
>>> T = TypeVar("T")
>>> args(Dict)
()
>>> args(Dict[str, int])
(<class 'str'>, <class 'int'>)
>>> args(Dict[str, T])
(<class 'str'>, typing.Any)
Source code in src/typelib/py/inspection.py
get_type_hints
¶
Wrapper for typing.get_type_hints
.
If typing.get_type_hints
raises ([NameError][], [TypeError][])
, we will
default to an empty dict.
Parameters:
-
obj
(Union[type, Callable]
) –The object to inspect.
-
exhaustive
(bool
, default:True
) –Whether to pull type hints from the signature of the object if none can be found via
typing.get_type_hints
. (defaults True)
Source code in src/typelib/py/inspection.py
isabstract
¶
isabstract(o) -> TypeIs[ABC]
isbuiltininstance
¶
isbuiltininstance(o: Any) -> TypeIs[BuiltIntypeT]
Test whether an object is an instance of a builtin type.
Examples:
isbuiltinsubtype
¶
Check whether the provided type is a subclass of a builtin-type.
Examples:
>>> from typing import NewType, Mapping
>>> class SuperStr(str): ...
...
>>> isbuiltinsubtype(SuperStr)
True
>>> isbuiltinsubtype(NewType("MyStr", SuperStr))
True
>>> class Foo: ...
...
>>> isbuiltintype(Foo)
False
>>> isbuiltintype(Mapping)
False
Source code in src/typelib/py/inspection.py
isbuiltintype
¶
isbuiltintype(obj: type | FunctionType) -> TypeIs[type[BuiltIntypeT]]
Check whether the provided object is a builtin-type.
Note
Python stdlib and Python documentation have no "definitive list" of
builtin-types, despite the fact that they are well-known. The closest we have
is https://docs.python.org/3.7/library/functions.html, which clumps the
builtin-types with builtin-functions. Despite clumping these types with functions
in the documentation, these types eval as False when compared to
types.BuiltinFunctionType
, which is meant to be an alias for the
builtin-functions listed in the documentation.
All this to say, here we are with a custom check to determine whether a type is a builtin.
Examples:
>>> from typing import NewType, Mapping
>>> isbuiltintype(str)
True
>>> isbuiltintype(NewType("MyStr", str))
True
>>> class Foo: ...
...
>>> isbuiltintype(Foo)
False
>>> isbuiltintype(Mapping)
False
Source code in src/typelib/py/inspection.py
isbytestype
¶
Test whether the given type is a subclass of text or bytes.
Examples:
Source code in src/typelib/py/inspection.py
iscallable
¶
Test whether the given type is a callable.
Examples:
>>> import typing
>>> import collections.abc
>>> iscallable(lambda: None)
True
>>> iscallable(typing.Callable)
True
>>> iscallable(collections.abc.Callable)
True
>>> iscallable(1)
False
Source code in src/typelib/py/inspection.py
isclassvartype
¶
Test whether an annotation is a ClassVar annotation.
Examples:
>>> from typing import ClassVar, NewType
>>> isclassvartype(ClassVar[str])
True
>>> isclassvartype(NewType("Foo", ClassVar[str]))
True
Source code in src/typelib/py/inspection.py
iscollectiontype
¶
iscollectiontype(obj: type) -> TypeIs[type[Collection]]
Test whether this annotation is a subclass of typing.Collection
.
Includes builtins.
Examples:
>>> from typing import Collection, Mapping, NewType
>>> iscollectiontype(Collection)
True
>>> iscollectiontype(Mapping[str, str])
True
>>> iscollectiontype(str)
True
>>> iscollectiontype(list)
True
>>> iscollectiontype(NewType("Foo", dict))
True
>>> iscollectiontype(int)
False
Source code in src/typelib/py/inspection.py
isdatetimetype
¶
Test whether this annotation is a a date/datetime object.
Examples:
>>> import datetime
>>> from typing import NewType
>>> isdatetype(datetime.datetime)
True
>>> isdatetype(datetime.date)
True
>>> isdatetype(NewType("Foo", datetime.datetime))
True
Source code in src/typelib/py/inspection.py
isdatetype
¶
Test whether this annotation is a a date/datetime object.
Examples:
>>> import datetime
>>> from typing import NewType
>>> isdatetype(datetime.datetime)
True
>>> isdatetype(datetime.date)
True
>>> isdatetype(NewType("Foo", datetime.datetime))
True
Source code in src/typelib/py/inspection.py
isdecimaltype
¶
Test whether this annotation is a Decimal object.
Examples:
>>> import decimal
>>> from typing import NewType
>>> isdecimaltype(decimal.Decimal)
True
>>> isdecimaltype(NewType("Foo", decimal.Decimal))
True
Source code in src/typelib/py/inspection.py
isdescriptor
¶
Test whether the given object is a types.GetSetDescriptorType
Examples:
>>> class StringDescriptor:
... __slots__ = ("value",)
...
... def __init__(self, default: str = "value"):
... self.value = default
...
... def __get__(self, instance: Any, value: str) -> str:
... return self.value
...
>>> isdescriptor(StringDescriptor)
True
Source code in src/typelib/py/inspection.py
isenumtype
¶
Test whether this annotation is a subclass of enum.Enum
Examples:
Source code in src/typelib/py/inspection.py
isfinal
¶
Test whether an annotation is typing.Final
.
Examples:
>>> from typing import NewType
>>> from typelib.py.compat import Final
>>> isfinal(Final[str])
True
>>> isfinal(NewType("Foo", Final[str]))
True
Source code in src/typelib/py/inspection.py
isfixedtupletype
¶
Check whether an object is a "fixed" tuple, e.g., tuple[int, int]
.
Examples:
>>> from typing import Tuple
>>>
>>>
>>> isfixedtupletype(Tuple[str, int])
True
>>> isfixedtupletype(Tuple[str, ...])
False
Source code in src/typelib/py/inspection.py
isfloattype
¶
Test whether t
is a subclass of the numbers.Number
protocol.
Examples:
Source code in src/typelib/py/inspection.py
isforwardref
¶
isforwardref(obj: Any) -> TypeIs[ForwardRef]
Tests whether the given object is a typing.ForwardRef
.
isfractiontype
¶
Test whether this annotation is a Decimal object.
Examples:
>>> import fractions
>>> from typing import NewType
>>> isdecimaltype(fractions.Fraction)
True
>>> isdecimaltype(NewType("Foo", fractions.Fraction))
True
Source code in src/typelib/py/inspection.py
isfromdictclass
¶
Test whether this annotation is a class with a from_dict()
method.
isfrozendataclass
¶
Test whether this is a dataclass and whether it's frozen.
isgeneric
¶
Test whether the given type is a typing generic.
Examples:
>>>
>>> isgeneric(Tuple)
True
>>> isgeneric(tuple)
False
>>> T = TypeVar("T")
>>> class MyGeneric(Generic[T]): ...
>>> isgeneric(MyGeneric[int])
True
Source code in src/typelib/py/inspection.py
ishashable
¶
Check whether an object is hashable.
An order of magnitude faster than isinstance
with
typing.Hashable
Examples:
Source code in src/typelib/py/inspection.py
isintegertype
¶
Test whether t
is a subclass of the numbers.Number
protocol.
Examples:
Source code in src/typelib/py/inspection.py
isiterabletype
¶
Test whether the given type is iterable.
Examples:
>>> from typing import Sequence, Collection
>>> isiterabletype(Sequence[str])
True
>>> isiterabletype(Collection)
True
>>> isiterabletype(str)
True
>>> isiterabletype(tuple)
True
>>> isiterabletype(int)
False
Source code in src/typelib/py/inspection.py
isiteratortype
¶
Check whether the given object is a subclass of an Iterator.
Examples:
>>> def mygen(): yield 1
...
>>> isiteratortype(mygen().__class__)
True
>>> isiteratortype(iter([]).__class__)
True
>>> isiteratortype(mygen)
False
>>> isiteratortype(list)
False
Source code in src/typelib/py/inspection.py
isliteral
¶
isliteral(obj) -> bool
ismappingtype
¶
Test whether this annotation is a subtype of typing.Mapping
.
Examples:
>>> from typing import Mapping, Dict, DefaultDict, NewType
>>> ismappingtype(Mapping)
True
>>> ismappingtype(Dict[str, str])
True
>>> ismappingtype(DefaultDict)
True
>>> ismappingtype(dict)
True
>>> class MyDict(dict): ...
...
>>> ismappingtype(MyDict)
True
>>> class MyMapping(Mapping): ...
...
>>> ismappingtype(MyMapping)
True
>>> ismappingtype(NewType("Foo", dict))
True
Source code in src/typelib/py/inspection.py
isnamedtuple
¶
isnamedtuple(obj: type) -> TypeIs[type[NamedTuple]]
Check whether an object is a "named" tuple (collections.namedtuple
).
Examples:
>>> from collections import namedtuple
>>>
>>> FooTup = namedtuple("FooTup", ["bar"])
>>> isnamedtuple(FooTup)
True
Source code in src/typelib/py/inspection.py
isnonetype
¶
isnonetype(t: Any) -> TypeIs[None]
isnumbertype
¶
Test whether t
is a subclass of the numbers.Number
protocol.
Examples:
Source code in src/typelib/py/inspection.py
isoptionaltype
¶
Test whether an annotation is typing.Optional
, or can be treated as.
typing.Optional
is an alias for typing.Union[<T>, None]
, so both are
"optional".
Examples:
>>> from typing import Optional, Union, Dict, Literal
>>> isoptionaltype(Optional[str])
True
>>> isoptionaltype(Union[str, None])
True
>>> isoptionaltype(Literal["", None])
True
>>> isoptionaltype(Dict[str, None])
False
Source code in src/typelib/py/inspection.py
ispathtype
¶
ispatterntype
¶
isproperty
¶
isproperty(obj) -> TypeIs[DynamicClassAttribute]
Test whether the given object is an instance of [property
] or functools.cached_property
.
Examples:
>>> class Foo:
... @property
... def prop(self) -> int:
... return 1
...
... @functools.cached_property
... def cached(self) -> str:
... return "foo"
...
>>> isproperty(Foo.prop)
True
>>> isproperty(Foo.cached)
True
Source code in src/typelib/py/inspection.py
issequencetype
¶
issequencetype(obj: type) -> TypeIs[type[Collection]]
Test whether this annotation is a subclass of typing.Collection
.
Includes builtins.
Examples:
>>> from typing import Collection, Mapping, NewType, Sequence
>>> issequencetype(Sequence)
True
>>> issequencetype(Mapping[str, str])
True
>>> issequencetype(str)
True
>>> issequencetype(list)
True
>>> issequencetype(NewType("Foo", dict))
True
>>> issequencetype(int)
False
Source code in src/typelib/py/inspection.py
issimpleattribute
¶
issimpleattribute(v) -> bool
Test whether the given object is a static value
(e.g., not a function, class, or descriptor).
Examples:
>>> class MyOperator:
... type = str
...
... def operate(self, v) -> type:
... return self.type(v)
...
... @property
... def default(self) -> type:
... return self.type()
...
>>> issimpleattribute(MyOperator.type)
False
>>> issimpleattribute(MyOperator.operate)
False
>>> issimpleattribute(MyOperator.default)
False
Source code in src/typelib/py/inspection.py
isstdlibinstance
¶
isstdlibinstance(o: Any) -> TypeIs[STDLibtypeT]
Test whether an object is an instance of a type in the standard-lib.
isstdlibsubtype
¶
Test whether the given type is a subclass of a standard-lib type.
Examples:
Source code in src/typelib/py/inspection.py
isstringtype
¶
Test whether the given type is a subclass of text or bytes.
Examples:
Source code in src/typelib/py/inspection.py
isstructuredtype
¶
Test whether the given type has a fixed set of fields.
Examples:
>>> import dataclasses
>>> from typing import Tuple, NamedTuple, TypedDict, Union, Literal, Collection
>>>
>>> isstructuredtype(Tuple[str, int])
True
>>> isstructuredtype(class MyDict(TypedDict): ...)
True
>>> isstructuredtype(class MyTup(NamedTuple): ...)
True
>>> isstructuredtype(class MyClass: ...)
True
>>> isstructuredtype(Union[str, int])
False
>>> isstructuredtype(Literal[1, 2])
False
>>> isstructuredtype(tuple)
False
>>> isstructuredtype(Collection[str])
False
Source code in src/typelib/py/inspection.py
issubscriptedcollectiontype
¶
issubscriptedcollectiontype(obj: type[Generic[_ArgsT]]) -> TypeIs[type[Collection[_ArgsT]]]
Test whether this annotation is a collection type and is subscripted.
Examples:
>>> from typing import Collection, Mapping, NewType
>>> issubscriptedcollectiontype(Collection)
False
>>> issubscriptedcollectiontype(Mapping[str, str])
True
>>> issubscriptedcollectiontype(str)
False
>>> issubscriptedcollectiontype(NewType("Foo", Collection[int]))
True
Source code in src/typelib/py/inspection.py
issubscriptedgeneric
¶
Test whether the given type is a typing generic.
Examples:
>>>
>>> isgeneric(Tuple)
True
>>> isgeneric(tuple)
False
>>> T = TypeVar("T")
>>> class MyGeneric(Generic[T]): ...
>>> isgeneric(MyGeneric[int])
True
Source code in src/typelib/py/inspection.py
istexttype
¶
Test whether the given type is a subclass of text or bytes.
Examples:
Source code in src/typelib/py/inspection.py
istimedeltatype
¶
Test whether this annotation is a a date/datetime object.
Examples:
>>> import datetime
>>> from typing import NewType
>>> istimedeltatype(datetime.timedelta)
True
>>> istimedeltatype(NewType("Foo", datetime.timedelta))
True
Source code in src/typelib/py/inspection.py
istimetype
¶
Test whether this annotation is a a date/datetime object.
Examples:
>>> import datetime
>>> from typing import NewType
>>> istimetype(datetime.time)
True
>>> istimetype(NewType("Foo", datetime.time))
True
Source code in src/typelib/py/inspection.py
istupletype
¶
Tests whether the given type is a subclass of tuple
.
Examples:
>>> from typing import NamedTuple, Tuple
>>> class MyTup(NamedTuple):
... field: int
...
>>> istupletype(tuple)
True
>>> istupletype(Tuple[str])
True
>>> istupletype(MyTup)
True
Source code in src/typelib/py/inspection.py
istypealiastype
¶
istypealiastype(t: Any) -> TypeIs[TypeAliasType]
Detect if the given object is a typing.TypeAliasType
.
Examples:
>>> type IntList = list[int]
>>> istypealiastype(IntList)
True
>>> IntList = compat.TypeAliasType("IntList", list[int])
>>> istypealiastype(IntList)
True
Source code in src/typelib/py/inspection.py
istypeddict
¶
Check whether an object is a typing.TypedDict
.
Examples:
>>> from typing import TypedDict
>>>
>>> class FooMap(TypedDict):
... bar: str
...
>>> istypeddict(FooMap)
True
Source code in src/typelib/py/inspection.py
istypedtuple
¶
istypedtuple(obj: type) -> TypeIs[type[NamedTuple]]
Check whether an object is a "typed" tuple (typing.NamedTuple
).
Examples:
>>> from typing import NamedTuple
>>>
>>> class FooTup(NamedTuple):
... bar: str
...
>>> istypedtuple(FooTup)
True
Source code in src/typelib/py/inspection.py
isunresolvable
¶
isuuidtype
¶
Test whether this annotation is a a date/datetime object.
Examples:
>>> import uuid
>>> from typing import NewType
>>> isuuidtype(uuid.UUID)
True
>>> class MyUUID(uuid.UUID): ...
...
>>> isuuidtype(MyUUID)
True
>>> isuuidtype(NewType("Foo", uuid.UUID))
True
Source code in src/typelib/py/inspection.py
name
¶
Safely retrieve the name of either a standard object or a type annotation.
Examples:
>>> from typelib.py import inspection
>>> from typing import Dict, Any, TypeVar
>>> T = TypeVar("T")
>>> name(Dict)
'Dict'
>>> name(Dict[str, str])
'Dict'
>>> name(Any)
'Any'
>>> name(dict)
'dict'
Source code in src/typelib/py/inspection.py
normalize_typevar
¶
Reduce a TypeVar to a simple type.
Note
TypeVar normalization follows this strategy:
-> If the TypeVar is bound
-----> return the bound type
-> Else If the TypeVar has constraints
-----> return a Union of the constraints
-> Else
-----> return Any
Source code in src/typelib/py/inspection.py
origin
¶
Get the highest-order 'origin'-type for a given type definition.
Tip
For the purposes of this library, if we can resolve to a builtin type, we will.
Examples:
>>> from typelib.py import inspection
>>> from typing import Dict, Mapping, NewType, Optional
>>> origin(Dict)
<class 'dict'>
>>> origin(Mapping)
<class 'dict'>
>>> Registry = NewType('Registry', Dict)
>>> origin(Registry)
<class 'dict'>
>>> class Foo: ...
...
>>> origin(Foo)
<class 'typelib.Foo'>
Source code in src/typelib/py/inspection.py
qualname
¶
Safely retrieve the qualname of either a standard object or a type annotation.
Examples:
>>> from typelib.py import inspection
>>> from typing import Dict, Any, TypeVar
>>> T = TypeVar("T")
>>> qualname(Dict)
'typing.Dict'
>>> qualname(Dict[str, str])
'typing.Dict'
>>> qualname(Any)
'typing.Any'
>>> qualname(dict)
'dict'
Source code in src/typelib/py/inspection.py
resolve_supertype
¶
resolve_supertype(annotation: type[Any] | FunctionType) -> Any
Get the highest-order supertype for a NewType.
Examples:
>>> from typelib.py import inspection
>>> from typing import NewType
>>> UserID = NewType("UserID", int)
>>> AdminID = NewType("AdminID", UserID)
>>> resolve_supertype(AdminID)
<class 'int'>
Source code in src/typelib/py/inspection.py
safe_get_params
¶
Try to extract the parameters of the given object.
Return an empty mapping if we encounter an error.
Source code in src/typelib/py/inspection.py
should_unwrap
¶
Test whether we should use the args attr for resolving the type.
This is useful for determining what type to use at run-time for coercion.
Source code in src/typelib/py/inspection.py
signature
¶
Get the signature of a type or callable.
Also supports TypedDict subclasses
Source code in src/typelib/py/inspection.py
simple_attributes
¶
Extract all public, static data-attributes for a given type.
Source code in src/typelib/py/inspection.py
tuple_signature
¶
A little faker for getting the "signature" of a tuple
.
Note
At runtime, tuples are just tuples, but we can make use of their type hints to define a predictable signature.
Source code in src/typelib/py/inspection.py
typed_dict_signature
¶
A little faker for getting the "signature" of a typing.TypedDict
.
Note
Technically, these are dicts at runtime, but we are enforcing a static shape, so we should be able to declare a matching signature for it.