Skip to content

Commit

Permalink
Merge pull request #19 from cfculhane/feat/ignore-category
Browse files Browse the repository at this point in the history
feat: Add --ignore-categories option to ignore whole categories of mypy errors
  • Loading branch information
orsinium authored Sep 25, 2023
2 parents 4485b2b + c627d40 commit 0968208
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 11 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -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:

Expand All @@ -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

Expand Down
14 changes: 8 additions & 6 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
```
14 changes: 12 additions & 2 deletions mypy_baseline/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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
2 changes: 2 additions & 0 deletions mypy_baseline/commands/_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions mypy_baseline/commands/_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
22 changes: 22 additions & 0 deletions tests/test_commands/test_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 0968208

Please sign in to comment.