Package: typenames
typenames : String representations of type annotationstypenamesis a configurable Python library for creating string representations of type annotations. By default, it produces compact representations by removing standard library module names. Configurable options include standardizing on|operator syntax for unions or standard collections classes for generics.importtypingfromtypenamesimporttypenamestypenames(int)#> 'int'typenames(dict[str,typing.Any])#> 'dict[str, Any]'typenames(str|int)#> 'str | int'typenames(typing.Optional[str])#> 'Optional[str]'Why use this library?String representations of Python type objects, type aliases, and special typing forms are inconsistent and often verbose. Here are some comparisons using default settings against built-in string representations:InputWithstr(...)Withtypenames(...)int<class 'int'>intlist<class 'list'>listtyping.Optional[int]typing.Optional[int]Optional[int]collections.abc.Iterator[typing.Any]collections.abc.Iterator[typing.Any]Iterator[Any]typing.Literal[MyEnum.NAME]typing.Literal[<MyEnum.NAME: 'value'>]Literal[MyEnum.NAME]typenames also has handy configurable functionality, such as:Forcing standardization on|operator union syntax (e.g.,Union[int, str]toint | str) or vice versaForcing standardization on|operator optional syntax (e.g.,Optional[int]toint | None) or vice versaForcing standardization on standard collection types for generics (e.g.,List[int]tolist[int]) or vice versaControlling exactly which module names to remove using regex patterns.No need for string manipulation to get what you want!Installationtypenames is available on PyPI:pipinstalltypenamesBasic UsageThe main way to use the library is thetypenamesfunction. Calling it on a type annotation renders a string representation:importtypingfromtypenamesimporttypenamestypenames(int)#> 'int'typenames(typing.Optional[str])#> 'Optional[str]'typenames(collections.abc.Callable[[int],tuple[str,...]])#> 'Callable[[int], tuple[str, ...]]Under the hood, typenames parses a type annotation as a tree structure. If you need to see the parsed tree, use theparse_type_treefunction to return the root node. You can get the rendered string representation by callingstr(...)on root node.importtypingfromtypenamesimportparse_type_treetree=parse_type_tree(typing.Union[typing.Any,list[typing.Any]])tree#> <GenericNode typing.Union[<TypeNode typing.Any>, <GenericNode <class 'list'>[<TypeNode typing.Any>]>]>str(tree)#> 'Union[Any, list[Any]]'Configurable optionsAll configuration options can be passed as keyword arguments to either thetypenamesorparse_type_treefunctions.Union Syntax (union_syntax)This option controls how unions are rendered. It supports both thetyping.Unionspecial form and the|operator (bitwise or) syntax fromPEP 604. Valid options are defined by the enumUnionSyntaxand include:"as_given"(default): render the union as it is given without changing syntax."or_operator": render all type unions using the|operator."special_form": render all type unions using thetyping.Unionspecial form.Note that runtime use of the|operator between types is new in Python 3.10. To use in earlier versions of Python, you will need to use postponed evaluation of annotations à laPEP 563withfrom __future__ import__annotations__. Support for the|operator is only a limitation on providing type annotation inputs to typenames, and not a limitation on output rendering.Limitations:Python automatically flattens unions when evaluating them at runtime. Since typenames uses runtime type objects, it will only see the flattened result and not know if your original input was nested. Furthermore, any mixing of|operator syntax and any typing module types will result in atyping.Unionunion, soas_givenwill always render such inputs withtyping.Union.Optional Syntax (optional_syntax)This option controls how optional types are rendered. It supports both thetyping.Optionalspecial form and the|operator (bitwise or) syntax fromPEP 604. Valid options are defined by the enumOptionalSyntaxand include:"as_given"(default): render the optional type as it is given without changing syntax"or_operator": render all optional types using the|operator"union_special_form": render all optional types using thetyping.Optionalspecial form"optional_special_form": render all optional types using thetyping.Optionalspecial formNote that runtime use of the|operator between types is new in Python 3.10. To use in earlier versions of Python, you will need to use postponed evaluation of annotations à laPEP 563withfrom __future__ import__annotations__. Support for the|operator is only a limitation on providing type annotation inputs to typenames, and not a limitation on output rendering.Limitations:Python automatically convertstyping.Union[..., None]totyping.Optional[...]when evaluating at runtime. Since typenames uses runtime type objects, it will only see the result usingtyping.Optionaland not know the form of your original input.Python automatically flattens unions when evaluating them at runtime. Since typenames uses runtime type objects, it will only see the flattened result and not know if your original input was nested. Furthermore, any mixing of|operator syntax and any typing module types will result in atyping.Unionunion, soas_givenwill always render such inputs with typing module special forms.Thetyping.Optionalspecial form only accepts exactly one parameter. By default, typenames will render cases with multiple parameters withOptional[Union[...]]. You can use theunion_syntaxoption to control the inner union's syntax.Standard Collection Syntax (standard_collection_syntax)This option controls how parameterized standard collection generic types are rendered. It supports both the typing module's generic aliases (e.g.,typing.List[...]) and the standard class (e.g.,list[...]) syntax fromPEP 585. Valid options are defined by the enumStandardCollectionSyntaxand include:"as_given"(default): render the parameterized generic type as it is given without changing syntax"standard_class": render all parameterized standard collection generic types using their class"typing_module": render all parameterized standard collection generic types using the typing module's generic aliasNote that runtime use of standard collection classes as parameterized generic types is new in Python 3.9. To use in earlier versions of Python, you will need to use postponed evaluation of annotations à laPEP 563withfrom __future__ import__annotations__. Support for standard collection classes for parameterized generic types is only a limitation on providing type annotation inputs to typenames, and not a limitation on output rendering.Removing Module Names (remove_modules)This option controls how module names are removed from the rendered output. It takes a list of inputs, which can either be a string of the module name or are.Patternregex pattern directly (the result ofre.compile). String inputs are templated into the following regex pattern:module:str# Given module namere.compile(r"^{}\.".format(module.replace(".",r"\.")))Note that module names are removed in the given order, so having entries that are submodules of other entries can potentially lead to the wrong behavior. You can either order them from higher-depth to lower-depth, or directly provide a compiled pattern with optional groups. For example, the patternre.compile(r"^collections\.(abc\.)?")will match both"collections."and"collections.abc.".The default list of module names include the standard library modules relevant toPEP 585plustypesandtyping. It can be accessed atDEFAULT_REMOVE_MODULES.DEFAULT_REMOVE_MODULES:List[Union[str,re.Pattern]]=["__main__","builtins",re.compile(r"^collections\.(abc\.)?"),"contextlib","re","types","typing",]If you are trying toaddadditional modules to this option (rather than overriding the defaults), the easiest way to do so is to concatenate with the default list:fromtypingimportOptionalfromtypenamesimporttypenames,DEFAULT_REMOVE_MODULES,BaseNodetypenames(Optional[BaseNode])#> 'Optional[typenames.BaseNode]'typenames(Optional[BaseNode],remove_modules=["typenames"])#> 'typing.Optional[BaseNode]'typenames(Optional[BaseNode],remove_modules=DEFAULT_REMOVE_MODULES+["typenames"],)#> 'Optional[BaseNode]'To remove all module names, you can useREMOVE_ALL_MODULES, which contains the patternre.compile(r"^(\w+\.)+").Reproducible examples created byreprexlite.