-
-
Notifications
You must be signed in to change notification settings - Fork 200
Fold nested context managers. #1012
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
base: main
Are you sure you want to change the base?
Conversation
Python 3.10 allows for context managers to be grouped in the same was a
imports. Previous versions only worked with a hack:
with (foo as _, bar as _):
body
This PR implements two fixes:
1. Fold nested with statements.
with foo:
with bar:
body
becomes
with (foo, bar):
body
2. Removes the pre 3.10 hack
with (foo as _, bar as _):
body
becomes
with (foo, bar):
body
README.md
Outdated
| ``` | ||
|
|
||
| ```diff | ||
| - with (foo as _, bar as _): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is in scope. there's no reason to write the original code with nonsense as
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a real work around. I know, I maintain code with it. So I added code to remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is also useless assigning to underscore so also fits in with things like replacing set() with {} or similar which pyupgrade does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no it does not. nobody would write code like that because it doesn't help
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://docs.python.org/3.3/reference/compound_stmts.html#the-with-statement
You needed to use the as syntax to stack them in one with. But since you often did not need the name using _ was a real thing.
The options were:
with foo:
with bar:
or
with foo as f, bar as b:
As you correctly point out, the underscore names are not helpful and with 3.10 there is nothing forcing the programmer to use a name. So it is ok to remove them. Technically.... we could do analysis of the body and following code to see if any of the names are used but that gets ugly fast so I stuck with only removing the useless underscore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disagree but understood. Will post a revised version shortly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case we misunderstood each other.
3.3 to 3.9 did require the use of as to nest context managers. with foo as f, bar as b: was the only way.
3.10 remove the requirement for the as naming. Now you can do with (foo, bar): and it follows the same pattern as import statements.
My original PR removed the now unneeded syntax of the as when migrating to 3.10 when the name was an underscore because that is was semantically safe. Any other name may have actually been used. I am moving this logic to another branch because I still want to upgrade code that I have to maintain elsewhere. I can post it as a separate PR for clarity. Or it can remain in a private repo. No worries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no it did not. I just tried it and it works fine without as
the only thing 3.9 added was trailing commas
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, our code was 3.7 at one point. I wonder if this was changed somewhere before 3.9. Because I know it was failing CI or we would not have added the ugly captures. Either way, it is out of the current PR. Folding the nesting is still valuable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I did some digging. Looks like that weird underscore form came from a StackOverflow discovery back in like 3.3 or 3.5 days.... definitely worthless now.
This code below passes 3.9 but the parenthesis form at the end does not parse in 3.8 or older. The as syntax does not help.
Thanks for your patience. I have removed one more mislearned thing from my list.
from contextlib import suppress
try:
with suppress(ValueError) as _, suppress(IndexError) as _:
print("hello 1")
raise ValueError("foo")
except ValueError:
print("Not supressed")
try:
with suppress(ValueError), suppress(IndexError):
print("hello 2")
raise ValueError("foo")
except ValueError:
print("Not supressed")
try:
with (
suppress(ValueError),
suppress(IndexError)
):
print("hello 3")
raise ValueError("foo")
except ValueError:
print("Not supressed")
Also, fix bug with deeper nestings.
|
PR updated as requested. In doing so I found a case I had fixed and then somehow missed during subsequent debugging. |
|
I would appreciate insight into why the 3.9 code coverage is failing. It passes for 3.10. |
Drop second change.
| def flatten(xs: Iterable[Any]) -> list[Any]: | ||
| return list(itertools.chain.from_iterable(xs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not at all acceptable or typesafe
|
|
||
|
|
||
| def _expand_item(indent: int, item: ast.AST) -> str: | ||
| return '{}{}'.format(' ' * indent, ast.unparse(item)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ast.unparse does not roundtrip so it is not usable or acceptable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/Instagram/LibCST is finally being maintained again so I guess @shaleh could use this. Alternatively, and likely recommended by @asottile, use his https://github.com/asottile/tokenize-rt
Kelleretoro
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
Context managers can be grouped in the same way as imports.
becomes
Resolves. #872