| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
@1st1 I'd like to take a further look at this one before we merge it, but
won't have time until Jan 6th or so (just before the final alpha). Does
that timeline work for you?
|
Sorry, something went wrong.
|
The alternative plan would be to merge this version based on the existing
reviews, and if I have any subsequent changes I want to make, I can do that
any time before the first beta. That's probably a better approach, since
it's more resilient against my being otherwise occupied in the first week
of January.
|
Sorry, something went wrong.
Sure, I think this is worth another look so let's wait. Let's just make sure we don't forget about this before the feature freeze. |
Sorry, something went wrong.
There was a problem hiding this comment.
I like the patch overall, but there's one design concern I have, as well as a backwards compatibility concern:
The design question is one @1st1 and I talked about on the issue tracker (see https://bugs.python.org/issue29302#msg288735 and the next couple of comments), and after seeing the code in PR form, I definitely want to go with the more explicit API:
Sorry, something went wrong.
There was a problem hiding this comment.
Folks may be calling stack.push(exit=obj), so we shouldn't gratuitously change parameter names.
Sorry, something went wrong.
There was a problem hiding this comment.
This introduces a dependency I'd prefer to avoid - inspect pulls in a lot of other modules, and contextlib is used frequently enough that we should aim to minimise its dependency tree.
Sorry, something went wrong.
There was a problem hiding this comment.
This comment is oddly placed, and doesn't seem especially accurate - the check is being made against __aexit__, not __aenter__.
More generally, implicitly interleaving synchronous with asynchronous context managers seems dubious to me - while it might be a good idea to allow it, doing it automagically rather than explicitly seems like a recipe for confusion when reading and debugging code.
Sorry, something went wrong.
There was a problem hiding this comment.
If we do decide to allow synchronous context managers in asynchronous exit stacks, I'd suggest wrapping their exit callbacks in an awaitable, so this check can be avoided.
Sorry, something went wrong.
There was a problem hiding this comment.
inspect is also used by _create_exit_wrapper and _create_cb_wrapper.
Sorry, something went wrong.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request. |
Sorry, something went wrong.
|
Couple of thoughts:
with Foo:
async with Bar:
with Ham:
...
|
Sorry, something went wrong.
|
Also, we need to get this merged before Jan 29. @Kentzo if you don't have time to work on this in the next few days I can handle this PR myself. |
Sorry, something went wrong.
|
@1st1 So the differences between AsyncExitStack and ExitStack would be:
I like that, since it means registering synchronous context managers and callbacks stays the same regardless of which kind of stack you're using. A note regarding the method names: the synchronous method names are just push and callback. I think those are slightly problematic, since they're both push operations (making the first one ambiguous), and the latter isn't a verb (which is dubious for a method name). Since push_async and callback_async aren't clear on whether the operation itself is asynchronous, I see value in switching to the more explicit method names before adding the async qualifier: push_async_exit, push_async_callback. |
Sorry, something went wrong.
Right.
Yeah, the API consistency for synchronous CMs is great. To be honest I haven't thought about it until you highlighted it, but now I see it as a requirement!
+1. |
Sorry, something went wrong.
|
Please name the close method aclose, for consistency with async generators. (This will also make AsyncExitStack a trio.abc.AsyncResource so long as all the items in it are themselves AsyncResources. But that's just because AsyncResource was designed to be consistent with async generators :-).) Regarding the bikeshed, I think my preference FWIW is to make both sync and async explicitly marked, so it's e.g. enter_sync_context and enter_async_context, and there is no enter_context. This adds a small amount of hassle in the case where you have an existing ExitStack and then realize you want to mix in some async contexts as well, because you have to update existing calls. But it makes things much less confusing when you start out thinking "hmm, I have some async contexts that I need to put in a stack", so you make an AsyncExitStack and then are confused that AsyncExitStack.enter_context wants a synchronous context. |
Sorry, something went wrong.
|
@njsmith following this way we should add a prefix to all async functions everywhere: aclose(), asend(), arecv() etc. |
Sorry, something went wrong.
|
The semantics around closing things are much more general and subtle than
sending/receiving. Obviously send/recv are inherently semantically blocking
operations, but close() is non-blocking on a regular socket and blocking on
an SSL socket. Plus in general there are just a lot more kinds of things
that get closed so it's useful to have general cross-type conventions here.
You can't use contextlib.closing with an object whose close is async (or
rather, you can if it calls the method 'close', and it will claim to
succeed without doing anything!). You *can* use async_generator.aclosing on
any object with an async close, but it assumes that the method is called
aclose(), because it's not specific to async generators but that is one of
the original use cases. In some cases you might want to provide both a
synchronous close() and an async aclose() on the same object, e.g. if the
object's native close semantics are synchronous, but the way it's used also
needs to match some generic ABC. (Probably it's *better* it you can handle
this via composition – in trio, trio.socket.socket has a synchronous
close() while trio.SocketStream and trio.SocketListener have async aclose()
methods – but sometimes stuff happens.) So personally at least I find it
very useful to have a conventional protocol for async close that doesn't
overlap with the existing convention for sync close.
…On Jan 20, 2018 04:42, "Andrew Svetlov" ***@***.***> wrote:
@njsmith <https://github.com/njsmith> following this way we should add a
prefix to all async functions everywhere: aclose(), asend(), arecv() etc.
The logic is weird, isn't it? I don't see how context manager is related
to generator.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#4790 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAlOaDSFF_kyr6I6me86pr7c6e5W8fUjks5tMd8zgaJpZM4Q85Ru>
.
|
Sorry, something went wrong.
|
@njsmith Good point regarding close() vs aclose() - I'd forgotten that part of PEP 525. Given that, I agree the method on AsyncExitStack should aclose(), and the synchronous close API should just be missing entirely (as with the other synchronous context management methods). I'm not especially worried about folks having to sprinkle extra "async" mentions through their code to get async context managers to work as expected - that's the default language wide. For example, even though you've written stack = contextlib.AsyncExitStack(), you also have to write async with stack: - you can't just write with stack: the way you can with the synchronous version and have Python automatically figure out you must have wanted to use the async variant of the with statement. By contrast, I'm definitely not keen on having the correctness of code like f = stack.enter_context(open(file_of_interest)) depend on whether or not "stack" is a regular exit stack or an asynchronous one. This does mean that stack.push(async_cm_or_exit) and stack.callback(async_callback) may run into the "coroutine never awaited" scenario, but that's why we have the other issue about detecting unawaited coroutines. I'd also be amenable to having a check (potentially __debug__-only) in AsyncContextManager.__aexit__ itself for nominally synchronous callbacks returning awaitables, as that scenario is likely to inadvertently suppress exceptions as well (since a lot of awaitables are likely to be "True" by default). |
Sorry, something went wrong.
|
I agree with everything Nick said here. |
Sorry, something went wrong.
|
👍 |
Sorry, something went wrong.
|
The Appveyor failures look unrelated to me - closing & reopening to check if they're transient errors. |
Sorry, something went wrong.
|
I'll take a look today/tomorrow, thanks Nick! |
Sorry, something went wrong.
|
@ncoghlan What do you think about adding push_exit and push_callback aliases for API symmetry? |
Sorry, something went wrong.
|
@Kentzo Worth considering as a separate issue for 3.8, but I wouldn't rush into it for 3.7. |
Sorry, something went wrong.
There was a problem hiding this comment.
There're multiple formatting issues with the PR. Please fix the code to follow PEP 8. Reformat docstrings to have a short first line ended with a period, optionally followed by an empty line with more paragraphs.
Most importantly, I don't like the design of _shutdown_loop. I think we shouldn't use generator.send/throw here, I'd prefer to copy/paste the code which will make the code easier to read and maintain (generators are complicated!)
/cc @ncoghlan
Sorry, something went wrong.
There was a problem hiding this comment.
Please trim the lines in your to be max 79 chars wide.
Sorry, something went wrong.
There was a problem hiding this comment.
I'd rewrite to:
An :ref:`asynchronous context manager <async-context-managers>`, similar to :class:`ExitStack`, that supports combining both synchronous and asynchronous context managers, as well as having coroutines for cleanup logic.
Sorry, something went wrong.
There was a problem hiding this comment.
Same as -> Similar to
Sorry, something went wrong.
There was a problem hiding this comment.
"or a coroutine function" -> "or a coroutine".
Sorry, something went wrong.
There was a problem hiding this comment.
ditto
Sorry, something went wrong.
There was a problem hiding this comment.
First line of the docstring should not be empty. Reformat to
"""A base class for ExitStack and AsyncExitStack."""
Sorry, something went wrong.
There was a problem hiding this comment.
Please keep and empty line after the first line of the docstring. I also recommend you to read https://www.python.org/dev/peps/pep-0257/.
Sorry, something went wrong.
There was a problem hiding this comment.
@1st1 In that PEP there is no empty line after a doctstring inside def. Should I add this extra empty line for all functions in my PR?
Sorry, something went wrong.
There was a problem hiding this comment.
Ilya, I mean this:
def foo():
"""First line
A paragraph
"""
codeshould be formatted as this
def foo():
"""First line.
A paragraph.
"""
code
Sorry, something went wrong.
There was a problem hiding this comment.
The first line should be a complete sentence.
I'm not making these rules up -- there're tons of tools out there that expect this specific code style to extract/parse docstrings.
Sorry, something went wrong.
There was a problem hiding this comment.
Ah I see.
Sorry, something went wrong.
There was a problem hiding this comment.
I don't like using generator.send/throw for this. I'd better copy/paste the code. Generators have a pretty complicated semantics (especially around closing) and sometimes have issues with keeping exceptions' tracebacks in tact.
Sorry, something went wrong.
There was a problem hiding this comment.
Put periods . at the end of all your sentences. Throughout the patch.
Sorry, something went wrong.
There was a problem hiding this comment.
Tabulation is off and many lines are longer than 79. Please make sure that your PR follows PEP 8.
Sorry, something went wrong.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request. |
Sorry, something went wrong.
|
I have made the requested changes; please review again |
Sorry, something went wrong.
|
Merged. Thanks so much Ilya! |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
This change is entirely based on the work of @thehesiod discussed at https://bugs.python.org/issue29302
I only changed implementation of __aexit__:
to:
and added tests.
https://bugs.python.org/issue29302