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
Define a general "asynchronous operation introspection" protocol #75413
Comments
As covered in bpo-31183, correctly disassembling functions, generator-iterators, coroutines, and async generator-iterators currently requires checking for 4 different attributes:
This could be simplified if the latter three all also exposed their code attributes as |
Some possibly helpful background (adapted from a discussion in PR 3077): It looks as though My best guess is that Then |
A related issue (since this issue is contemplating restructuring these objects anyway): Other than However, all three of those have On a clean slate (with no attention paid to issues around breaking changes or how these attributes are already used in existing code), is there an argument for dundering some or all of these along with |
I think there's a strong case for a generic __frame__ attribute, since there are plenty of useful things you can do given "object with a linked frame" as a protocol (like extract the current locals namespace). We may even want to include traceback objects in that particular attribute access consolidation (since they have a tb_frame attribute). Looking at the way inspect.getgeneratorstate() and inspect.getcoroutinestate() are implemented, I also think there may be a case for consolidating
Then, rather than adding an inspect API specifically for async generators, we could add a general "inspect.getasyncstate()" one that covered all the object types, with the possible states:
Properly interpreting |
Actually, async_return would be applicable for the synchronous generator case as well, since it would link to the generator containing the |
Slight amendment: "__async_call__" and "__async_return__" both have the problem that they look like imperative commands (since "call" and "return" are typically used as verbs), and collection referring to "yield from" and "await" as "asynchronous delegation" would help avoid potential confusion with regular synchronous function calls. I've also retitled the issue to cover the broader scope that also addresses the needs of the inspect module, not just the dis module. |
I like where this is heading! Aside from the cleaner patterns for handling these objects, I think it'll make it a little easier for people who are just starting to use asynchronous objects in Python (e.g. me) to grasp what's similar about them. +1 that A not-thought-out alternative: what about noun-ing the verbs into BTW, I was thinking of taking a quick run at bpo-31197 while this simmers. I don't /think/ that risks being eventually mooted by these changes; if anything, it might be easier to adapt |
I agree https://bugs.python.org/issue31197 is orthogonal - refactoring the current logic is useful regardless of what we do at the object attribute layer. Regarding __delegated_to__/returns_to, the reason I like *not* having "async" in the attribute names is that generators are actually used as a synchronous construct (via synchronous for loops and next() calls), even though they technically define an asynchronous operation from the interpreter's point of view. The reason I like omitting "call" (or "calls") from the name is that even though "yield from" and "await" are both sometimes described as providing syntax for asynchronous calls, that terminology is really only defensible for "await" - PEP-380 describes the "yield from" operation as delegating to a subgenerator, and I think that's a better way of framing the general concept. |
I started a local PR at https://github.com/ncoghlan/cpython/pull/1/files to explore what this might look like in practice. I think that what I've done so far shows that generic __frame__ and __running__ attributes would be sufficient to extend the inspect module's state introspection support to also cover async generators, while also allowing for the soft (i.e. documentation only) deprecation of the generator and coroutine specific variants of those APIs. bpo-31183 already showed the potential value of a __code__ attribute, since it would allow all of the asynchronous operations to be handled by the same code path that already handles functions. I'm less sure about __delegated_to__/returns_to, since we don't have *any* code in the standard library that reads gi_yieldfrom, and the only code that reads cr_await is a Python 3.5 compatibility hack in asyncio. |
Looks good to me.
I'm -1 on this too. gi_yieldfrom and cr_await are very special and rarely used things. Refactoring or unifying them isn't trivial and ultimately not as useful. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: