mypy で MethodType を用いる時に incompatible な代入をエラーとして検出したい
import types
from typing import Callable, Any
class Foo:
def __init__(self, f: Callable[[Any, str], str] = lambda this, x: x) -> None:
# エラーにならない!
self.iden: Callable[[str], int] = types.MethodType(f, self)
i: int
foo = Foo()
i = foo.iden("a") # pylint: disable=not-callable
print(i)
既存のクラス階層に対して、テンプレートメソッドのようなことをやりたくなり、クラス階層の整合性を考えた結果、クラスを継承しながらオーバーライドする形式ではなく、上記のように、テンプレートメソッドをコンストラクタの引数にとる形式にするのが良いであろう、という結論に達しました。(このクラスはすでにいろいろなクラスで継承されていて、それらすべての derived クラスに対してテンプレートメソッドをオーバーライドするクラスを定義するのは辛い)
上記は、今回の問題を再現するために単純化したコードです。このコードは、コードとして実行すれば、問題なく実行され (コードとしては正しい) 、また mypy の検査も pass するのですが、その type annotation は間違っています。というのも、 Foo
のコンストラクタの第一引数である f
は、 (Any, str) => str
というシグネチャを持っているにも関わらず、コンストラクタの初期化において (Foo, str) => int
というシグネチャを持つフィールドに代入されているからです。そして、これはたとえばグローバルの i
変数の型を str
にするとエラーになることから、この間違った型宣言によって mypy の推論は実行されていることが確認できます。
質問
mypy において、 MethodType
まわりの型推論において、その不整合を検出することは可能ですか?
環境
- mypy 0.701