Inspecting type annotations at runtime can be hard. Often times, typing members aren’t properly checked, and the stdlib get_origin()/get_args() utility functions are not understood correctly.
Here are a couple examples:
- For a typing object named
TypingObj, it is common to see simplevar is typing.TypingObjchecks in the wild, which do not account for the possibly differenttyping_extensionsvariant [1]. get_origin()is not necessarily returning the “unparameterized” version of a generic typing object. For instance,get_origin(typing.Tuple)istuple, whileget_origin(tuple)isNone.
Additionally, such checks can be become expensive if repeated a lot (get_origin/args() perform a lot of isinstance calls).
As per a discussion initiated by @leyec, we created the typing-inspection library in the Pydantic org [2]. It provides:
- a low-level
typing_objectsmodule, meant to check if a variable is a typing object, e.g.is_annotated(). - a high-level
introspectionmodule, meant to inspect type annotations (unpacking literal values, type qualifiers, etc).
To better understand how these utilities can be used, I wrote a (probably still incomplete) guide giving a recommended workflow to inspect type annotations, available here.
We are planning on making an initial release, soon, but we’d be pleased to have feedback from developers making use of type hints at runtime. Some design decisions are still under discussion, and as such I opened a bunch of open issues to discuss.