`--exclude` regular expression leading "/" does not match in current directory
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 20.6k
- フォーク
- 3.3k
- PR マージ指標
- PR 指標を取得中
説明
This might be a documentation error, but I expect that the documentation does reflect intended behavior so I am reporting it here.
Bug Report
The documentation includes the following example for --exclude
Similarly, you can ignore discovering directories with a given name by e.g. --exclude /build/ or those matching a subpath with --exclude /project/vendor/.
The implicature from the documentation (and just typical user expectation) is that --exclude /build/ would exclude ./build/b.py and ./some_dir/build/e.py, while all others would be checked. However ./build/b.py is not excluded. But /build/ and /project/ will not match (and therefore will not exclude) a build or project directory directly in the current directory.
Some examples will better illustrate.
To Reproduce
I created a directory structure
% tree .
.
├── a.py
├── build
│ └── b.py
├── extra_build
│ └── d.py
└── some_dir
├── build
│ └── e.py
└── c.py
The Python files are all identical and contain
from typing import TYPE_CHECKING
def main() -> None:
v: str = "a literal string"
if TYPE_CHECKING:
reveal_type(v)
else:
print(f"Not type checking {__file__}")
if __name__ == "__main__":
main()
Then run
mypy --exclude '/build/' --config-file= .
in the directory that contains a.py.
Expected Behavior
a.py:7: note: Revealed type is "builtins.str"
some_dir/c.py:7: note: Revealed type is "builtins.str"
extra_build/d.py:7: note: Revealed type is "builtins.str"
Success: no issues found in 3 source files
That is, I would expect that build/b.py would not be type checked.
Actual Behavior
a.py:7: note: Revealed type is "builtins.str"
some_dir/c.py:7: note: Revealed type is "builtins.str"
extra_build/d.py:7: note: Revealed type is "builtins.str"
build/b.py:7: note: Revealed type is "builtins.str"
Success: no issues found in 4 source files
Note that build/b.py is erroneously type checked.
Your Environment
- Mypy version used: mypy 1.14.1 (compiled: yes)
- Mypy command-line flags: --exclude '/build/' --config-file= .
- Mypy configuration options from
mypy.ini(and other config files): None - Python version used: 3.12.5
- OS: macOS 15.4
- Shell: zsh
Update: Now tested with mypy 1.15.0 and Python 3.13.3. The behavior remains as described above.
Obvious explanation
It appears that when the documentation was written, the expectation was that regular expression would have been tested against "./build/b.py'", which would match as expected. But instead it is being tested against "build/b.py`" which does not match the regular expression
Addition samples show what happens with different expressions
--exclude 'build' correctly matches (excludes) build/b.py, but incorrectly matches (excludes) extra_build/d.py
% mypy --exclude 'build/' --config-file= .
a.py:7: note: Revealed type is "builtins.str"
some_dir/c.py:7: note: Revealed type is "builtins.str"
--exclude '\bbuild/' does match what is expected for the structure I gave,
mypy --exclude '\bbuild/' --config-file= .
a.py:7: note: Revealed type is "builtins.str"
some_dir/c.py:7: note: Revealed type is "builtins.str"
extra_build/d.py:7: note: Revealed type is "builtins.str"
But that would not help if I constructed a subdirectory with a name like foo+build.
Although it definitely would be possible to construct a regular expression that does the right thing, it is going to be far from obvious how to do so, and unless there is some RE magic that I don't know or don't recall, it is not going to be pretty.
I have not looked at the source, but I expect that it will be easier to just prepend the OS specific version of "`./'" to what is being matched.
Meta
I am sure that I am not the first person to wish that we could go back in time and use some other form of file globbing here instead of regular expressions. But we have the history we have.
Also, I do recognize that it is much better and easier to manage exclude patterns in configuration files instead of on the command line, but I did have reason to use the command line, and so I encountered this issue.
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
まず、提供されている mypy 1.15.0 の再現用コードを、--exclude '/build/' を付けて、示されたディレクトリツリーに対して実行し、その後 --exclude のパス照合のエントリーポイントを追跡します。正規表現が適用される前にパスがどのように構築されるかを確認します。完了条件は、先頭にスラッシュのあるパターンによって build/b.py が除外され、他の3つのファイルは引き続きチェックされ、文書化された動作のカバレッジがあることです。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- cli
- issue の種類
- バグ
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 45/100