Skip to content

Commit 7670a7c

Browse files
committed
Merge remote-tracking branch 'upstream/main' into codegen-reduce-repetition
2 parents 66d5609 + cf730b5 commit 7670a7c

25 files changed

+583
-131
lines changed

Doc/c-api/type.rst

+2
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,8 @@ The following functions and structs are used to create
296296
Array of :c:type:`PyType_Slot` structures.
297297
Terminated by the special slot value ``{0, NULL}``.
298298
299+
Each slot ID should be specified at most once.
300+
299301
.. c:type:: PyType_Slot
300302
301303
Structure defining optional functionality of a type, containing a slot ID

Doc/library/os.path.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ the :mod:`glob` module.)
469469
("c:", "/dir")
470470

471471
If the path contains a UNC path, drive will contain the host name
472-
and share, up to but not including the fourth separator::
472+
and share::
473473

474474
>>> splitdrive("//host/computer/dir")
475475
("//host/computer", "/dir")

Grammar/python.gram

+3-3
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ or_pattern[pattern_ty]:
471471
| patterns[asdl_pattern_seq*]='|'.closed_pattern+ {
472472
asdl_seq_LEN(patterns) == 1 ? asdl_seq_GET(patterns, 0) : _PyAST_MatchOr(patterns, EXTRA) }
473473

474-
closed_pattern[pattern_ty]:
474+
closed_pattern[pattern_ty] (memo):
475475
| literal_pattern
476476
| capture_pattern
477477
| wildcard_pattern
@@ -558,7 +558,7 @@ maybe_star_pattern[pattern_ty]:
558558
| star_pattern
559559
| pattern
560560

561-
star_pattern[pattern_ty]:
561+
star_pattern[pattern_ty] (memo):
562562
| '*' target=pattern_capture_target {
563563
_PyAST_MatchStar(target->v.Name.id, EXTRA) }
564564
| '*' wildcard_pattern {
@@ -1312,4 +1312,4 @@ invalid_kvpair:
13121312
| a=expression !(':') {
13131313
RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, a->lineno, a->end_col_offset - 1, a->end_lineno, -1, "':' expected after dictionary key") }
13141314
| expression ':' a='*' bitwise_or { RAISE_SYNTAX_ERROR_STARTING_FROM(a, "cannot use a starred expression in a dictionary value") }
1315-
| expression a=':' {RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "expression expected after dictionary key and ':'") }
1315+
| expression a=':' {RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "expression expected after dictionary key and ':'") }

Lib/ntpath.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,23 @@ def splitdrive(p):
172172
sep = b'\\'
173173
altsep = b'/'
174174
colon = b':'
175+
unc_prefix = b'\\\\?\\UNC'
175176
else:
176177
sep = '\\'
177178
altsep = '/'
178179
colon = ':'
180+
unc_prefix = '\\\\?\\UNC'
179181
normp = p.replace(altsep, sep)
180182
if (normp[0:2] == sep*2) and (normp[2:3] != sep):
181183
# is a UNC path:
182184
# vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
183185
# \\machine\mountpoint\directory\etc\...
184186
# directory ^^^^^^^^^^^^^^^
185-
index = normp.find(sep, 2)
187+
if normp[:8].upper().rstrip(sep) == unc_prefix:
188+
start = 8
189+
else:
190+
start = 2
191+
index = normp.find(sep, start)
186192
if index == -1:
187193
return p[:0], p
188194
index2 = normp.find(sep, index + 1)

Lib/pathlib.py

+4-64
Original file line numberDiff line numberDiff line change
@@ -120,68 +120,18 @@ class _WindowsFlavour(_Flavour):
120120

121121
is_supported = (os.name == 'nt')
122122

123-
drive_letters = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
124-
ext_namespace_prefix = '\\\\?\\'
125-
126123
reserved_names = (
127124
{'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} |
128125
{'COM%s' % c for c in '123456789\xb9\xb2\xb3'} |
129126
{'LPT%s' % c for c in '123456789\xb9\xb2\xb3'}
130127
)
131128

132-
# Interesting findings about extended paths:
133-
# * '\\?\c:\a' is an extended path, which bypasses normal Windows API
134-
# path processing. Thus relative paths are not resolved and slash is not
135-
# translated to backslash. It has the native NT path limit of 32767
136-
# characters, but a bit less after resolving device symbolic links,
137-
# such as '\??\C:' => '\Device\HarddiskVolume2'.
138-
# * '\\?\c:/a' looks for a device named 'C:/a' because slash is a
139-
# regular name character in the object namespace.
140-
# * '\\?\c:\foo/bar' is invalid because '/' is illegal in NT filesystems.
141-
# The only path separator at the filesystem level is backslash.
142-
# * '//?/c:\a' and '//?/c:/a' are effectively equivalent to '\\.\c:\a' and
143-
# thus limited to MAX_PATH.
144-
# * Prior to Windows 8, ANSI API bytes paths are limited to MAX_PATH,
145-
# even with the '\\?\' prefix.
146-
147129
def splitroot(self, part, sep=sep):
148-
first = part[0:1]
149-
second = part[1:2]
150-
if (second == sep and first == sep):
151-
# XXX extended paths should also disable the collapsing of "."
152-
# components (according to MSDN docs).
153-
prefix, part = self._split_extended_path(part)
154-
first = part[0:1]
155-
second = part[1:2]
130+
drv, rest = self.pathmod.splitdrive(part)
131+
if drv[:1] == sep or rest[:1] == sep:
132+
return drv, sep, rest.lstrip(sep)
156133
else:
157-
prefix = ''
158-
third = part[2:3]
159-
if (second == sep and first == sep and third != sep):
160-
# is a UNC path:
161-
# vvvvvvvvvvvvvvvvvvvvv root
162-
# \\machine\mountpoint\directory\etc\...
163-
# directory ^^^^^^^^^^^^^^
164-
index = part.find(sep, 2)
165-
if index != -1:
166-
index2 = part.find(sep, index + 1)
167-
# a UNC path can't have two slashes in a row
168-
# (after the initial two)
169-
if index2 != index + 1:
170-
if index2 == -1:
171-
index2 = len(part)
172-
if prefix:
173-
return prefix + part[1:index2], sep, part[index2+1:]
174-
else:
175-
return part[:index2], sep, part[index2+1:]
176-
drv = root = ''
177-
if second == ':' and first in self.drive_letters:
178-
drv = part[:2]
179-
part = part[2:]
180-
first = third
181-
if first == sep:
182-
root = first
183-
part = part.lstrip(sep)
184-
return prefix + drv, root, part
134+
return drv, '', rest
185135

186136
def casefold(self, s):
187137
return s.lower()
@@ -192,16 +142,6 @@ def casefold_parts(self, parts):
192142
def compile_pattern(self, pattern):
193143
return re.compile(fnmatch.translate(pattern), re.IGNORECASE).fullmatch
194144

195-
def _split_extended_path(self, s, ext_prefix=ext_namespace_prefix):
196-
prefix = ''
197-
if s.startswith(ext_prefix):
198-
prefix = s[:4]
199-
s = s[4:]
200-
if s.startswith('UNC\\'):
201-
prefix += s[:3]
202-
s = '\\' + s[3:]
203-
return prefix, s
204-
205145
def is_reserved(self, parts):
206146
# NOTE: the rules for reserved names seem somewhat complicated
207147
# (e.g. r"..\NUL" is reserved but not r"foo\NUL" if "foo" does not

Lib/test/test_capi.py

+6
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,12 @@ def test_heaptype_with_custom_metaclass(self):
618618
with self.assertRaisesRegex(TypeError, msg):
619619
t = _testcapi.pytype_fromspec_meta(_testcapi.HeapCTypeMetaclassCustomNew)
620620

621+
def test_pytype_fromspec_with_repeated_slots(self):
622+
for variant in range(2):
623+
with self.subTest(variant=variant):
624+
with self.assertRaises(SystemError):
625+
_testcapi.create_type_from_repeated_slots(variant)
626+
621627
def test_pynumber_tobase(self):
622628
from _testcapi import pynumber_tobase
623629
self.assertEqual(pynumber_tobase(123, 2), '0b1111011')

Lib/test/test_dis.py

+159-8
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ def bug42562():
389389
POP_EXCEPT
390390
RERAISE 1
391391
ExceptionTable:
392+
4 rows
392393
""" % (TRACEBACK_CODE.co_firstlineno,
393394
TRACEBACK_CODE.co_firstlineno + 1,
394395
TRACEBACK_CODE.co_firstlineno + 2,
@@ -421,6 +422,133 @@ def _fstring(a, b, c, d):
421422
RETURN_VALUE
422423
""" % (_fstring.__code__.co_firstlineno, _fstring.__code__.co_firstlineno + 1)
423424

425+
def _with(c):
426+
with c:
427+
x = 1
428+
y = 2
429+
430+
dis_with = """\
431+
%3d RESUME 0
432+
433+
%3d LOAD_FAST 0 (c)
434+
BEFORE_WITH
435+
POP_TOP
436+
437+
%3d LOAD_CONST 1 (1)
438+
STORE_FAST 1 (x)
439+
440+
%3d LOAD_CONST 0 (None)
441+
LOAD_CONST 0 (None)
442+
LOAD_CONST 0 (None)
443+
CALL 2
444+
POP_TOP
445+
446+
%3d LOAD_CONST 2 (2)
447+
STORE_FAST 2 (y)
448+
LOAD_CONST 0 (None)
449+
RETURN_VALUE
450+
451+
%3d >> PUSH_EXC_INFO
452+
WITH_EXCEPT_START
453+
POP_JUMP_FORWARD_IF_TRUE 1 (to 46)
454+
RERAISE 2
455+
>> POP_TOP
456+
POP_EXCEPT
457+
POP_TOP
458+
POP_TOP
459+
460+
%3d LOAD_CONST 2 (2)
461+
STORE_FAST 2 (y)
462+
LOAD_CONST 0 (None)
463+
RETURN_VALUE
464+
>> COPY 3
465+
POP_EXCEPT
466+
RERAISE 1
467+
ExceptionTable:
468+
2 rows
469+
""" % (_with.__code__.co_firstlineno,
470+
_with.__code__.co_firstlineno + 1,
471+
_with.__code__.co_firstlineno + 2,
472+
_with.__code__.co_firstlineno + 1,
473+
_with.__code__.co_firstlineno + 3,
474+
_with.__code__.co_firstlineno + 1,
475+
_with.__code__.co_firstlineno + 3,
476+
)
477+
478+
async def _asyncwith(c):
479+
async with c:
480+
x = 1
481+
y = 2
482+
483+
dis_asyncwith = """\
484+
%3d RETURN_GENERATOR
485+
POP_TOP
486+
RESUME 0
487+
488+
%3d LOAD_FAST 0 (c)
489+
BEFORE_ASYNC_WITH
490+
GET_AWAITABLE 1
491+
LOAD_CONST 0 (None)
492+
>> SEND 3 (to 22)
493+
YIELD_VALUE 3
494+
RESUME 3
495+
JUMP_BACKWARD_NO_INTERRUPT 4 (to 14)
496+
>> POP_TOP
497+
498+
%3d LOAD_CONST 1 (1)
499+
STORE_FAST 1 (x)
500+
501+
%3d LOAD_CONST 0 (None)
502+
LOAD_CONST 0 (None)
503+
LOAD_CONST 0 (None)
504+
CALL 2
505+
GET_AWAITABLE 2
506+
LOAD_CONST 0 (None)
507+
>> SEND 3 (to 56)
508+
YIELD_VALUE 2
509+
RESUME 3
510+
JUMP_BACKWARD_NO_INTERRUPT 4 (to 48)
511+
>> POP_TOP
512+
513+
%3d LOAD_CONST 2 (2)
514+
STORE_FAST 2 (y)
515+
LOAD_CONST 0 (None)
516+
RETURN_VALUE
517+
518+
%3d >> PUSH_EXC_INFO
519+
WITH_EXCEPT_START
520+
GET_AWAITABLE 2
521+
LOAD_CONST 0 (None)
522+
>> SEND 3 (to 82)
523+
YIELD_VALUE 6
524+
RESUME 3
525+
JUMP_BACKWARD_NO_INTERRUPT 4 (to 74)
526+
>> POP_JUMP_FORWARD_IF_TRUE 1 (to 86)
527+
RERAISE 2
528+
>> POP_TOP
529+
POP_EXCEPT
530+
POP_TOP
531+
POP_TOP
532+
533+
%3d LOAD_CONST 2 (2)
534+
STORE_FAST 2 (y)
535+
LOAD_CONST 0 (None)
536+
RETURN_VALUE
537+
>> COPY 3
538+
POP_EXCEPT
539+
RERAISE 1
540+
ExceptionTable:
541+
2 rows
542+
""" % (_asyncwith.__code__.co_firstlineno,
543+
_asyncwith.__code__.co_firstlineno + 1,
544+
_asyncwith.__code__.co_firstlineno + 2,
545+
_asyncwith.__code__.co_firstlineno + 1,
546+
_asyncwith.__code__.co_firstlineno + 3,
547+
_asyncwith.__code__.co_firstlineno + 1,
548+
_asyncwith.__code__.co_firstlineno + 3,
549+
)
550+
551+
424552
def _tryfinally(a, b):
425553
try:
426554
return a
@@ -455,6 +583,7 @@ def _tryfinallyconst(b):
455583
POP_EXCEPT
456584
RERAISE 1
457585
ExceptionTable:
586+
2 rows
458587
""" % (_tryfinally.__code__.co_firstlineno,
459588
_tryfinally.__code__.co_firstlineno + 1,
460589
_tryfinally.__code__.co_firstlineno + 2,
@@ -484,6 +613,7 @@ def _tryfinallyconst(b):
484613
POP_EXCEPT
485614
RERAISE 1
486615
ExceptionTable:
616+
1 row
487617
""" % (_tryfinallyconst.__code__.co_firstlineno,
488618
_tryfinallyconst.__code__.co_firstlineno + 1,
489619
_tryfinallyconst.__code__.co_firstlineno + 2,
@@ -678,6 +808,18 @@ def assert_offsets_increasing(self, text, delta):
678808
self.assertGreaterEqual(offset, expected_offset, line)
679809
expected_offset = offset + delta
680810

811+
def assert_exception_table_increasing(self, lines):
812+
prev_start, prev_end = -1, -1
813+
count = 0
814+
for line in lines:
815+
m = re.match(r' (\d+) to (\d+) -> \d+ \[\d+\]', line)
816+
start, end = [int(g) for g in m.groups()]
817+
self.assertGreaterEqual(end, start)
818+
self.assertGreater(start, prev_end)
819+
prev_start, prev_end = start, end
820+
count += 1
821+
return count
822+
681823
def strip_offsets(self, text):
682824
lines = text.splitlines(True)
683825
start, end = self.find_offset_column(lines)
@@ -691,6 +833,9 @@ def strip_offsets(self, text):
691833
res.append(line)
692834
else:
693835
res.append(line[:start] + line[end:])
836+
num_rows = self.assert_exception_table_increasing(lines)
837+
if num_rows:
838+
res.append(f"{num_rows} row{'s' if num_rows > 1 else ''}\n")
694839
return "".join(res)
695840

696841
def do_disassembly_compare(self, got, expected, with_offsets=False):
@@ -883,6 +1028,12 @@ def test_disassemble_coroutine(self):
8831028
def test_disassemble_fstring(self):
8841029
self.do_disassembly_test(_fstring, dis_fstring)
8851030

1031+
def test_disassemble_with(self):
1032+
self.do_disassembly_test(_with, dis_with)
1033+
1034+
def test_disassemble_asyncwith(self):
1035+
self.do_disassembly_test(_asyncwith, dis_asyncwith)
1036+
8861037
def test_disassemble_try_finally(self):
8871038
self.do_disassembly_test(_tryfinally, dis_tryfinally)
8881039
self.do_disassembly_test(_tryfinallyconst, dis_tryfinallyconst)
@@ -1471,16 +1622,16 @@ def _prepare_test_cases():
14711622
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=302, starts_line=None, is_jump_target=False, positions=None),
14721623
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=304, starts_line=25, is_jump_target=False, positions=None),
14731624
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=306, starts_line=None, is_jump_target=False, positions=None),
1474-
Instruction(opname='POP_JUMP_FORWARD_IF_TRUE', opcode=115, arg=4, argval=318, argrepr='to 318', offset=308, starts_line=None, is_jump_target=False, positions=None),
1625+
Instruction(opname='POP_JUMP_FORWARD_IF_TRUE', opcode=115, arg=1, argval=312, argrepr='to 312', offset=308, starts_line=None, is_jump_target=False, positions=None),
14751626
Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=310, starts_line=None, is_jump_target=False, positions=None),
1476-
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None),
1627+
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=312, starts_line=None, is_jump_target=True, positions=None),
14771628
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=314, starts_line=None, is_jump_target=False, positions=None),
1478-
Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None),
1479-
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=318, starts_line=None, is_jump_target=True, positions=None),
1480-
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=320, starts_line=None, is_jump_target=False, positions=None),
1481-
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None),
1482-
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None),
1483-
Instruction(opname='JUMP_BACKWARD', opcode=140, arg=27, argval=274, argrepr='to 274', offset=326, starts_line=None, is_jump_target=False, positions=None),
1629+
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None),
1630+
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=318, starts_line=None, is_jump_target=False, positions=None),
1631+
Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=274, argrepr='to 274', offset=320, starts_line=None, is_jump_target=False, positions=None),
1632+
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None),
1633+
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None),
1634+
Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=326, starts_line=None, is_jump_target=False, positions=None),
14841635
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=328, starts_line=None, is_jump_target=False, positions=None),
14851636
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=330, starts_line=22, is_jump_target=False, positions=None),
14861637
Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=342, starts_line=None, is_jump_target=False, positions=None),

0 commit comments

Comments
 (0)