You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[lib2to3] Synchronize token.py and tokenize.py with the standard library #77519
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:
assignee=Noneclosed_at=<Date2021-10-20.22:50:30.926>created_at=<Date2018-04-23.01:04:56.372>labels= ['expert-2to3', '3.8', 'library']
title='[lib2to3] Synchronize token.py and tokenize.py with the standard library'updated_at=<Date2021-10-20.22:50:30.926>user='https://github.com/ambv'
lib2to3's token.py and tokenize.py were initially copies of the respective
files from the standard library. They were copied to allow Python 3 to read
Python 2's grammar.
Since 2006, lib2to3 grew to be widely used as a Concrete Syntax Tree, also for
parsing Python 3 code. Additions to support Python 3 grammar were added but
sadly, the main token.py and tokenize.py diverged.
This change brings them back together, minimizing the differences to the bare
minimum that is in fact required by lib2to3. Before this change, almost every
line in lib2to3/pgen2/tokenize.py was different from tokenize.py. After this
change, the diff between the two files is only 175 lines long and is entirely
filled with relevant Python 2 compatibility bits.
Merging the implementations, there's numerous fixes to the lib2to3 tokenizer:
It seems to me that regular expressions used in the lib2to3 version are more efficient but more complex.
$ ./python -m timeit -s 'import re; p = re.compile(r"0[bB](?:_?[01])+"); s = "0b"+"_0101"*16''p.match(s)'
100000 loops, best of 5: 2.45 usec per loop
$ ./python -m timeit -s 'import re; p = re.compile(r"0[bB]_?[01]+(?:_[01]+)*"); s = "0b"+"_0101"*16''p.match(s)'
200000 loops, best of 5: 1.08 usec per loop
$ ./python -m timeit -s 'import re; p = re.compile(r"0[xX](?:_?[0-9a-fA-F])+[lL]?"); s = "0x_0123_4567_89ab_cdef"''p.match(s)'
500000 loops, best of 5: 815 nsec per loop
$ ./python -m timeit -s 'import re; p = re.compile(r"0[xX]_?[\da-fA-F]+(?:_[\da-fA-F]+)*[lL]?"); s = "0x_0123_4567_89ab_cdef"''p.match(s)'
500000 loops, best of 5: 542 nsec per loop
Since the performance of lib2to3 is important, it is better to keep the current regexpes.
But using \d in Python 3 is a bug, it should be replaced with [0-9]. This also speeds up the regex:
$ ./python -m timeit -s 'import re; p = re.compile(r"0[xX]_?[0-9a-fA-F]+(?:_[0-9a-fA-F]+)*[lL]?"); s = "0x_0123_4567_89ab_cdef"''p.match(s)'
500000 loops, best of 5: 471 nsec per loop
I agree with you Serhiy, there's a number things I want to make faster. But first I'd like to merge implementations so there is a clear one-way diff ("this is what we updated in lib2to3 to make it consistent it Lib/tokenize.py"). Then I want to optimize.
Activity
ambv commentedon Apr 23, 2018
lib2to3's token.py and tokenize.py were initially copies of the respective
files from the standard library. They were copied to allow Python 3 to read
Python 2's grammar.
Since 2006, lib2to3 grew to be widely used as a Concrete Syntax Tree, also for
parsing Python 3 code. Additions to support Python 3 grammar were added but
sadly, the main token.py and tokenize.py diverged.
This change brings them back together, minimizing the differences to the bare
minimum that is in fact required by lib2to3. Before this change, almost every
line in lib2to3/pgen2/tokenize.py was different from tokenize.py. After this
change, the diff between the two files is only 175 lines long and is entirely
filled with relevant Python 2 compatibility bits.
Merging the implementations, there's numerous fixes to the lib2to3 tokenizer:
TokenInfotokenize.tokenize()andtokenize.open()stream (added \Z (end of string) to PseudoExtras) - BPO-16152
find_cookieincludes file name in error messages, if availablefind_cookieraises SyntaxError on invalid encodings: BPO-14990Improvements to lib2to3/pgen2/token.py:
__all__properly definedambv commentedon Apr 23, 2018
### Diff between files
The unified diff between tokenize implementations is here:
https://gist.github.com/ambv/679018041d85dd1a7497e6d89c45fb86
It clocks at 275 lines but that's because it gives context. The actual diff is
175 lines long.
To make it that small, I needed to move some insignificant bits in
Lib/tokenize.py. This is what the other PR on this issue is about.
ambv commentedon Apr 23, 2018
New changeset c2d384d by Łukasz Langa in branch 'master':
bpo-33338: [tokenize] Minor code cleanup (bpo-6573)
c2d384d
serhiy-storchaka commentedon Apr 26, 2018
It seems to me that regular expressions used in the lib2to3 version are more efficient but more complex.
Since the performance of lib2to3 is important, it is better to keep the current regexpes.
But using \d in Python 3 is a bug, it should be replaced with [0-9]. This also speeds up the regex:
ambv commentedon Apr 26, 2018
I agree with you Serhiy, there's a number things I want to make faster. But first I'd like to merge implementations so there is a clear one-way diff ("this is what we updated in lib2to3 to make it consistent it Lib/tokenize.py"). Then I want to optimize.