Mitar
Mitar

Reputation: 7070

Compare types from Python typing

I have a function accepting another Python functions which are annotated with type hints (__annotations__). I would like to use those hints to do some type checking during runtime. The issue is that type classes from typing module does not seem very easy to work with (no isinstance, no issubclass). So, I wonder, is there a way to convert them to mypy type objects, and then use mypy.subtypes.is_subtype to compare types from type hints?

Upvotes: 3

Views: 2182

Answers (2)

user23307932
user23307932

Reputation: 177

I can provide a way to convert the most typing types into builtin types. Maybe this helps.

The typing module gives us the function get_origin. From documentation:

Get the unsubscripted version of a type: for a typing object of the form X[Y, Z, ...] return X.

If X is a typing-module alias for a builtin or collections class, it will be normalized to the original class. If X is an instance of ParamSpecArgs or ParamSpecKwargs, return the underlying ParamSpec. Return None for unsupported objects.

from typing import get_origin
import typing

def convert_typing_types(typing_type):
    converted = get_origin(typing_type)
    if converted in vars(typing).values():
        # do something with supported but not mappable types for example Literal
        pass

    if converted is None:
        # do something with unsupported typing Constructs, such like Self or NoReturn
        pass

    return converted

Now you can use the function like this:

>>> convert_typing_types(typing.List)
<class 'list'>
>>> convert_typing_types(typing.Dict)
<class 'dict'>

Because get_origin is not just for converting typing-aliases to builtins, there is a side effect, if, for example str is passed to get_origin, None is returned, so we have to do the following:

def convert_to_mypy(typ: Any) -> MyPyType:
    try:
        return convert_builtin_or_abc(typ)
    except ValueError:
        return convert_builtin_or_abc(convert_typing_types(typ))

Upvotes: 0

BoarGules
BoarGules

Reputation: 16951

The short answer is there is no easy way. The typing module is, by design, not going to provide much help for runtime checking. PEP 484 says

This PEP aims to provide a standard syntax for type annotations, opening up Python code to easier static analysis and refactoring, potential runtime type checking, and (perhaps, in some contexts) code generation utilizing type information.

Of these goals, static analysis is the most important. This includes support for off-line type checkers such as mypy, as well as providing a standard notation that can be used by IDEs for code completion and refactoring.

Non-goals

While the proposed typing module will contain some building blocks for runtime type checking -- in particular the get_type_hints() function -- third party packages would have to be developed to implement specific runtime type checking functionality, for example using decorators or metaclasses. Using type hints for performance optimizations is left as an exercise for the reader.

Upvotes: 1

Related Questions