Skip to content

Commit fb844e1

Browse files
authored
gh-98762: Fix locations of match sub-patterns (GH-98775)
1 parent 73a921b commit fb844e1

File tree

3 files changed

+212
-130
lines changed

3 files changed

+212
-130
lines changed

Lib/test/test_compile.py

+95-1
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,7 @@ def check_positions_against_ast(self, snippet):
11641164
class SourceOffsetVisitor(ast.NodeVisitor):
11651165
def generic_visit(self, node):
11661166
super().generic_visit(node)
1167-
if not isinstance(node, ast.expr) and not isinstance(node, ast.stmt):
1167+
if not isinstance(node, (ast.expr, ast.stmt, ast.pattern)):
11681168
return
11691169
lines.add(node.lineno)
11701170
end_lines.add(node.end_lineno)
@@ -1442,6 +1442,100 @@ async def f():
14421442
self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_VALUE',
14431443
line=2, end_line=7, column=4, end_column=36, occurrence=1)
14441444

1445+
def test_matchcase_sequence(self):
1446+
snippet = """\
1447+
match x:
1448+
case a, b:
1449+
pass
1450+
"""
1451+
compiled_code, _ = self.check_positions_against_ast(snippet)
1452+
self.assertOpcodeSourcePositionIs(compiled_code, 'MATCH_SEQUENCE',
1453+
line=2, end_line=2, column=9, end_column=13, occurrence=1)
1454+
self.assertOpcodeSourcePositionIs(compiled_code, 'UNPACK_SEQUENCE',
1455+
line=2, end_line=2, column=9, end_column=13, occurrence=1)
1456+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1457+
line=2, end_line=2, column=9, end_column=13, occurrence=1)
1458+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1459+
line=2, end_line=2, column=9, end_column=13, occurrence=2)
1460+
1461+
def test_matchcase_sequence_wildcard(self):
1462+
snippet = """\
1463+
match x:
1464+
case a, *b, c:
1465+
pass
1466+
"""
1467+
compiled_code, _ = self.check_positions_against_ast(snippet)
1468+
self.assertOpcodeSourcePositionIs(compiled_code, 'MATCH_SEQUENCE',
1469+
line=2, end_line=2, column=9, end_column=17, occurrence=1)
1470+
self.assertOpcodeSourcePositionIs(compiled_code, 'UNPACK_EX',
1471+
line=2, end_line=2, column=9, end_column=17, occurrence=1)
1472+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1473+
line=2, end_line=2, column=9, end_column=17, occurrence=1)
1474+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1475+
line=2, end_line=2, column=9, end_column=17, occurrence=2)
1476+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1477+
line=2, end_line=2, column=9, end_column=17, occurrence=3)
1478+
1479+
def test_matchcase_mapping(self):
1480+
snippet = """\
1481+
match x:
1482+
case {"a" : a, "b": b}:
1483+
pass
1484+
"""
1485+
compiled_code, _ = self.check_positions_against_ast(snippet)
1486+
self.assertOpcodeSourcePositionIs(compiled_code, 'MATCH_MAPPING',
1487+
line=2, end_line=2, column=9, end_column=26, occurrence=1)
1488+
self.assertOpcodeSourcePositionIs(compiled_code, 'MATCH_KEYS',
1489+
line=2, end_line=2, column=9, end_column=26, occurrence=1)
1490+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1491+
line=2, end_line=2, column=9, end_column=26, occurrence=1)
1492+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1493+
line=2, end_line=2, column=9, end_column=26, occurrence=2)
1494+
1495+
def test_matchcase_mapping_wildcard(self):
1496+
snippet = """\
1497+
match x:
1498+
case {"a" : a, "b": b, **c}:
1499+
pass
1500+
"""
1501+
compiled_code, _ = self.check_positions_against_ast(snippet)
1502+
self.assertOpcodeSourcePositionIs(compiled_code, 'MATCH_MAPPING',
1503+
line=2, end_line=2, column=9, end_column=31, occurrence=1)
1504+
self.assertOpcodeSourcePositionIs(compiled_code, 'MATCH_KEYS',
1505+
line=2, end_line=2, column=9, end_column=31, occurrence=1)
1506+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1507+
line=2, end_line=2, column=9, end_column=31, occurrence=1)
1508+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1509+
line=2, end_line=2, column=9, end_column=31, occurrence=2)
1510+
1511+
def test_matchcase_class(self):
1512+
snippet = """\
1513+
match x:
1514+
case C(a, b):
1515+
pass
1516+
"""
1517+
compiled_code, _ = self.check_positions_against_ast(snippet)
1518+
self.assertOpcodeSourcePositionIs(compiled_code, 'MATCH_CLASS',
1519+
line=2, end_line=2, column=9, end_column=16, occurrence=1)
1520+
self.assertOpcodeSourcePositionIs(compiled_code, 'UNPACK_SEQUENCE',
1521+
line=2, end_line=2, column=9, end_column=16, occurrence=1)
1522+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1523+
line=2, end_line=2, column=9, end_column=16, occurrence=1)
1524+
self.assertOpcodeSourcePositionIs(compiled_code, 'STORE_NAME',
1525+
line=2, end_line=2, column=9, end_column=16, occurrence=2)
1526+
1527+
def test_matchcase_or(self):
1528+
snippet = """\
1529+
match x:
1530+
case C(1) | C(2):
1531+
pass
1532+
"""
1533+
compiled_code, _ = self.check_positions_against_ast(snippet)
1534+
self.assertOpcodeSourcePositionIs(compiled_code, 'MATCH_CLASS',
1535+
line=2, end_line=2, column=9, end_column=13, occurrence=1)
1536+
self.assertOpcodeSourcePositionIs(compiled_code, 'MATCH_CLASS',
1537+
line=2, end_line=2, column=16, end_column=20, occurrence=2)
1538+
14451539
def test_very_long_line_end_offset(self):
14461540
# Make sure we get the correct column offset for offsets
14471541
# too large to store in a byte.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix source locations of :keyword:`match` sub-patterns.

0 commit comments

Comments
 (0)