16
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[mypy] `--strict` で有効にならないオプションまとめ

Last updated at Posted at 2020-05-02

今まで適当に mypy --strict を使ってきたが,本当にstrictなのか気になったので,何か有効になっていないオプションで大事なものがないか調べることにしました.

以下は投稿日時現在で最新のバージョン 0.770 のものです

結論

--strict で有効になっていない警告系のオプションは以下の6つ.

  • --disallow-any-unimported
  • --disallow-any-expr
  • --disallow-any-decorated
  • --disallow-any-explicit
  • --warn-unreachable
  • --warn-incomplete-stub

それぞれのオプションが有効かどうか

まず,mypy --help で表示される警告系のオプションについて --strict で有効になるかどうかを以下にまとめました.

ただし,以下のようにデフォルトでオンになっているオプションは含めていません( mypy --help だとそれぞれを抑制するためのオプションが表示されます).

  • --strict-optional
  • --warn-no-return
  • --disallow-untyped-globals
  • --disallow-redefinition

--strict で有効:✅ / 無効:❌

Config file

option description
--warn-unused-configs Warn about unused '[mypy-]' config sections

Disallow dynamic typing

option description
--disallow-any-unimported Disallow Any types resulting from unfollowed imports
--disallow-any-expr Disallow all expressions that have type Any
--disallow-any-decorated Disallow functions that have Any in their signature after decorator transformation
--disallow-any-explicit Disallow explicit Any in type positions
--disallow-any-generics Disallow usage of generic types that do not specify explicit type parameters
--disallow-subclassing-any Disallow subclassing values of type Any when defining classes

Untyped definitions and calls

option description
--disallow-untyped-calls Disallow calling functions without type annotations from functions with type annotations
--disallow-untyped-defs Disallow defining functions without type annotations or with incomplete type annotations
--disallow-incomplete-defs Disallow defining functions with incomplete type annotations
--check-untyped-defs Type check the interior of functions without type annotations
--disallow-untyped-decorators Disallow decorating typed functions with untyped decorators

None and Optional handling

option description
--no-implicit-optional Don't assume arguments with default values of None are Optional

Configuring warnings

option description
--warn-redundant-casts Warn about casting an expression to its inferred type
--warn-unused-ignores Warn about unneeded # type: ignore comments
--warn-return-any Warn about returning values of type Any from non-Any typed functions
--warn-unreachable Warn about statements or expressions inferred to be unreachable or redundant

Miscellaneous strictness flags

option description
--no-implicit-reexport Treat imports as private unless aliased
--strict-equality Prohibit equality, identity, and container checks for non-overlapping types

Advanced options

option description
--warn-incomplete-stub Warn if missing type annotation in typeshed, only relevant with --disallow-untyped-defs or --disallow-incomplete-defs enabled

有効になっていないオプションについて

--disallow-any-unimported

スタブがないと,外部ライブラリの型は typing.Any のエイリアスになりますが,それを使用していると警告.

sample.py
import numpy as np  # type: ignore

def func() -> np.ndarray:
    return np.array(1)
$ mypy --strict --show-error-code --pretty sample.py
Success: no issues found in 1 source file
$ mypy --disallow-any-unimported --show-error-code --pretty sample.py
sample.py:3: error: Return type becomes "Any" due to an unfollowed import  [no-any-unimported]
    def func() -> np.ndarray:
    ^
Found 1 error in 1 file (checked 1 source file)

以下のように変更するとOK.

- def func() -> np.ndarray:
+ def func() -> t.Any:

Any だらけになるからどうかとも思ったが, np.ndarray も結局のところ錯覚でしかないので結構ありかもしれません.
コメントと割り切って, np.ndarray とか書く場合もあると思うので,そこら辺は個人の判断だと思います.

--disallow-any-expr

typing.Any を含む式に警告.
np.array(1) + np.array(2) とかでアウト.スタブを作らないとほとんど何もできない.

--disallow-any-decorated

デコレータを通したあとの関数が引数or返り値に typing.Any を持っていると警告.

sample.py
from abc import ABC, abstractmethod
from functools import wraps
import typing as t


class A(ABC):
    @abstractmethod
    def func_a(a: t.Any) -> None:
        pass


def deco(f: t.Callable[[int], int]) -> t.Callable[[int], t.Any]:
    @wraps(f)
    def wrapper(a: int) -> t.Any:
        return t.cast(t.Any, f(a))
    
    return wrapper


@deco
def func_b(a: int) -> int:
    return 0
$ mypy --strict --show-error-code --pretty sample.py
Success: no issues found in 1 source file
$ mypy --disallow-any-decorated --show-error-code --pretty sample.py
sample.py:8: error: Type of decorated function contains type "Any" ("Callable[[Any], None]")  [misc]
        def func_a(a: t.Any) -> None:
        ^
sample.py:21: error: Type of decorated function contains type "Any" ("Callable[[int], Any]")  [misc]
    def func_b(a: int) -> int:
    ^
Found 2 errors in 1 file (checked 1 source file)

普通の関数が --disallow-any-explicit 付けない限り,typing.Any を引数等に使ってもよいのに,デコレータだけ特別視する意味がよくわからない(そして, --disallow-any-explicit はできる気がしない).

--disallow-any-explicit

明示的な typing.Any に警告.厳しい.

--warn-unreachable

不達コードに対して警告.

sample.py
def process(x: int) -> None:
    if isinstance(x, int) or x > 7:
        print(str(x) + "bad")
    else:
        print(str(x) + "bad")

https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-warn-unreachable のコードを少し変更した.)

$ mypy --strict --show-error-code --pretty sample.py
Success: no issues found in 1 source file
$ mypy --warn-unreachable --show-error-code --pretty sample.py
sample.py:2: error: Right operand of 'or' is never evaluated  [unreachable]
        if isinstance(x, int) or x > 7:
                                 ^
sample.py:5: error: Statement is unreachable  [unreachable]
            print(str(x) + "bad")
            ^
Found 2 errors in 1 file (checked 1 source file)

あらゆる不達コードを検出できるわけではないが付けて悪いことはなさそう?

--warn-incomplete-stub

スタブに対する警告.そもそも stubgen がうまくいかないのでよくわからない.
ドキュメントに

This flag is mainly intended to be used by people who want contribute to typeshed and would like a convenient way to find gaps and omissions.

って書いてあるから別にいいのかな?

感想

個人的には,--strict に加えて,以下の2つは一考の余地があるかなと思いました.

  • --disallow-any-unimported
  • --warn-unreachable

そもそもmypyを使っているのは単なる惰性なので,Pyright, Pyre, pytype辺りで使いやすいのがあれば乗り換えたい.

雑比較

|ツール名|言語|GitHubリポジトリ|Star数 (2020/5/2 22:41現在)
|---|---|---|---|---
|mypy|Python|https://github.com/python/mypy|8379
|pytype|Python|https://github.com/google/pytype|2629
|Pyre|OCaml|https://github.com/facebook/pyre-check|3334
|Pyright|TypeScript|https://github.com/microsoft/pyright|5107

参考

16
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?