これは、なにをしたくて書いたもの?
Pythonでソースコードを書く時にはできる限り型をつけていこうかなと思っているのですが、mypyについてはとりあえず
--disallow-untyped-defs
をつけて型指定がない場合にエラーにしているくらいだったので、もう少しちゃんと設定というかどういうチェックを
するべきか見ておこうかなと思いまして。
mypyの設定
説明としてはこちらです。
The mypy configuration file - mypy 1.14.0 documentation
mypyの設定は以下から読み込まれます。
- ./mypy.ini
- ./.mypy.ini
- ./pyproject.toml
- ./setup.cfg
- $XDG_CONFIG_HOME/mypy/config
- ~/.config/mypy/config
- ~/.mypy.ini
あとはコマンドライン引数ですね。
The mypy command line - mypy 1.14.0 documentation
環境
今回の環境はこちら。
$ python3 --version Python 3.12.3 $ pip3 --version pip 24.0 from /usr/lib/python3/dist-packages/pip (python 3.12)
mypyの設定を見る
ひとまずmypyをインストールします。
$ pip3 install mypy $ mypy --version mypy 1.14.0 (compiled: yes)
ヘルプを見てみます。
$ mypy --help
今回は型チェックに関する内容が見たいので、見るべきはこのあたりですね。
Disallow dynamic typing: Disallow the use of the dynamic 'Any' type under certain conditions. --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 (inverse: --allow-any-generics) --disallow-any-unimported Disallow Any types resulting from unfollowed imports (inverse: --allow-any-unimported) --disallow-subclassing-any Disallow subclassing values of type 'Any' when defining classes (inverse: --allow-subclassing-any) Untyped definitions and calls: Configure how untyped definitions and calls are handled. Note: by default, mypy ignores any untyped function definitions and assumes any calls to such functions have a return type of 'Any'. --disallow-untyped-calls Disallow calling functions without type annotations from functions with type annotations (inverse: --allow-untyped-calls) --untyped-calls-exclude MODULE Disable --disallow-untyped-calls for functions/methods coming from specific package, module, or class --disallow-untyped-defs Disallow defining functions without type annotations or with incomplete type annotations (inverse: --allow-untyped-defs) --disallow-incomplete-defs Disallow defining functions with incomplete type annotations (while still allowing entirely unannotated definitions) (inverse: --allow- incomplete-defs) --check-untyped-defs Type check the interior of functions without type annotations (inverse: --no-check-untyped-defs) --disallow-untyped-decorators Disallow decorating typed functions with untyped decorators (inverse: --allow-untyped-decorators) None and Optional handling: Adjust how values of type 'None' are handled. For more context on how mypy handles values of type 'None', see: https://mypy.readthedocs.io/en/stable/kinds_of_types.html#no-strict-optional --implicit-optional Assume arguments with default values of None are Optional (inverse: --no-implicit-optional) --no-strict-optional Disable strict Optional checks (inverse: --strict-optional) Configuring warnings: Detect code that is sound but redundant or problematic. --warn-redundant-casts Warn about casting an expression to its inferred type (inverse: --no-warn-redundant-casts) --warn-unused-ignores Warn about unneeded '# type: ignore' comments (inverse: --no-warn-unused-ignores) --no-warn-no-return Do not warn about functions that end without returning (inverse: --warn-no-return) --warn-return-any Warn about returning values of type Any from non-Any typed functions (inverse: --no-warn-return-any) --warn-unreachable Warn about statements or expressions inferred to be unreachable (inverse: --no-warn-unreachable) --report-deprecated-as-note Report importing or using deprecated features as notes instead of errors (inverse: --no-report-deprecated-as-note) Miscellaneous strictness flags: --allow-untyped-globals Suppress toplevel errors caused by missing annotations (inverse: --disallow-untyped-globals) --allow-redefinition Allow unconditional variable redefinition with a new type (inverse: --disallow-redefinition) --no-implicit-reexport Treat imports as private unless aliased (inverse: --implicit-reexport) --strict-equality Prohibit equality, identity, and container checks for non-overlapping types (inverse: --no-strict-equality) --extra-checks Enable additional checks that are technically correct but may be impractical in real code. For example, this prohibits partial overlap in TypedDict updates, and makes arguments prepended via Concatenate positional-only (inverse: --no-extra-checks) --strict Strict mode; enables the following flags: --warn-unused-configs, --disallow-any-generics, --disallow-subclassing-any, --disallow-untyped- calls, --disallow-untyped-defs, --disallow-incomplete-defs, --check-untyped-defs, --disallow-untyped-decorators, --warn-redundant-casts, --warn-unused-ignores, --warn-return-any, --no-implicit-reexport, --strict-equality, --extra-checks --disable-error-code NAME Disable a specific error code --enable-error-code NAME Enable a specific error code Configuring error messages: Adjust the amount of detail shown in error messages. --show-error-context Precede errors with "note:" messages explaining context (inverse: --hide-error-context) --show-column-numbers Show column numbers in error messages (inverse: --hide-column-numbers) --show-error-end Show end line/end column numbers in error messages. This implies --show-column-numbers (inverse: --hide-error-end) --hide-error-codes Hide error codes in error messages (inverse: --show-error-codes) --show-error-code-links Show links to error code documentation (inverse: --hide-error-code-links) --pretty Use visually nicer output in error messages: Use soft word wrap, show source code snippets, and show error location markers (inverse: --no-pretty) --no-color-output Do not colorize error messages (inverse: --color-output) --no-error-summary Do not show error stats summary (inverse: --error-summary) --show-absolute-path Show absolute paths to files (inverse: --hide-absolute-path)
ちなみに、設定ファイルに書く時には_
区切りになるようです。
デフォルト値はドキュメントを見ないとわからないようですね。
The mypy configuration file - mypy 1.14.0 documentation
ただ、説明自体はコマンドライン引数の方が読んだ方がよいみたいです。
The mypy command line - mypy 1.14.0 documentation
--strict
はドキュメントを見ても「ヘルプを見ること」としか書かれていないので、実際に見てみるとこんな感じでした。
--strict Strict mode; enables the following flags: --warn-unused-configs, --disallow-any-generics, --disallow-subclassing-any, --disallow-untyped- calls, --disallow-untyped-defs, --disallow-incomplete-defs, --check-untyped-defs, --disallow-untyped-decorators, --warn-redundant-casts, --warn-unused-ignores, --warn-return-any, --no-implicit-reexport, --strict-equality, --extra-checks
Enable all optional error checking flags. You can see the list of flags enabled by strict mode in the full mypy --help output.
mypy 1.14.0では以下のフラグが有効になるようです。
- --warn-unused-configs
- --disallow-any-generics
- --disallow-subclassing-any
- --disallow-untyped-calls
- --disallow-untyped-defs
- --disallow-incomplete-defs
- --check-untyped-defs
- --disallow-untyped-decorators
- --warn-redundant-casts
- --warn-unused-ignores
- --warn-return-any
- --no-implicit-reexport
- --strict-equality
- --extra-checks
OSSプロジェクトではどういう設定をしているんでしょう?とFastAPIを見たところ、全体としてはstrict
のみtrue
にしてあり、
ディレクトリによってはオーバーライドしているものもある、という感じでした。
https://github.com/fastapi/fastapi/blob/0.115.6/pyproject.toml#L123-L140
カテゴリー | 項目 | 説明 | デフォルト値 | strictに含まれているか? |
---|---|---|---|---|
動的型付けを許可しない | disallow_any_unimported | フォローされていないインポートから取得する型(Any )の使用を禁止する |
False | |
disallow_any_expr | Any を使う式を許可しない |
False | ||
disallow_any_decorated | デコーレーターによる変換後の関数シグネチャにAny が含まれることを禁止する |
False | ||
disallow_any_explicit | Any の明示的な使用を禁止する |
False | ||
disallow_any_generics | 明示的な型パラメーターを指定しないジェネリック型の使用を禁止する | False | ○ | |
disallow_subclassing_any | Any のサブクラス化を禁止する |
False | ○ | |
型のない定義と呼び出し | disallow_untyped_calls | 型アノテーションを持つ関数を型アノテーションなしでの呼び出しを禁止する | False | ○ |
untyped_calls_exclude | 特定のパッケージ、モジュール、またはクラスで定義された関数を disallow_untyped_calls アクションから選択して除外する | |||
disallow_untyped_defs | 型アノテーションのない関数定義または不完全な型アノテーションのある関数定義を禁止する | False | ○ | |
disallow_incomplete_defs | 部分的に型アノテーションが付与された関数定義を禁止する。完全に型アノテーションがない場合は許容する | False | ○ | |
check_untyped_defs | False | ○ | ||
disallow_untyped_decorators | 型アノテーションつきの関数を型アノテーションなしのデコレーターで装飾することを禁止する | False | ○ | |
None とOptional の扱い |
implicit_optional | デフォルト値を持つパラメーターを暗黙的に T | None として扱う | False | |
strict_optional | Optional の型とNone 値のチェックを無効にする。つまり、None はすべての型と互換性があるものとして扱う |
True | ||
警告の設定 | warn_redundant_casts | 冗長なキャストを使用すると警告する | False | ○ |
warn_unused_ignores | 不要な# type: ignore コメントがあると警告する |
False | ○ | |
warn_no_return | 関数からreturn 文が欠落している場合に警告する。例外は関数の戻り値の肩がNone またはAny 、関数本体が空で抽象メソッドとしてマークされているか、プロトコルクラス内またはスタブファイル内にある、例外をスローするなどのreturn に制御が移らない場合 |
True | ||
warn_return_any | Any 以外の型を戻り値として定義している関数からAny を返そうとすると警告する |
False | ○ | |
warn_unreachable | 到達不能または冗長であるコードを検出すると警告する | False | ||
エラーの抑制 | ignore_errors | 致命的なエラー以外を無視する | False | |
その他の厳密性フラグ | allow_untyped_globals | 型指定のないグローバル変数を許容する | False | |
allow_redefinition | 変数を別の型で再定義することを許容する | False | ||
local_partial_types | ローカル変数に対する部分型(None を部分型として扱うこと)を禁止する |
False(mypy daemonでは暗黙的にTrueになる) | ||
disable_error_code | 指定したエラーコードを無効にする。複数指定する場合はカンマで区切る | |||
enable_error_code | 指定したエラーコードを有効にする。複数指定する場合はカンマで区切る | |||
extra_checks | 技術的には正しいが実用的なコードでない可能性があるものに対して、追加のチェックを行う | False | ○ | |
implicit_reexport | モジュールにインポートしたものを、暗黙的にエクスポートする | True | ※ no_implicit_reexport が有効になる |
|
strict_concatenate | ?(extra_checksのこと?) | False | ||
strict_equality | 互換性のない型の間での等価チェック、一意性チェック、コンテナチェックを禁止する | False | ○ | |
strict | 特定のチェックが有効になる(この表の右端を参照) | False | ||
エラーメッセージの設定 | show_error_context | 各エラーの先頭に関連するコンテキストを付与する | False | |
show_column_numbers | エラーメッセージに列番号を表示する | False | ||
show_error_code_links | 対応するエラーコードへのドキュメントのリンクを表示する | False | ||
hide_error_codes | エラーメッセージからエラーコードを非表示にする | False | ||
pretty | エラーメッセージを見やすくする | False | ||
color_output | エラーメッセージを色付きで表示する | True | ||
error_summary | エラーメッセージの後に短いサマリーを表示する | True | ||
show_absolute_path | ファイルの絶対パスを表示する | False | ||
force_uppercase_builtins | Python 3.9以降であってもエラーメッセージの表示では大文字を強制する | False | ||
force_union_syntax | Python 3.10以降であってもエラーメッセージ内の共用型には | の代わりにUnion[] やOptional[] を使用する |
False | ||
その他 | warn_unused_configs | mypyの呼び出し時に処理されるファイルと一致しない、設定ファイル内のモジュールごとのセクションに対して警告する | False | ○ |
その他は型チェックには関係しなさそうでしたが、strict
で有効になるwarn_unused_configs
のみ載せました。
こう見ていると、最低限strict
を有効にすればよいのでは?という気もしますね。
mypy.iniを設定してみる
というわけで、ここまでの内容を元にmypyの設定ファイルであるmypy.ini
を作成してみます。
まずはこんな感じにしてみようかなと思います。今回はデフォルト値のままでいいものについては省略しました。
mypy.ini
[mypy] strict = True disallow_any_unimported = True disallow_any_expr = True disallow_any_explicit = True warn_unreachable = True pretty = True
uvでpyproject.toml
に書く場合はこうでしょうか。
[tool.mypy] strict = true disallow_any_unimported = true disallow_any_expr = true disallow_any_explicit = true warn_unreachable = true pretty = true
使っていて微妙に思ったら、適宜見直していこうと思います。
ところで、設定する項目名を間違えると警告してくれるのがいいですね。
こんな感じで。
mypy.ini: [mypy]: Unrecognized option: hoge = True
おわりに
mypyの設定について調べてみました。
せっかくなのでざっくりまとめつつという感じで進めてみましたが、だいたい雰囲気はわかった感じです。
ちゃんと使っていこうと思います。