Skip to content

implement autofix for TRIO100 - #149

Merged
jakkdl merged 1 commit into
python-trio:mainfrom
jakkdl:91x_autofix
Mar 14, 2023
Merged

jakkdl merged 1 commit into
python-trio:mainfrom
jakkdl:91x_autofix

Conversation

@jakkdl

@jakkdl jakkdl commented Mar 6, 2023 •

Copy link
Copy Markdown
Member

Before jumping on autofixing TRIO91X I decided to start with the simpler TRIO100.
Turns out I'd forgotten how messy it is to manipulate code and preserve whitespace, comments, lines, etc etc etc 🙃

But I remember solving it in shed, so I can probably crib that from there and write some helper function.
Also remaining is actually changing the file on disk, and adding a flag.

shed/Black/isort is also back to being incredibly annoying, I'll have to figure out a better way of writing autofix files so they don't get fucked with as much as is done currently.

@jakkdl
jakkdl marked this pull request as ready for review March 8, 2023 15:13
@jakkdl

jakkdl commented Mar 8, 2023

Copy link
Copy Markdown
Member Author

It be done!

Very happy with this new autofix testing infrastructure, and I even just now realized that I can exclude autofix files from being shed'd by excluding them in pre-commit ^^

Uses a similar approach to Zac-HD/shed#52 ; and shed would normally codemod away the useless pass statements that are inserted in the autofix files sometimes ... which would cause the autofix tests to fail.
It would be great if I could highly selectively disable pass removal, so shed can check that the autofixed files are otherwise generated with good formatting. fmt: off does nothing.

--generate-autofix maybe deserves a mention in CONTRIBUTING.md - it helps a lot when developing. And ofcourse --autofix should be documented, but it should probably be a comma-separated list anyway.

@jakkdl jakkdl left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments to ease reviewing

Comment thread flake8_trio/runner.py
@@ -100,20 +100,20 @@ def visit(self, node: ast.AST):


class Flake8TrioRunner_cst:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the runner is kind of .. not necessary and clunky, esp as currently __init__ does a bunch of logic itself. Might warrant some restructuring.

Comment thread flake8_trio/runner.py
Comment on lines 111 to 117

def run(self, module: Module) -> Iterable[Error]:
def run(self) -> Iterable[Error]:
if not self.visitors:
return
wrapper = cst.MetadataWrapper(module)
for v in self.visitors:
_ = wrapper.visit(v)
self.module = cst.MetadataWrapper(self.module).visit(v)
yield from self.state.problems

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now saves and updates self.module after visiting.


with trio.move_on_after(10): # error: 5, "trio", "move_on_after"
pass
...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaced pass with ellipsis partly in attempts to avoid shed headaches, but means you can see a difference with ellipsis's transferred over, vs injected passs, in the autofix file.

@@ -0,0 +1,84 @@
# type: ignore

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's not a ton to see here ("trio100_simple_autofix.py" is easier to read), but if you want to review it you should view this and tests/eval_files/trio100.py with a difftool of your choice.

Comment on lines +39 to +50
# extreme case I'm not gonna care about, i.e. one item in the with, but it's multiline.
# Only these leading comments, and the last one, are kept, the rest are lost.
with ( # a
# b
# c
trio.move_on_after( # error: 4, "trio", "move_on_after"
# e
9999999999999999999999999999999999999999999999999999999 # f
# g
) # h
# i
): # this comment is kept
...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can maybe detect this and abort the autofix, rather than eating the comments. But I'm not sure if this happens ever? Maybe if you're passing a lot of parameters to one of fail_after/fail_at/move_on_after/CancelScope so it's gotten split across lines by Black.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, comments are now preserved.

Comment on lines +74 to +77
monkeypatch.chdir(tmp_path)
monkeypatch.setattr(
sys, "argv", [tmp_path / "flake8_trio", "--autofix", "./example.py"]
)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might deserve a helper function, and/or helper fixture

Comment thread tests/test_flake8_trio.py Outdated
Comment on lines +103 to +104
def test_assure_all_autofix_files_used():
assert set(autofix_files.keys()) - checked_autofix == set()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one is a minor pain since I usually develop locally with --failed-first, but didn't see any simple way of forcing this to be run late without installing pytest plugins (and that might still get overridden by --failed-first). But should help the occasional messed up file management by making sure all files in autofixed_files are used.
(although ig that could be done by static analysis of directory contents....)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, now statically checking the contents of the file lists.

@jakkdl
jakkdl force-pushed the 91x_autofix branch 2 times, most recently from 7b54bf6 to 522c1db Compare March 9, 2023 12:05
Comment thread tox.ini Resolved
Comment thread flake8_trio/visitors/helpers.py Resolved
@jakkdl

jakkdl commented Mar 11, 2023

Copy link
Copy Markdown
Member Author

I realize now I added this comment in #124

just remove the context, unless there's other warnings about the content of the context.

that's ... really really hard to implement properly - at least until everything is converted to libcst. So that will have to wait for a later PR, if it turns out to actually be of use. I was probably mainly thinking of missing awaits - but if I can fix trio typing so type checkers can warn on async function calls not being awaited that should be a non-issue.

@jakkdl jakkdl mentioned this pull request Mar 11, 2023
11 of 63 tasks

@Zac-HD Zac-HD left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks good to me! Rebase on master and then merge?

Comment on lines 58 to +62
for res in self.node_dict[original_node]:
self.error(res.node, res.base, res.function)
# if: autofixing is enabled for this code
# then: remove the with and pop out it's body

if self.options.autofix and len(updated_node.items) == 1:
return flatten_preserving_comments(updated_node)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that we don't actually emit the error for autofixed code?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This currently always does, I'll introduce ways of configuring that soon :)

@jakkdl
jakkdl merged commit 76f5363 into python-trio:main Mar 14, 2023
@jakkdl
jakkdl deleted the 91x_autofix branch March 14, 2023 10:40
@jakkdl

jakkdl commented Mar 14, 2023 •

Copy link
Copy Markdown
Member Author

merged! 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants