Skip to content

Commit

Permalink
chore: Update docs for new --ignore-categories changes option, and fi…
Browse files Browse the repository at this point in the history
…x a few small typos and markdown formatting issues, also add tests to mypy path
  • Loading branch information
cfculhane committed Sep 25, 2023
1 parent ccb383c commit 9e33004
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 41 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 = []
```
28 changes: 14 additions & 14 deletions docs/follower.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,32 @@ And whatever happens, be brave. Tinker, experiment, hack, and observe.
When mypy-baseline tells you that you introduced new errors and you need to resolve them, have a look at the very top of the command output, above "total errors". There you see the original output of mypy with filtered out old violations. Each error shown there is something you introduced since the last sync. That's what you need to resolve.

1. Start from going to the named file and line number to see what's the code that caused it.
1. Read the error message. It says exactly what's wrong.
1. If you don't understand the error, google it. Chances are you're not the first one to struggle with it.
1. Use [reveal_type](https://adamj.eu/tech/2021/05/14/python-type-hints-how-to-debug-types-with-reveal-type/) to show the type of a variable. Your IDE may show different types (because it's likely not using mypy for that), so always double-check what exactly mypy sees.
1. If you still can't figure it out, don't hesitate to ask your co-workers. You all can learn something from it.
1. The last resort is to add `# type: ignore[error-code]` to the line that caused the issue. Don't overuse it, though, each error reported by mypy is reported for a reason.
2. Read the error message. It says exactly what's wrong.
3. If you don't understand the error, google it. Chances are you're not the first one to struggle with it.
4. Use [reveal_type](https://adamj.eu/tech/2021/05/14/python-type-hints-how-to-debug-types-with-reveal-type/) to show the type of a variable. Your IDE may show different types (because it's likely not using mypy for that), so always double-check what exactly mypy sees.
5. If you still can't figure it out, don't hesitate to ask your co-workers. You all can learn something from it.
6. The last resort is to add `# type: ignore[error-code]` to the line that caused the issue. Don't overuse it, though, each error reported by mypy is reported for a reason.

## Resolve old errors

1. Run bare-bones mypy without using mypy-baseline, and that will spit out all existing type errors.
1. Run `mypy-baseline top-files`. These are the files that need the most attention. Either they have lots of problems, or there is a small error (like a wrong annotation for a base class method) that causes a cascade of type violations and so fixing it would be a quick win.
1. Don't forget to run `mypy | mypy-baseline sync` when you finish.
2. Run `mypy-baseline top-files`. These are the files that need the most attention. Either they have lots of problems, or there is a small error (like a wrong annotation for a base class method) that causes a cascade of type violations and so fixing it would be a quick win.
3. Don't forget to run `mypy | mypy-baseline sync` when you finish.

## Resolve suggested errors

If your team uses [mypy-baseline suggest](./suggest.md) on CI, you may get in your MRs suggestions from mypy-baseline on what errors to resolve.

1. Copy the suggested error.
1. Open the baseline file mentioned in the comment (`mypy-baseline.txt` by default).
1. Find and remove the suggested error from the file and save the changes.
1. Run `mypy | mypy-baseline filter` and it should show you that error with the correct line number.
1. Go to the reported line of code and solve the issue.
2. Open the baseline file mentioned in the comment (`mypy-baseline.txt` by default).
3. Find and remove the suggested error from the file and save the changes.
4. Run `mypy | mypy-baseline filter` and it should show you that error with the correct line number.
5. Go to the reported line of code and solve the issue.

## Keep mypy-baseline in sync

1. By default, mypy-baseline will fail if there are resolved but unsynced errors. The reason for that is to keep `mypy-baseline.txt` always up-to-date. If you don't do that, it will be hard for others to see what errors their changes resolved. Think about others.
1. If mypy-baseline tells you "your changes resolved existing violations", you need to run `mypy | mypy-baseline sync`. It will actualize `mypy-baseline.txt` for you.
2. If mypy-baseline tells you "your changes resolved existing violations", you need to run `mypy | mypy-baseline sync`. It will actualize `mypy-baseline.txt` for you.

## Deal with merge conflicts

Expand All @@ -47,5 +47,5 @@ The best you can do when you encounter a merge conflict is to re-generate the ba
Mypy and its ecosystem is widely used, battle-tested, and made by smart people. False-positives are possible but rare. When you see a violation reported by mypy, considering it a false-positive and simply ignoring must be your very last option.

1. Check if all you type annotations are correct. For instance, if you assign to a variable a `list`, then assign to the same variable a `tuple`, and mypy complaints about it, consider annotating the variable as a `Sequence` or similar.
1. Some errors might be a sign of a bad design. For instance, mypy requires you to follow [Liskov substitution principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle), and methods violating it will be reported. The best you can do in such cases is to refactor it.
1. Don't be afraid to ask for help your coworkers or online. Some errors might look cryptic for newcomers, and nobody will blame you for not understanding how to fix it right away.
2. Some errors might be a sign of a bad design. For instance, mypy requires you to follow [Liskov substitution principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle), and methods violating it will be reported. The best you can do in such cases is to refactor it.
3. Don't be afraid to ask for help your coworkers or online. Some errors might look cryptic for newcomers, and nobody will blame you for not understanding how to fix it right away.
12 changes: 6 additions & 6 deletions docs/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ mypy-baseline history
Columns:

1. `date` and `time` is when the commit was created (`%cI`).
1. `res` is how many lines there were in the baseline after the commit.
1. `old` is how many lines there were in the baseline before the commit.
1. `fix` is how many lines were removed from the baseline.
1. `new` is how many lines were added into the baseline
1. `commit` is the SHA256 has of the commit (`%H`).
1. `author` is the email of the commit author (`%ae`).
2. `res` is how many lines there were in the baseline after the commit.
3. `old` is how many lines there were in the baseline before the commit.
4. `fix` is how many lines were removed from the baseline.
5. `new` is how many lines were added into the baseline
6. `commit` is the SHA256 has of the commit (`%H`).
7. `author` is the email of the commit author (`%ae`).

![example of the command output](./assets/history.png)
24 changes: 12 additions & 12 deletions docs/leader.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,34 @@ This page provides guides and tips for the person who takes the initiative to in

1. The [Usage](./usage.md) page covers the basic integration. To summarize, you generate the initial baseline with `mypy | mypy-baseline sync`, and then all consequentice runs of `mypy | mypy-baseline filter` will ignore these errors.
If you have something like [Taskfile](https://taskfile.dev/) or [Makefile](https://www.gnu.org/software/make/manual/make.html), it's good to provide tasks for both commands, for your team's convenience.
1. Start with the most friendly and relaxed mypy config. Allow everything that can be allowed. For instance, set `allow_redefinition = true`. That will allow you to focus on the most important errors for now.
1. `mypy-baseline.txt` should be committed into the repository, so it's always the same and up-to-date for everyone in the team.
1. Don't forget to integrate mypy-baseline with CI.
1. And lastly, tell your team about mypy, mypy-baseline, and how to use it. Write some internal documentation, make a tech talk, and support them when they struggle to understand why mypy complaints about something. It's a good idea to make a Slack channel where people can ask their mypy-related questions.
2. Start with the most friendly and relaxed mypy config. Allow everything that can be allowed. For instance, set `allow_redefinition = true`. That will allow you to focus on the most important errors for now.
3. `mypy-baseline.txt` should be committed into the repository, so it's always the same and up-to-date for everyone in the team.
4. Don't forget to integrate mypy-baseline with CI.
5. And lastly, tell your team about mypy, mypy-baseline, and how to use it. Write some internal documentation, make a tech talk, and support them when they struggle to understand why mypy complaints about something. It's a good idea to make a Slack channel where people can ask their mypy-related questions.

## Encourage your team to resolve old errors

The purpose of mypy-baseline not to let you ignore all existing errors in the project, but to let you resolve them gradually, start using mypy right now, and make sure nobody introduces new errors. That's why it's important to bring one day the number of mypy errors to zero. And that should be a team effort.

1. Foster the engineering culture of making things better. Tell them about [the boy scout rule](https://www.oreilly.com/library/view/97-things-every/9780596809515/ch08.html).
1. The colorful statistics mypy-baseline shows at the end of each run are designed to encourage people making these numbers smaller. You can help by posting this stats bi-weekly in Slack, so everyone sees the progress you all make.
1. On review, praise the people who reduced the number of lines in "mypy-baseline.txt".
2. The colorful statistics mypy-baseline shows at the end of each run are designed to encourage people making these numbers smaller. You can help by posting this stats bi-weekly in Slack, so everyone sees the progress you all make.
3. On review, praise the people who reduced the number of lines in "mypy-baseline.txt".

## Review merge requests

1. Praise merge request author for removing lines from `mypy-baseline.txt`.
1. Question them for adding new lines in `mypy-baseline.txt`. There should be no new violations. Don't accumulate tech debt without a very good reason. Resolve all type errors right away whenever possible.
1. Question them adding `# type: ignore`. There (almost) always a way to resolve an error instead of just ignoring it. However, it's not always obvious how. Help them find the way.
1. If you see some mistakes in type annotations, gently tell them how to fix it.
2. Question them for adding new lines in `mypy-baseline.txt`. There should be no new violations. Don't accumulate tech debt without a very good reason. Resolve all type errors right away whenever possible.
3. Question them adding `# type: ignore`. There (almost) always a way to resolve an error instead of just ignoring it. However, it's not always obvious how. Help them find the way.
4. If you see some mistakes in type annotations, gently tell them how to fix it.

## Resolve all type errors in the code

Your ultimate goal is to resolve all errors you have and get rid of mypy-baseline.

1. As mentioned in "Integrate mypy-baseline with the project", start with the most friendly and relaxed mypy config.
1. Try adding some third-party plugins, like [django-stubs](https://github.com/typeddjango/django-stubs). Sometimes, they bring the number of detected violations down, not up. If that the case for your project, use it. If not, don't use them just yet, leave it for later.
1. When you resolve at least 80% of existing errors, make mypy config a bit more strict, and repeat the process. Then make it more strict again.
1. When you're happy with the config, it's time to integrate mypy-plugins and stubs you haven't integrated yet. See [awesome-python-typing](https://github.com/typeddjango/awesome-python-typing) for what is available.
2. Try adding some third-party plugins, like [django-stubs](https://github.com/typeddjango/django-stubs). Sometimes, they bring the number of detected violations down, not up. If that the case for your project, use it. If not, don't use them just yet, leave it for later.
3. When you resolve at least 80% of existing errors, make mypy config a bit more strict, and repeat the process. Then make it more strict again.
4. When you're happy with the config, it's time to integrate mypy-plugins and stubs you haven't integrated yet. See [awesome-python-typing](https://github.com/typeddjango/awesome-python-typing) for what is available.

## Deal with false-positives

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

0 comments on commit 9e33004

Please sign in to comment.