让mypy警告有关不同类型变量的相等性检查

时间:2018-09-01 05:48:16

标签: python-3.x types static-typing mypy

mypy --strict允许以下最小示例,而不会出现任何错误:

a: int = 1
b: str = '1'

if a == b:
    pass
else:
    pass

是否有可能使它发出关于if a == b:行的错误(或至少是警告)?

1 个答案:

答案 0 :(得分:1)

使用(目前处于实验和未记录状态的)插件API可以实现。

简而言之,将以下文件添加到项目中的某个位置:

from typing import Callable, Optional, Type
from mypy.plugin import MethodContext, Plugin
from mypy.meet import is_overlapping_types

class StrictEqualityPlugin(Plugin):
    def get_method_hook(self, fullname: str) -> Optional[Callable[[MethodContext], Type]]:
        if fullname.endswith('__eq__') or fullname.endswith('__ne__'):
            return strict_check_callback

def strict_check_callback(ctx: MethodContext) -> Type:
    if len(ctx.arg_types) == 1 and len(ctx.arg_types[0]) == 1:
        # Note: Expressions of the form 'base_type == arg_type' get
        # translated into `base_type.__eq__(arg_type)`.
        base_type = ctx.type
        arg_type = ctx.arg_types[0][0]

        # Two types are overlapping if one of the types could potentially be the
        # same as or a subtype of the other.
        #
        # If you want something even stricter, add `from mypy.sametypes import is_same_type`
        # up at the top and call `is_same_type` instead of `is_overlapping_types`.
        if not is_overlapping_types(base_type, arg_type):
            ctx.api.msg.warn(
                "The left and right operands have disjoint types ({} and {})".format(
                    ctx.api.msg.format(base_type),
                    ctx.api.msg.format(arg_type),
                ), 
                ctx.context)
    return ctx.default_return_type

def plugin(mypy_version: str) -> Plugin:
    return StrictEqualityPlugin

我们假设此文件的名称为strict_equality_plugins.py

然后,在项目的顶级中,创建一个mypy.ini文件。该文件至少应包含以下内容:

[mypy]
plugins = ./path/to/strict_equality_plugins.py

然后,在根项目中运行mypy将产生如下错误:

  

foo.py:1:警告:左右操作数的类型不相交(“ int”和“ str”)

免责声明: mypy项目的插件API具有高度的实验性-我不保证该插件在mypy的未来版本中将继续运行而无需修改。