Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e109c70

Browse files
committed
give the names of missing positional or keyword-only arguments (closes #12356)
1 parent 947d6b0 commit e109c70

4 files changed

Lines changed: 199 additions & 94 deletions

File tree

Lib/inspect.py

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -918,10 +918,24 @@ def convert(name, locals=locals,
918918
specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
919919
return '(' + ', '.join(specs) + ')'
920920

921-
def _positional_error(f_name, args, kwonly, varargs, defcount, given, values):
921+
def _missing_arguments(f_name, argnames, pos, values):
922+
names = [repr(name) for name in argnames if name not in values]
923+
missing = len(names)
924+
if missing == 1:
925+
s = names[0]
926+
elif missing == 2:
927+
s = "{} and {}".format(*names)
928+
else:
929+
tail = ", {} and {}".format(names[-2:])
930+
del names[-2:]
931+
s = ", ".join(names) + tail
932+
raise TypeError("%s() missing %i required %s argument%s: %s" %
933+
(f_name, missing,
934+
"positional" if pos else "keyword-only",
935+
"" if missing == 1 else "s", s))
936+
937+
def _too_many(f_name, args, kwonly, varargs, defcount, given, values):
922938
atleast = len(args) - defcount
923-
if given is None:
924-
given = len([arg for arg in args if arg in values])
925939
kwonly_given = len([arg for arg in kwonly if arg in values])
926940
if varargs:
927941
plural = atleast != 1
@@ -980,22 +994,25 @@ def getcallargs(func, *positional, **named):
980994
(f_name, kw))
981995
arg2value[kw] = value
982996
if num_pos > num_args and not varargs:
983-
_positional_error(f_name, args, kwonlyargs, varargs, num_defaults,
984-
num_pos, arg2value)
997+
_too_many(f_name, args, kwonlyargs, varargs, num_defaults,
998+
num_pos, arg2value)
985999
if num_pos < num_args:
986-
for arg in args[:num_args - num_defaults]:
1000+
req = args[:num_args - num_defaults]
1001+
for arg in req:
9871002
if arg not in arg2value:
988-
_positional_error(f_name, args, kwonlyargs, varargs,
989-
num_defaults, None, arg2value)
1003+
_missing_arguments(f_name, req, True, arg2value)
9901004
for i, arg in enumerate(args[num_args - num_defaults:]):
9911005
if arg not in arg2value:
9921006
arg2value[arg] = defaults[i]
1007+
missing = 0
9931008
for kwarg in kwonlyargs:
9941009
if kwarg not in arg2value:
995-
if kwarg not in kwonlydefaults:
996-
raise TypeError("%s() requires keyword-only argument %r" %
997-
(f_name, kwarg))
998-
arg2value[kwarg] = kwonlydefaults[kwarg]
1010+
if kwarg in kwonlydefaults:
1011+
arg2value[kwarg] = kwonlydefaults[kwarg]
1012+
else:
1013+
missing += 1
1014+
if missing:
1015+
_missing_arguments(f_name, kwonlyargs, False, arg2value)
9991016
return arg2value
10001017

10011018
# -------------------------------------------------- stack frame extraction

Lib/test/test_extcall.py

Lines changed: 48 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,17 @@
6666
>>> g()
6767
Traceback (most recent call last):
6868
...
69-
TypeError: g() takes at least 1 positional argument but 0 were given
69+
TypeError: g() missing 1 required positional argument: 'x'
7070
7171
>>> g(*())
7272
Traceback (most recent call last):
7373
...
74-
TypeError: g() takes at least 1 positional argument but 0 were given
74+
TypeError: g() missing 1 required positional argument: 'x'
7575
7676
>>> g(*(), **{})
7777
Traceback (most recent call last):
7878
...
79-
TypeError: g() takes at least 1 positional argument but 0 were given
79+
TypeError: g() missing 1 required positional argument: 'x'
8080
8181
>>> g(1)
8282
1 () {}
@@ -263,91 +263,80 @@
263263
>>> f(**x)
264264
1 2
265265
266-
Some additional tests about positional argument errors:
266+
Too many arguments:
267267
268-
>>> def f(a, b):
269-
... pass
270-
>>> f(b=1)
268+
>>> def f(): pass
269+
>>> f(1)
271270
Traceback (most recent call last):
272271
...
273-
TypeError: f() takes 2 positional arguments but 1 was given
274-
275-
>>> def f(a):
276-
... pass
277-
>>> f(6, a=4, *(1, 2, 3))
272+
TypeError: f() takes 0 positional arguments but 1 was given
273+
>>> def f(a): pass
274+
>>> f(1, 2)
278275
Traceback (most recent call last):
279276
...
280-
TypeError: f() got multiple values for argument 'a'
281-
>>> def f(a, *, kw):
282-
... pass
283-
>>> f(6, 4, kw=4)
277+
TypeError: f() takes 1 positional argument but 2 were given
278+
>>> def f(a, b=1): pass
279+
>>> f(1, 2, 3)
284280
Traceback (most recent call last):
285281
...
286-
TypeError: f() takes 1 positional argument but 2 positional arguments (and 1 keyword-only argument) were given
287-
288-
>>> def f(a):
289-
... pass
290-
>>> f()
282+
TypeError: f() takes from 1 to 2 positional arguments but 3 were given
283+
>>> def f(*, kw): pass
284+
>>> f(1, kw=3)
291285
Traceback (most recent call last):
292286
...
293-
TypeError: f() takes 1 positional argument but 0 were given
294-
295-
>>> def f(a, b):
296-
... pass
297-
>>> f(1)
287+
TypeError: f() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
288+
>>> def f(*, kw, b): pass
289+
>>> f(1, 2, 3, b=3, kw=3)
290+
Traceback (most recent call last):
291+
...
292+
TypeError: f() takes 0 positional arguments but 3 positional arguments (and 2 keyword-only arguments) were given
293+
>>> def f(a, b=2, *, kw): pass
294+
>>> f(2, 3, 4, kw=4)
298295
Traceback (most recent call last):
299296
...
300-
TypeError: f() takes 2 positional arguments but 1 was given
297+
TypeError: f() takes from 1 to 2 positional arguments but 3 positional arguments (and 1 keyword-only argument) were given
301298
302-
>>> def f(a, *b):
303-
... pass
299+
Too few and missing arguments:
300+
301+
>>> def f(a): pass
304302
>>> f()
305303
Traceback (most recent call last):
306304
...
307-
TypeError: f() takes at least 1 positional argument but 0 were given
308-
309-
>>> def f(a, *, kw=4):
310-
... pass
311-
>>> f(kw=4)
305+
TypeError: f() missing 1 required positional argument: 'a'
306+
>>> def f(a, b): pass
307+
>>> f()
312308
Traceback (most recent call last):
313309
...
314-
TypeError: f() takes 1 positional argument but 0 positional arguments (and 1 keyword-only argument) were given
315-
316-
>>> def f(a, b=2):
317-
... pass
310+
TypeError: f() missing 2 required positional arguments: 'a' and 'b'
311+
>>> def f(a, b, c): pass
318312
>>> f()
319313
Traceback (most recent call last):
320314
...
321-
TypeError: f() takes from 1 to 2 positional arguments but 0 were given
322-
323-
>>> def f(a, *b):
324-
... pass
315+
TypeError: f() missing 3 required positional arguments: 'a', 'b', and 'c'
316+
>>> def f(a, b, c, d, e): pass
325317
>>> f()
326318
Traceback (most recent call last):
327319
...
328-
TypeError: f() takes at least 1 positional argument but 0 were given
329-
330-
>>> def f(*, kw):
331-
... pass
332-
>>> f(3, kw=4)
320+
TypeError: f() missing 5 required positional arguments: 'a', 'b', 'c', 'd', and 'e'
321+
>>> def f(a, b=4, c=5, d=5): pass
322+
>>> f(c=12, b=9)
333323
Traceback (most recent call last):
334324
...
335-
TypeError: f() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
325+
TypeError: f() missing 1 required positional argument: 'a'
336326
337-
>>> def f(a, c=3, *b, kw):
338-
... pass
327+
Same with keyword only args:
328+
329+
>>> def f(*, w): pass
339330
>>> f()
340331
Traceback (most recent call last):
341-
...
342-
TypeError: f() takes at least 1 positional argument but 0 were given
343-
>>> f(kw=3)
344-
Traceback (most recent call last):
345-
...
346-
TypeError: f() takes at least 1 positional argument but 0 positional arguments (and 1 keyword-only argument) were given
347-
>>> f(kw=3, c=4)
332+
...
333+
TypeError: f() missing 1 required keyword-only argument: 'w'
334+
>>> def f(*, a, b, c, d, e): pass
335+
>>> f()
348336
Traceback (most recent call last):
349-
...
350-
TypeError: f() takes at least 1 positional argument but 1 positional argument (and 1 keyword-only argument) were given
337+
...
338+
TypeError: f() missing 5 required keyword-only arguments: 'a', 'b', 'c', 'd', and 'e'
339+
351340
"""
352341

353342
import sys

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ What's New in Python 3.3 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #12356: When required positional or keyword-only arguments are not
14+
given, produce a informative error message which includes the name(s) of the
15+
missing arguments.
16+
1317
- Issue #12370: Fix super with not arguments when __class__ is overriden in the
1418
class body.
1519

0 commit comments

Comments
 (0)