classification
Title: Put back the ability to parse files where async/await aren't keywords
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.8
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: gvanrossum Nosy List: Ethan Smith, gvanrossum, levkivskyi, masthana, miss-islington, msullivan, serhiy.storchaka, vstinner, yselivanov
Priority: normal Keywords: patch

Created on 2019-02-12 00:23 by gvanrossum, last changed 2019-03-07 22:58 by gvanrossum. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 12086 merged gvanrossum, 2019-02-28 00:44
Messages (12)
msg335277 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-02-12 00:23
Now that the ast module can be used to parse type comments, there’s one more feature I’d like to lobby for – a flag that modifies the grammar slightly so it resembles an older version of Python (going back to 3.4).

This is used in mypy to decouple the Python version you’re running from the Python version for which you’re checking compatibility (useful when checking code that will be deployed on a system with a different Python version installed). I imagine this would be useful to other linters as well, and the implementation is mostly manipulating whether `async` and `await` are keywords. But if there’s pushback to this part I can live without it – the rest of the work is still useful.

The implementation in typed_ast takes the form of a feature_version flag which is set to the minor Python version to be parsed. Setting it to 4 or lower would make async/await never keywords, setting it to 5 or 6 would make them conditional per PEP 492, and setting it to 7 or higher would make these unconditional keywords. A few minor uses of the same flag also reject f-strings, annotated assignments (PEP 526), and matrix multiply for versions where those don't exist.

But I don't need all of those -- I really just need to be able to select the 3.5/3.6 rules for conditional async/await keywords, since all the other features are purely backwards compatible, whereas with async/await there is legal (and plentiful!) code that uses these as variable or function names that should be supported in 3.5/3.6 mode.

Of course having it be a (minor) version number would still be more future-proof -- if say in 3.10 we add a match expression using some kind of conditional keyword hack, we might have to dust it off.

Note that much of what I'm asking for would effectively roll back https://bugs.python.org/issue30406 -- sorry Jelle! (Though there's more to it -- Serhiy's introduction of Grammar/Token followed, and I would still need to thread some kind of flag all the way from ast.parse() to tokenizer.c.
msg336785 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2019-02-28 00:24
Well, it's not just rolling back async/await from being keywords. Since 3.7 it's possible to create async generator expressions in non-async functions. This wasn't possible to do with old hacks on the lexer. So if you want to revert the change you risk losing some functionality we enabled in 3.7
msg336786 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-02-28 00:37
That should still work. The strategy is as follows:

- For Python 3.7 or higher, 'async' and 'await' are *always* recognized.

- For Python 3.5 and 3.6, the hacks from the PEP are used.
msg336788 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2019-02-28 01:00
Actually, I think we could revert to old lexer hacks in 3.8 if we modify them to treat 'async for' tocken sequence as one meta-tocken.
msg336789 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-02-28 01:10
But why would we? I already have a working solution. (Literally reverting Jelle's PR won't work anyway, because Serhiy changed how regen-token works.)
msg336790 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2019-02-28 01:25
> But why would we? I already have a working solution. 

I've heard some complaints that it's hard to migrate to Python 3.7 because async and await are keywords (although I think by now all popular libraries have migrated already), so in case you ever considered to revert that decision I think we could actually make it work.  But for the current PR you're working on we don't need that, you're right.
msg336795 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-02-28 03:06
And the same tokenizer trick that detects 'async def' could detect 'async for' easily. See https://github.com/python/cpython/pull/12086/files#diff-30b8266a4285de981f8b1b82a8cc6231R1418
msg336800 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2019-02-28 05:11
> And the same tokenizer trick that detects 'async def' could detect 'async for' easily.

Exactly.  I just never thought that we could support async generator expressions with the kind of hacks in tokenizer we had in 3.5-3.6.  FWIW I still believe that it's better for async & await tokens to be proper keywords, but in case we ever realize we want them to become "soft" keywords we apparently have options.
msg336831 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2019-02-28 12:32
Would not be simpler to just drop the support of Python versions <3.7 in new MyPy versions?
msg336879 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-02-28 23:25
> Would not be simpler to just drop the support of Python versions <3.7 in new MyPy versions?

Not really -- mypy has a lot of users who run it over (very) large code bases that can't easily be upgraded. Basically mypy has to support all Python versions that haven't reached their end of life yet. (And it's also important that mypy not be constrained to the same Python version as the target code.)

I suppose we could just stick with the existing typed_ast that supports 3.4 through 3.7, but we actually have a use case for the end_lineno and end_col_offset fields that were just added to ast in 3.8, and in general we'd like to support any future grammar elements and ast features.
msg337243 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-03-05 23:21
Everyone watching, the PR is now ready for review!
msg337432 - (view) Author: miss-islington (miss-islington) Date: 2019-03-07 20:38
New changeset 495da292255b92dd73758fdd0e4c7d27d82b1e57 by Miss Islington (bot) (Guido van Rossum) in branch 'master':
bpo-35975: Support parsing earlier minor versions of Python 3 (GH-12086)
https://github.com/python/cpython/commit/495da292255b92dd73758fdd0e4c7d27d82b1e57
History
Date User Action Args
2019-03-07 22:58:25gvanrossumsetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2019-03-07 20:38:15miss-islingtonsetnosy: + miss-islington
messages: + msg337432
2019-03-05 23:21:09gvanrossumsetmessages: + msg337243
2019-03-01 15:33:06vstinnersetnosy: + vstinner
2019-02-28 23:25:04gvanrossumsetmessages: + msg336879
2019-02-28 12:32:17serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg336831
2019-02-28 05:11:37yselivanovsetmessages: + msg336800
2019-02-28 03:06:04gvanrossumsetmessages: + msg336795
2019-02-28 01:25:45yselivanovsetmessages: + msg336790
2019-02-28 01:10:22gvanrossumsetmessages: + msg336789
2019-02-28 01:00:29yselivanovsetmessages: + msg336788
2019-02-28 00:44:52gvanrossumsetkeywords: + patch
stage: needs patch -> patch review
pull_requests: + pull_request12096
2019-02-28 00:37:38gvanrossumsetmessages: + msg336786
2019-02-28 00:24:20yselivanovsetnosy: + yselivanov
messages: + msg336785
2019-02-26 20:59:18msullivansetnosy: + msullivan
2019-02-16 16:30:59masthanasetnosy: + masthana
2019-02-13 02:59:14gvanrossumsetassignee: gvanrossum
stage: needs patch
type: behavior
components: + Interpreter Core
versions: + Python 3.8
2019-02-12 01:24:40Ethan Smithsetnosy: + Ethan Smith
2019-02-12 00:35:49levkivskyisetnosy: + levkivskyi
2019-02-12 00:23:38gvanrossumcreate