代码之家  ›  专栏  ›  技术社区  ›  Tobias Hermann

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

  •  0
  • Tobias Hermann  · 技术社区  · 7 年前

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

    a: int = 1
    b: str = '1'
    
    if a == b:
        pass
    else:
        pass
    

    if a == b:

    1 回复  |  直到 7 年前
        1
  •  1
  •   Michael0x2a    6 年前

    编辑: 下面我的原始答案描述了如何通过编写自定义mypy插件来实现这一点。

    然而, as of mypy 0.700 ,现在可以通过 --strict-equality --strict 旗帜。

    例如,在上面的原始程序上运行mypy将产生以下错误:

    test.py:4: error: Non-overlapping equality check (left operand type: "int", right operand type: "str")
    

    您可以在页面底部找到有关此标志的更多详细信息 Miscellaneous strictness options mypy命令行标志doc的部分。


    这是可能的使用(目前实验和未记录)插件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将产生如下错误:

    免责声明: