Source code for returns.contrib.mypy._features.decorators

from typing import Callable, Optional

from mypy.nodes import ARG_POS, SymbolTableNode
from mypy.plugin import FunctionContext
from mypy.types import CallableType
from mypy.types import Type as MypyType

from returns.contrib.mypy._structures.args import FuncArg
from returns.contrib.mypy._typeops import analtype


[docs]def analyze( sym: Optional[SymbolTableNode], ) -> Callable[[FunctionContext], MypyType]: """ Changes a type of a decorator. This problem appears when we try to change the return type of the function. However, currently it is impossible due to this bug: https://github.com/python/mypy/issues/3157 It uses the passed function to copy its type. We only copy arguments and return type is defined by type annotations. """ def factory(ctx: FunctionContext) -> MypyType: if not (sym and sym.type and isinstance(sym.type, CallableType)): return ctx.default_return_type arg = ctx.api.expr_checker.accept(ctx.args[0][0]) # type: ignore tp = analtype.analyze_call( sym.type, [FuncArg(None, arg, ARG_POS)], ctx, show_errors=False, ) if not (isinstance(arg, CallableType) and isinstance(tp, CallableType)): return ctx.default_return_type if not isinstance(tp.ret_type, CallableType): return ctx.default_return_type return _change_decorator_function_type(tp.ret_type, arg) return factory
def _change_decorator_function_type( decorator: CallableType, arg_type: CallableType, ) -> CallableType: """Replaces revealed argument types by mypy with types from decorated.""" return decorator.copy_modified( arg_types=arg_type.arg_types, arg_kinds=arg_type.arg_kinds, arg_names=arg_type.arg_names, variables=arg_type.variables, is_ellipsis_args=arg_type.is_ellipsis_args, )