Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement autofix for TRIO100 #149

Merged
merged 1 commit into from
Mar 14, 2023
Merged

Conversation

jakkdl
Copy link
Member

@jakkdl jakkdl commented Mar 6, 2023

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
Copy link
Member Author

jakkdl commented Mar 8, 2023

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.

Copy link
Member Author

@jakkdl jakkdl left a comment

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

@@ -100,20 +100,20 @@ def visit(self, node: ast.AST):


class Flake8TrioRunner_cst:
Copy link
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 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
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.

pass
...
Copy link
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
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
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
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
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 on lines 103 to 104
def test_assure_all_autofix_files_used():
assert set(autofix_files.keys()) - checked_autofix == set()
Copy link
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
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
tox.ini Outdated Show resolved Hide resolved
flake8_trio/visitors/helpers.py Show resolved Hide resolved
@jakkdl
Copy link
Member Author

jakkdl commented Mar 11, 2023

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
63 tasks
Copy link
Member

@Zac-HD Zac-HD left a comment

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
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
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
Copy link
Member Author

jakkdl commented Mar 14, 2023

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