CLI tool for providing a clean slate for mypy usage within a project.
Project description
Mypy Clean Slate
CLI tool for providing a clean slate for mypy usage within a project
Motivation
It can be difficult to get a large project to the point where mypy --strict
can be run on it. Rather than incrementally increasing the severity of mypy,
either overall or per module, mypy_clean_slate
enables one to ignore all
previous errors so that mypy --strict
(or similar) can be used almost
immediately. This enables all code written from that point on to be checked with
mypy --strict
(or whichever flags are preferred), gradually removing the
type: ignore
comments from that point onwards.
Often running mypy_clean_slate
will cover all errors cleanly in a single pass,
but there are cases when not all error output is generated first time, and it
can be necessary to run a couple of times, checking the diffs. Example of this
scenario is given.
By default mypy_clean_slate
works by parsing the output of mypy --strict
and
adding the relevant type: ignore[code]
to each line, though custom flags can
be passed to mypy instead. Only errors from the report are considered, notes are
not handled. Meaning something such as error: Function is missing a type annotation [no-untyped-def]
will have # type: ignore[no-untyped-def]
appended to the end of the line, whereas note: (Skipping most remaining errors due to unresolved imports or missing stubs; fix these first)
will be ignored.
Errors relating to unused ignores (which might occur if code changes after
adding the initial ignore) can also be handled.
Installation
pip install mypy-clean-slate
Usage
usage: mypy_clean_slate [options]
CLI tool for providing a clean slate for mypy usage within a project.
Default expectation is to want to get a project into a state that it
will pass mypy when run with `--strict`, if this isn't the case custom
flags can be passed to mypy via the `--mypy_flags` argument.
options:
-h, --help show this help message and exit
-r, --generate_mypy_error_report
Generate 'mypy_error_report.txt' in the cwd.
-p PATH_TO_CODE, --path_to_code PATH_TO_CODE
Where code is that needs report generating for it.
-a, --add_type_ignore
Add "# type: ignore[<error-code>]" to suppress all raised mypy errors.
--remove_unused Remove unused instances of "# type: ignore[<error-code>]" if raised as an error by mypy.
-o MYPY_REPORT_OUTPUT, --mypy_report_output MYPY_REPORT_OUTPUT
File to save report output to (default is mypy_error_report.txt)
--mypy_flags MYPY_FLAGS
Custom flags to pass to mypy (provide them as a single string, default is to use --strict)
See ./tests/test_mypy_clean_slate.py
for some examples with before/after.
Examples
Simple example
Given a project with only:
➜ simple_example git:(master) ✗ tree
.
`-- simple.py
0 directories, 1 file
Containing:
# simple.py
def f(x):
return x + 1
The report can be generated, and simple.py
updated, using mypy_clean_slate -ra
, resulting in:
def f(x): # type: ignore[no-untyped-def]
return x + 1
And mypy --strict
will now pass.
Project example, using pingouin
Project pingouin
is located at: https://github.com/raphaelvallat/pingouin, and
commit ea8b5605a1776aaa0e89dd5c0e3df4320950fb38
is used for this example.
mypy_clean_slate
needs to be run a couple of times here.
First, generate report and apply type: ignore[<error code>]
mypy_clean_slate -ra
Looking at a subset of git diff
:
(venv) ➜ pingouin git:(master) ✗ git diff | grep 'type' | head
+import sphinx_bootstrap_theme # type: ignore[import]
+from outdated import warn_if_outdated # type: ignore[import]
+import numpy as np # type: ignore[import]
+from scipy.integrate import quad # type: ignore[import]
+ from scipy.special import gamma, betaln, hyp2f1 # type: ignore[import]
+ from mpmath import hyp3f2 # type: ignore[import]
+ from scipy.stats import binom # type: ignore[import]
+import numpy as np # type: ignore[import]
+from scipy.stats import norm # type: ignore[import]
+import numpy as np # type: ignore[import]
Changes are added and committed with message 'mypy_clean_slate first pass'
(commit message used makes no functional difference), and the report re-generated:
mypy_clean_slate -r
Which reports Found 1107 errors in 39 files (checked 42 source files)
. So, re-running mypy_clean_slate
mypy_clean_slate -a
And looking again at the diff:
(venv) ➜ pingouin git:(master) ✗ gd | grep 'type' | head
+latex_elements = { # type: ignore[var-annotated]
+def setup(app): # type: ignore[no-untyped-def]
@@ -27,4 +27,4 @@ from outdated import warn_if_outdated # type: ignore[import]
+set_default_options() # type: ignore[no-untyped-call]
+def _format_bf(bf, precision=3, trim='0'): # type: ignore[no-untyped-def]
if type(bf) == str:
+def bayesfactor_ttest(t, nx, ny=None, paired=False, tail='two-sided', r=.707): # type: ignore[no-untyped-def]
+ def fun(g, t, n, r, df): # type: ignore[no-untyped-def]
+def bayesfactor_pearson(r, n, tail='two-sided', method='ly', kappa=1.): # type: ignore[no-untyped-def]
+ def fun(g, r, n): # type: ignore[no-untyped-def]
Committing these with 'mypy_clean_slate second pass'
, and re-running mypy_clean_slate -r
outputs the following:
(venv) ➜ pingouin git:(master) ✗ cat mypy_error_report.txt
Success: no issues found in 42 source files
Can now rebase / amend commits as necessary, but could now update CI/pre-commit or whatever to use mypy --strict
(or a subset of its flags) going forwards.
Handling of existing comments and pylint
Lines which contain existing comments such as:
def ThisFunction(something): # pylint: disable=invalid-name
return f"this is {something}"
Will be updated to:
def ThisFunction(something): # type: ignore[no-untyped-def] # pylint: disable=invalid-name
return f"this is {something}"
As the type:
comment needs to precede pylints.
Issues
Generating report
The report generation is pretty straightforward, mypy . --strict --show-error-codes
, so might not be worth having as part of this script. The user can generate the report to a text file and just pass the path to that as an argument.
Handling -> None
Report output for functions which don't return is pretty consistent, so these could be automated if considered worth it.
Integration with other tooling
I've tried to consider pylint
comments, but no doubt there are many other arguments for different tools which aren't taken into consideration.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file mypy_clean_slate-0.3.4.tar.gz
.
File metadata
- Download URL: mypy_clean_slate-0.3.4.tar.gz
- Upload date:
- Size: 9.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.1 CPython/3.10.12 Linux/5.15.0-97-generic
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8dfb199e583afbe730b84d54cccba6a3d435d299bf83e8d8dab4eb0bf2922476 |
|
MD5 | ada6f907f8e725cbcde27bfcd60cd273 |
|
BLAKE2b-256 | ed8b8abcd40fa3b03d4d331b5e91793ad9445f2b08aaa883f110c1f10468931e |
File details
Details for the file mypy_clean_slate-0.3.4-py3-none-any.whl
.
File metadata
- Download URL: mypy_clean_slate-0.3.4-py3-none-any.whl
- Upload date:
- Size: 9.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.1 CPython/3.10.12 Linux/5.15.0-97-generic
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 045f1b4bb82623b59086eafa888fc67c7c93b9ef83b21439d87926cc5906e70b |
|
MD5 | 23d7d53825733675ceb17b95482f7865 |
|
BLAKE2b-256 | c2b5f60ef0786f0fe66bdd93c2b96c21b10d47b5895ac20e871a216b172c10da |