Skip to content

optype.inspect

A collection of functions for runtime inspection of types, modules, and other objects.

Function Description
get_args(_) A better alternative to typing.get_args(), that
  • unpacks typing.Annotated and Python 3.12 type _ alias types (i.e. typing.TypeAliasType),
  • recursively flattens unions and nested typing.Literal types, and
  • raises TypeError if not a type expression.
Return a tuple[...] of type arguments or parameters.
To illustrate one of the (many) issues with typing.get_args():
>>> from typing import Literal, TypeAlias, get_args
>>> Falsy: TypeAlias = Literal[None] | Literal[False, 0] | Literal["", b""]
>>> get_args(Falsy)
(typing.Literal[None], typing.Literal[False, 0], typing.Literal['', b''])
But this is in direct contradiction with the official typing documentation:
When a Literal is parameterized with more than one value, it’s treated as exactly equivalent to the union of those types. That is, Literal[v1, v2, v3] is equivalent to Literal[v1] | Literal[v2] | Literal[v3]
So this is why optype.inspect.get_args should be used
>>> import optype as opt
>>> opt.inspect.get_args(Falsy)
(None, False, 0, '', b'')
Another issue of typing.get_args() is with Python 3.12 type _ = ... aliases, which are meant as a replacement for _: typing.TypeAlias = ..., and should therefore be treated equally:
>>> import typing
>>> import optype as opt
>>> type StringLike = str | bytes
>>> typing.get_args(StringLike)
()
>>> opt.inspect.get_args(StringLike)
(<class 'str'>, <class 'bytes'>)
Clearly, typing.get_args fails miserably here; it would have been better if it would have raised an error, but it instead returns an empty tuple, hiding the fact that it doesn't support the new type _ = ... aliases. But luckily, optype.inspect.get_args doesn't have this problem, and treats it just like it treats typing.Alias (and so do the other optype.inspect functions).
get_protocol_members(_) A better alternative to typing.get_protocol_members(), that
  • doesn't require Python 3.13 or above,
  • supports PEP 695 type _ alias types on Python 3.12 and above,
  • unpacks unions of typing.Literal ...
  • ... and flattens them if nested within another typing.Literal,
  • treats typing.Annotated[T] as T, and
  • raises a TypeError if the passed value isn't a type expression.
Returns a frozenset[str] with member names.
get_protocols(_) Returns a frozenset[type] of the public protocols within the passed module. Pass private=True to also return the private protocols.
is_iterable(_) Check whether the object can be iterated over, i.e. if it can be used in a for loop, without attempting to do so. If True is returned, then the object is an optype.typing.AnyIterable instance.
is_final(_) Check if the type, method / classmethod / staticmethod / property, is decorated with @typing.final.
Note that a @property won't be recognized unless the @final decorator is placed *below* the @property decorator. See the function docstring for more information.
is_protocol(_) A backport of typing.is_protocol that was added in Python 3.13, a re-export of typing_extensions.is_protocol.
is_runtime_protocol(_) Check if the type expression is a runtime-protocol, i.e. a typing.Protocol type, decorated with @typing.runtime_checkable (also supports typing_extensions).
is_union_type(_) Check if the type is a typing.Union type, e.g. str | int.
Unlike isinstance(_, types.Union), this function also returns True for unions of user-defined Generic or Protocol types (because those are different union types for some reason).
is_generic_alias(_) Check if the type is a *subscripted* type, e.g. list[str] or optype.CanNext[int], but not list, CanNext.
Unlike isinstance(_, typing.GenericAlias), this function also returns True for user-defined Generic or Protocol types (because those are use a different generic alias for some reason).
Even though technically T1 | T2 is represented as typing.Union[T1, T2] (which is a (special) generic alias), is_generic_alias will returns False for such union types, because calling T1 | T2 a subscripted type just doesn't make much sense.

[!NOTE] All functions in optype.inspect also work for Python 3.12 type _ aliases (i.e. types.TypeAliasType) and with typing.Annotated.