From ccb383c5e0ca77ef44de7290e1e1264b11ae99f0 Mon Sep 17 00:00:00 2001 From: Chris Culhane Date: Mon, 25 Sep 2023 17:32:15 +1000 Subject: [PATCH 1/2] feat: Add --ignore-categories option to ignore whole categories of mypy errors --- mypy_baseline/_config.py | 14 ++++++++++++-- mypy_baseline/commands/_filter.py | 2 ++ mypy_baseline/commands/_sync.py | 2 ++ tests/test_commands/test_filter.py | 22 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/mypy_baseline/_config.py b/mypy_baseline/_config.py index ef403d3..8da227c 100644 --- a/mypy_baseline/_config.py +++ b/mypy_baseline/_config.py @@ -20,7 +20,7 @@ try: import tomllib as tomli # type: ignore except ImportError: - tomli = None # type: ignore[assignment] + tomli = None # type: ignore[assignment] @dataclasses.dataclass @@ -32,6 +32,7 @@ class Config: hide_stats: bool = False no_colors: bool = bool(os.environ.get('NO_COLOR')) ignore: list[str] = dataclasses.field(default_factory=list) + ignore_categories: list[str] = dataclasses.field(default_factory=list) default_branch: str = '' @classmethod @@ -77,7 +78,11 @@ def init_parser(self, parser: ArgumentParser) -> None: ) add( '--ignore', nargs='*', - help='regexes for messages to ignore.', + help='regexes for messages to ignore, e.g. ".*Enum.*"', + ) + add( + '--ignore-categories', nargs='*', + help='categories of mypy errors to ignore, e.g. "note" or "call-arg"', ) add( '--default-branch', @@ -131,3 +136,8 @@ def is_ignored(self, msg: str) -> bool: """Check if the message matches any ignore pattern from the config. """ return any(rex.fullmatch(msg) for rex in self._ignore_regexes) + + def is_ignored_category(self, category: str) -> bool: + """Check if the category matches any ignore pattern from the config. + """ + return category in self.ignore_categories diff --git a/mypy_baseline/commands/_filter.py b/mypy_baseline/commands/_filter.py index 3852949..6925235 100644 --- a/mypy_baseline/commands/_filter.py +++ b/mypy_baseline/commands/_filter.py @@ -27,6 +27,8 @@ def run(self) -> int: continue if self.config.is_ignored(error.message): continue + if self.config.is_ignored_category(error.category): + continue clean_line = error.get_clean_line(self.config) try: baseline.remove(clean_line) diff --git a/mypy_baseline/commands/_sync.py b/mypy_baseline/commands/_sync.py index 0b3357e..50e911a 100644 --- a/mypy_baseline/commands/_sync.py +++ b/mypy_baseline/commands/_sync.py @@ -23,6 +23,8 @@ def run(self) -> int: continue if self.config.is_ignored(error.message): continue + if self.config.is_ignored_category(error.category): + continue clean_line = error.get_clean_line(self.config) new_baseline.append(clean_line) diff --git a/tests/test_commands/test_filter.py b/tests/test_commands/test_filter.py index 03fc0be..59f4cc2 100644 --- a/tests/test_commands/test_filter.py +++ b/tests/test_commands/test_filter.py @@ -31,6 +31,28 @@ def test_filter(): assert 'Your changes introduced' in actual +def test_filter__ignore_category(): + stdin = StringIO() + stdin.write(LINE_WITH_NOTE) + stdin.seek(0) + stdout = StringIO() + code = main(['filter', '--ignore-categories', 'note'], stdin, stdout) + assert code == 0 + actual = stdout.getvalue() + assert actual == '' + + +def test_filter__ignore(): + stdin = StringIO() + stdin.write(LINE3) + stdin.seek(0) + stdout = StringIO() + code = main(['filter', '--ignore', '.*Enum.*'], stdin, stdout) + assert code == 0 + actual = stdout.getvalue() + assert actual == '' + + def test_filter_notebook(): stdin = StringIO() stdin.write(NOTEBOOK_LINE1) From c627d40b31cee3cf9f6bc8738c8eca052adf9605 Mon Sep 17 00:00:00 2001 From: Chris Culhane Date: Mon, 25 Sep 2023 17:35:59 +1000 Subject: [PATCH 2/2] chore: Update docs for new --ignore-categories changes option, and fix a few small typos and markdown formatting issues, also add tests to mypy path --- README.md | 4 ++-- docs/config.md | 14 ++++++++------ pyproject.toml | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6b3a5c9..18a8c77 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # mypy-baseline -A CLI tool for painless integration of mypy with an existing Python project. When you run it for the first time, it will remember all type errors that you already have in the project (generate "baseline"). All consequentive runs will ignore these errors and report only ones that you introduced after that. +A CLI tool for painless integration of mypy with an existing Python project. When you run it for the first time, it will remember all type errors that you already have in the project (generate "baseline"). All consecutive runs will ignore these errors and report only ones that you introduced after that. Additionally, the tool will show you what progress you made since the last baseline, to encourage your team to resolve mypy errors: @@ -17,7 +17,7 @@ Features: + Baseline is carefully crafted to avoid merge conflicts. + Baseline is human-readable, and diffs are informative. The reviewers of your PR will know exactly what errors you resolve and what errors you introduced. + Track the progress you make with git-based history of changes and burndown chart of resolved type violations. -+ Ignore speicific error messages (using regular expressions), so that buggy mypy plugins don't bother you with false-positives. ++ Ignore specific error messages (using regular expressions) and error categories, so that buggy mypy plugins don't bother you with false-positives. ## Installation diff --git a/docs/config.md b/docs/config.md index e14b9b0..94f14a8 100644 --- a/docs/config.md +++ b/docs/config.md @@ -2,20 +2,22 @@ The tool has a number of CLI flags to configure the behavior of `filter`. The default value for each flag can be specified in `pyproject.toml`. There are all the configuration options and their defaults: -```python +```toml [tool.mypy-baseline] # --baseline-path: the file where the baseline should be stored baseline_path = "mypy-baseline.txt" # --depth: cut path names longer than that many directories deep depth = 40 # --allow-unsynced: do not fail for unsynced resolved errors -allow_unsynced = False +allow_unsynced = false # --preserve-position: do not remove error position from the baseline -preserve_position = False +preserve_position = false # --hide-stats: do not show stats and messages at the end -hide_stats = False +hide_stats = false # --no-colors: do not use colors in stats -no_colors = False -# --ignore: regexes for error messages to ignore +no_colors = false +# --ignore: regexes for error messages to ignore, e.g. ".*Enum.*" ignore = [] +# --ignore-categories: categories of mypy errors to ignore, e.g. "note" or "call-arg" +ignore_categories = [] ``` diff --git a/pyproject.toml b/pyproject.toml index 7892f1c..bdc47ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,7 @@ Source = "https://github.com/orsinium-labs/mypy-baseline" mypy-baseline = "mypy_baseline:entrypoint" [tool.mypy] -files = ["mypy_baseline"] +files = ["mypy_baseline", "tests"] python_version = 3.8 ignore_missing_imports = true # follow_imports = "silent"