8000 implement autofix for 91x · python-trio/flake8-async@49166b6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 49166b6

Browse files
committed
implement autofix for 91x
1 parent dc83998 commit 49166b6

File tree

14 files changed

+2338
-46
lines changed

14 files changed

+2338
-46
lines changed

CONTRIBUTING.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ To check that all codes are tested and documented there's a test that error code
3232
## Test generator
3333
Tests are automatically generated for files in the `tests/eval_files/` directory, with the code that it's testing interpreted from the file name. The file extension is split off, if there's a match for for `_py\d*` it strips that off and uses it to determine if there's a minimum python version for which the test should only run.
3434

35+
### autofix files
36+
Checks that have autofixing can have a file in the `tests/autofix_files` directory matching the filename in `tests/eval_files`. The result of running the checker on the eval file with autofix enabled will then be compared to the content of the autofix file and will print a diff (if `-s` is on) and assert that the content is the same. `--generate-autofix` is added as a pytest flag to ease development, which will print a diff (with `-s`) and overwrite the content of the autofix file. Also see the magic line marker `pass # AUTOFIX_LINE ` below
37+
3538
### `error:`
3639
Lines containing `error:` are parsed as expecting an error of the code matching the file name, with everything on the line after the colon `eval`'d and passed as arguments to `flake8_trio.Error_codes[<error_code>].str_format`. The `globals` argument to `eval` contains a `lineno` variable assigned the current line number, and the `flake8_trio.Statement` namedtuple. The first element after `error:` *must* be an integer containing the column where the error on that line originates.
3740
#### `TRIOxxx:`
@@ -47,6 +50,9 @@ If a file is marked with `# NOTRIO` it will not replace instances of "trio" with
4750
#### `# ANYIO_NO_ERROR`
4851
A file which is marked with this will ignore all `# error` or `# TRIO...` comments when running with anyio. Use when an error is trio-specific and replacing "trio" with "anyio" should silence all errors.
4952

53+
### `pass # AUTOFIX_LINE ...`
54+
Added to an eval file when the autofixed file is expected to insert a line `...` at that position. When autofix tests evaluate the diff the entire line is stripped from the autofixed file, and the leading `pass # AUTOFIX_LINE ` is stripped from the eval_file (leaving only `...`), so while the files will look slightly different when viewed with a difftool the autofix test should see `...` and `...`. Note that you may need to disable black/isort/other for the file.
55+
5056
## Running pytest outside tox
5157
If you don't want to bother with tox to quickly test stuff, you'll need to install the following dependencies:
5258
```

flake8_trio/runner.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@
99
import ast
1010
import re
1111
from dataclasses import dataclass, field
12+
from itertools import chain
1213
from typing import TYPE_CHECKING
1314

1415
import libcst as cst
1516

16-
from .visitors import ERROR_CLASSES, ERROR_CLASSES_CST, utility_visitors
17+
from .visitors import (
18+
ERROR_CLASSES,
19+
ERROR_CLASSES_CST,
20+
utility_visitors,
21+
utility_visitors_cst,
22+
)
1723

1824
if TYPE_CHECKING:
1925
from argparse import Namespace
@@ -104,6 +110,13 @@ def __init__(self, options: Namespace, module: Module):
104110
super().__init__()
105111
self.state = SharedState(options)
106112
self.options = options
113+
114+
# Could possibly enable/disable utility visitors here, if visitors declared
115+
# dependencies
116+
self.utility_visitors: tuple[Flake8TrioVisitor_cst, ...] = tuple(
117+
v(self.state) for v in utility_visitors_cst
118+
)
119+
107120
self.visitors: tuple[Flake8TrioVisitor_cst, ...] = tuple(
108121
v(self.state) for v in ERROR_CLASSES_CST if self.selected(v.error_codes)
109122
)
@@ -112,7 +125,7 @@ def __init__(self, options: Namespace, module: Module):
112125
def run(self) -> Iterable[Error]:
113126
if not self.visitors:
114127
return
115-
for v in self.visitors:
128+
for v in chain(self.utility_visitors, self.visitors):
116129
self.module = cst.MetadataWrapper(self.module).visit(v)
117130
yield from self.state.problems
118131

flake8_trio/visitors/__init__.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,18 @@
1212
if TYPE_CHECKING:
1313
from .flake8triovisitor import Flake8TrioVisitor, Flake8TrioVisitor_cst
1414

15-
__all__ = ["ERROR_CLASSES", "default_disabled_error_codes", "utility_visitors"]
15+
__all__ = [
16+
"ERROR_CLASSES",
17+
"ERROR_CLASSES_CST",
18+
"default_disabled_error_codes",
19+
"utility_visitors",
20+
"utility_visitors_cst",
21+
]
1622
ERROR_CLASSES: set[type[Flake8TrioVisitor]] = set()
1723
ERROR_CLASSES_CST: set[type[Flake8TrioVisitor_cst]] = set()
18-
utility_visitors: set[type[Flake8TrioVisitor]] = set()
1924
default_disabled_error_codes: list[str] = []
25+
utility_visitors: set[type[Flake8TrioVisitor]] = set()
26+
utility_visitors_cst: set[type[Flake8TrioVisitor_cst]] = set()
2027

2128
# Import all visitors so their decorators run, filling the above containers
2229
# This has to be done at the end to avoid circular imports

flake8_trio/visitors/flake8triovisitor.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,13 @@ def error(
227227
*args,
228228
)
229229
)
230+
231+
@property
232+
def library(self) -> tuple[str, ...]:
233+
return self.__state.library if self.__state.library else ("trio",)
234+
235+
# library_str not used in cst yet
236+
237+
def add_library(self, name: str) -> None:
238+
if name not in self.__state.library:
239+
self.__state.library = self.__state.library + (name,)

flake8_trio/visitors/helpers.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
ERROR_CLASSES_CST,
2020
default_disabled_error_codes,
2121
utility_visitors,
22+
utility_visitors_cst,
2223
)
2324

2425
if TYPE_CHECKING:
@@ -58,6 +59,13 @@ def utility_visitor(c: type[T]) -> type[T]:
5859
return c
5960

6061

62+
def utility_visitor_cst(c: type[T_CST]) -> type[T_CST]:
63+
assert not hasattr(c, "error_codes")
64+
c.error_codes = {}
65+
utility_visitors_cst.add(c)
66+
return c
67+
68+
6169
def _get_identifier(node: ast.expr) -> str:
6270
if isinstance(node, ast.Name):
6371
return node.id

0 commit comments

Comments
 (0)
0