Skip to content

Commit a0c01bf

Browse files
authored
bpo-37115: Support annotations in positional-only arguments (GH-13698)
1 parent 2f58a84 commit a0c01bf

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

Lib/test/test_grammar.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,14 +620,22 @@ def f(x) -> list: pass
620620
self.assertEqual(f.__annotations__, {'return': list})
621621
def f(x: int): pass
622622
self.assertEqual(f.__annotations__, {'x': int})
623+
def f(x: int, /): pass
624+
self.assertEqual(f.__annotations__, {'x': int})
625+
def f(x: int = 34, /): pass
626+
self.assertEqual(f.__annotations__, {'x': int})
623627
def f(*x: str): pass
624628
self.assertEqual(f.__annotations__, {'x': str})
625629
def f(**x: float): pass
626630
self.assertEqual(f.__annotations__, {'x': float})
627631
def f(x, y: 1+2): pass
628632
self.assertEqual(f.__annotations__, {'y': 3})
633+
def f(x, y: 1+2, /): pass
634+
self.assertEqual(f.__annotations__, {'y': 3})
629635
def f(a, b: 1, c: 2, d): pass
630636
self.assertEqual(f.__annotations__, {'b': 1, 'c': 2})
637+
def f(a, b: 1, /, c: 2, d): pass
638+
self.assertEqual(f.__annotations__, {'b': 1, 'c': 2})
631639
def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6): pass
632640
self.assertEqual(f.__annotations__,
633641
{'b': 1, 'c': 2, 'e': 3, 'g': 6})
@@ -636,6 +644,11 @@ def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6, h: 7, i=8, j: 9 = 10,
636644
self.assertEqual(f.__annotations__,
637645
{'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9,
638646
'k': 11, 'return': 12})
647+
def f(a, b: 1, c: 2, d, e: 3 = 4, f: int = 5, /, *g: 6, h: 7, i=8, j: 9 = 10,
648+
**k: 11) -> 12: pass
649+
self.assertEqual(f.__annotations__,
650+
{'b': 1, 'c': 2, 'e': 3, 'f': int, 'g': 6, 'h': 7, 'j': 9,
651+
'k': 11, 'return': 12})
639652
# Check for issue #20625 -- annotations mangling
640653
class Spam:
641654
def f(self, *, __kw: 1):

Lib/test/test_type_comments.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,25 @@ def fa(
9999
):
100100
pass
101101
102+
def fa(
103+
a = 1, # type: A
104+
/
105+
):
106+
pass
107+
102108
def fab(
103109
a, # type: A
104110
b, # type: B
105111
):
106112
pass
107113
114+
def fab(
115+
a, # type: A
116+
/,
117+
b, # type: B
118+
):
119+
pass
120+
108121
def fab(
109122
a, # type: A
110123
b # type: B
@@ -149,6 +162,13 @@ def fav(
149162
):
150163
pass
151164
165+
def fav(
166+
a, # type: A
167+
/,
168+
*v, # type: V
169+
):
170+
pass
171+
152172
def fav(
153173
a, # type: A
154174
*v # type: V
@@ -161,6 +181,13 @@ def fak(
161181
):
162182
pass
163183
184+
def fak(
185+
a, # type: A
186+
/,
187+
**k, # type: K
188+
):
189+
pass
190+
164191
def fak(
165192
a, # type: A
166193
**k # type: K
@@ -174,6 +201,14 @@ def favk(
174201
):
175202
pass
176203
204+
def favk(
205+
a, # type: A
206+
/,
207+
*v, # type: V
208+
**k, # type: K
209+
):
210+
pass
211+
177212
def favk(
178213
a, # type: A
179214
*v, # type: V
@@ -290,18 +325,21 @@ def test_longargs(self):
290325
for t in tree.body:
291326
# The expected args are encoded in the function name
292327
todo = set(t.name[1:])
293-
self.assertEqual(len(t.args.args),
328+
self.assertEqual(len(t.args.args) + len(t.args.posonlyargs),
294329
len(todo) - bool(t.args.vararg) - bool(t.args.kwarg))
295330
self.assertTrue(t.name.startswith('f'), t.name)
296-
for c in t.name[1:]:
331+
for index, c in enumerate(t.name[1:]):
297332
todo.remove(c)
298333
if c == 'v':
299334
arg = t.args.vararg
300335
elif c == 'k':
301336
arg = t.args.kwarg
302337
else:
303-
assert 0 <= ord(c) - ord('a') < len(t.args.args)
304-
arg = t.args.args[ord(c) - ord('a')]
338+
assert 0 <= ord(c) - ord('a') < len(t.args.posonlyargs + t.args.args)
339+
if index < len(t.args.posonlyargs):
340+
arg = t.args.posonlyargs[ord(c) - ord('a')]
341+
else:
342+
arg = t.args.args[ord(c) - ord('a') - len(t.args.posonlyargs)]
305343
self.assertEqual(arg.arg, c) # That's the argument name
306344
self.assertEqual(arg.type_comment, arg.arg.upper())
307345
assert not todo

Python/compile.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,8 @@ compiler_visit_annotations(struct compiler *c, arguments_ty args,
19911991

19921992
if (!compiler_visit_argannotations(c, args->args, names))
19931993
goto error;
1994+
if (!compiler_visit_argannotations(c, args->posonlyargs, names))
1995+
goto error;
19941996
if (args->vararg && args->vararg->annotation &&
19951997
!compiler_visit_argannotation(c, args->vararg->arg,
19961998
args->vararg->annotation, names))

0 commit comments

Comments
 (0)