Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
e109c708
Kaydet (Commit)
e109c708
authored
Haz 24, 2011
tarafından
Benjamin Peterson
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
give the names of missing positional or keyword-only arguments (closes #12356)
üst
947d6b04
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
199 additions
and
94 deletions
+199
-94
inspect.py
Lib/inspect.py
+29
-12
test_extcall.py
Lib/test/test_extcall.py
+48
-59
NEWS
Misc/NEWS
+4
-0
ceval.c
Python/ceval.c
+118
-23
No files found.
Lib/inspect.py
Dosyayı görüntüle @
e109c708
...
...
@@ -918,10 +918,24 @@ def formatargvalues(args, varargs, varkw, locals,
specs
.
append
(
formatvarkw
(
varkw
)
+
formatvalue
(
locals
[
varkw
]))
return
'('
+
', '
.
join
(
specs
)
+
')'
def
_positional_error
(
f_name
,
args
,
kwonly
,
varargs
,
defcount
,
given
,
values
):
def
_missing_arguments
(
f_name
,
argnames
,
pos
,
values
):
names
=
[
repr
(
name
)
for
name
in
argnames
if
name
not
in
values
]
missing
=
len
(
names
)
if
missing
==
1
:
s
=
names
[
0
]
elif
missing
==
2
:
s
=
"{} and {}"
.
format
(
*
names
)
else
:
tail
=
", {} and {}"
.
format
(
names
[
-
2
:])
del
names
[
-
2
:]
s
=
", "
.
join
(
names
)
+
tail
raise
TypeError
(
"
%
s() missing
%
i required
%
s argument
%
s:
%
s"
%
(
f_name
,
missing
,
"positional"
if
pos
else
"keyword-only"
,
""
if
missing
==
1
else
"s"
,
s
))
def
_too_many
(
f_name
,
args
,
kwonly
,
varargs
,
defcount
,
given
,
values
):
atleast
=
len
(
args
)
-
defcount
if
given
is
None
:
given
=
len
([
arg
for
arg
in
args
if
arg
in
values
])
kwonly_given
=
len
([
arg
for
arg
in
kwonly
if
arg
in
values
])
if
varargs
:
plural
=
atleast
!=
1
...
...
@@ -980,22 +994,25 @@ def getcallargs(func, *positional, **named):
(
f_name
,
kw
))
arg2value
[
kw
]
=
value
if
num_pos
>
num_args
and
not
varargs
:
_
positional_error
(
f_name
,
args
,
kwonlyargs
,
varargs
,
num_defaults
,
num_pos
,
arg2value
)
_
too_many
(
f_name
,
args
,
kwonlyargs
,
varargs
,
num_defaults
,
num_pos
,
arg2value
)
if
num_pos
<
num_args
:
for
arg
in
args
[:
num_args
-
num_defaults
]:
req
=
args
[:
num_args
-
num_defaults
]
for
arg
in
req
:
if
arg
not
in
arg2value
:
_positional_error
(
f_name
,
args
,
kwonlyargs
,
varargs
,
num_defaults
,
None
,
arg2value
)
_missing_arguments
(
f_name
,
req
,
True
,
arg2value
)
for
i
,
arg
in
enumerate
(
args
[
num_args
-
num_defaults
:]):
if
arg
not
in
arg2value
:
arg2value
[
arg
]
=
defaults
[
i
]
missing
=
0
for
kwarg
in
kwonlyargs
:
if
kwarg
not
in
arg2value
:
if
kwarg
not
in
kwonlydefaults
:
raise
TypeError
(
"
%
s() requires keyword-only argument
%
r"
%
(
f_name
,
kwarg
))
arg2value
[
kwarg
]
=
kwonlydefaults
[
kwarg
]
if
kwarg
in
kwonlydefaults
:
arg2value
[
kwarg
]
=
kwonlydefaults
[
kwarg
]
else
:
missing
+=
1
if
missing
:
_missing_arguments
(
f_name
,
kwonlyargs
,
False
,
arg2value
)
return
arg2value
# -------------------------------------------------- stack frame extraction
...
...
Lib/test/test_extcall.py
Dosyayı görüntüle @
e109c708
...
...
@@ -66,17 +66,17 @@ Verify clearing of SF bug #733667
>>> g()
Traceback (most recent call last):
...
TypeError: g()
takes at least 1 positional argument but 0 were given
TypeError: g()
missing 1 required positional argument: 'x'
>>> g(*())
Traceback (most recent call last):
...
TypeError: g()
takes at least 1 positional argument but 0 were given
TypeError: g()
missing 1 required positional argument: 'x'
>>> g(*(), **{})
Traceback (most recent call last):
...
TypeError: g()
takes at least 1 positional argument but 0 were given
TypeError: g()
missing 1 required positional argument: 'x'
>>> g(1)
1 () {}
...
...
@@ -263,91 +263,80 @@ the function call setup. See <http://bugs.python.org/issue2016>.
>>> f(**x)
1 2
Some additional tests about positional argument error
s:
Too many argument
s:
>>> def f(a, b):
... pass
>>> f(b=1)
>>> def f(): pass
>>> f(1)
Traceback (most recent call last):
...
TypeError: f() takes 2 positional arguments but 1 was given
>>> def f(a):
... pass
>>> f(6, a=4, *(1, 2, 3))
TypeError: f() takes 0 positional arguments but 1 was given
>>> def f(a): pass
>>> f(1, 2)
Traceback (most recent call last):
...
TypeError: f() got multiple values for argument 'a'
>>> def f(a, *, kw):
... pass
>>> f(6, 4, kw=4)
TypeError: f() takes 1 positional argument but 2 were given
>>> def f(a, b=1): pass
>>> f(1, 2, 3)
Traceback (most recent call last):
...
TypeError: f() takes 1 positional argument but 2 positional arguments (and 1 keyword-only argument) were given
>>> def f(a):
... pass
>>> f()
TypeError: f() takes from 1 to 2 positional arguments but 3 were given
>>> def f(*, kw): pass
>>> f(1, kw=3)
Traceback (most recent call last):
...
TypeError: f() takes 1 positional argument but 0 were given
>>> def f(a, b):
... pass
>>> f(1)
TypeError: f() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
>>> def f(*, kw, b): pass
>>> f(1, 2, 3, b=3, kw=3)
Traceback (most recent call last):
...
TypeError: f() takes 0 positional arguments but 3 positional arguments (and 2 keyword-only arguments) were given
>>> def f(a, b=2, *, kw): pass
>>> f(2, 3, 4, kw=4)
Traceback (most recent call last):
...
TypeError: f() takes
2 positional arguments but 1 was
given
TypeError: f() takes
from 1 to 2 positional arguments but 3 positional arguments (and 1 keyword-only argument) were
given
>>> def f(a, *b):
... pass
Too few and missing arguments:
>>> def f(a): pass
>>> f()
Traceback (most recent call last):
...
TypeError: f() takes at least 1 positional argument but 0 were given
>>> def f(a, *, kw=4):
... pass
>>> f(kw=4)
TypeError: f() missing 1 required positional argument: 'a'
>>> def f(a, b): pass
>>> f()
Traceback (most recent call last):
...
TypeError: f() takes 1 positional argument but 0 positional arguments (and 1 keyword-only argument) were given
>>> def f(a, b=2):
... pass
TypeError: f() missing 2 required positional arguments: 'a' and 'b'
>>> def f(a, b, c): pass
>>> f()
Traceback (most recent call last):
...
TypeError: f() takes from 1 to 2 positional arguments but 0 were given
>>> def f(a, *b):
... pass
TypeError: f() missing 3 required positional arguments: 'a', 'b', and 'c'
>>> def f(a, b, c, d, e): pass
>>> f()
Traceback (most recent call last):
...
TypeError: f() takes at least 1 positional argument but 0 were given
>>> def f(*, kw):
... pass
>>> f(3, kw=4)
TypeError: f() missing 5 required positional arguments: 'a', 'b', 'c', 'd', and 'e'
>>> def f(a, b=4, c=5, d=5): pass
>>> f(c=12, b=9)
Traceback (most recent call last):
...
TypeError: f()
takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
TypeError: f()
missing 1 required positional argument: 'a'
>>> def f(a, c=3, *b, kw):
... pass
Same with keyword only args:
>>> def f(*, w): pass
>>> f()
Traceback (most recent call last):
...
TypeError: f() takes at least 1 positional argument but 0 were given
>>> f(kw=3)
Traceback (most recent call last):
...
TypeError: f() takes at least 1 positional argument but 0 positional arguments (and 1 keyword-only argument) were given
>>> f(kw=3, c=4)
...
TypeError: f() missing 1 required keyword-only argument: 'w'
>>> def f(*, a, b, c, d, e): pass
>>> f()
Traceback (most recent call last):
...
TypeError: f() takes at least 1 positional argument but 1 positional argument (and 1 keyword-only argument) were given
...
TypeError: f() missing 5 required keyword-only arguments: 'a', 'b', 'c', 'd', and 'e'
"""
import
sys
...
...
Misc/NEWS
Dosyayı görüntüle @
e109c708
...
...
@@ -10,6 +10,10 @@ What's New in Python 3.3 Alpha 1?
Core and Builtins
-----------------
- Issue #12356: When required positional or keyword-only arguments are not
given, produce a informative error message which includes the name(s) of the
missing arguments.
- Issue #12370: Fix super with not arguments when __class__ is overriden in the
class body.
...
...
Python/ceval.c
Dosyayı görüntüle @
e109c708
...
...
@@ -3046,28 +3046,118 @@ exit_eval_frame:
}
static
void
positional_argument_error
(
PyCodeObject
*
co
,
int
given
,
int
defcount
,
PyObject
**
fastlocals
)
format_missing
(
const
char
*
kind
,
PyCodeObject
*
co
,
PyObject
*
names
)
{
int
err
;
Py_ssize_t
len
=
PyList_GET_SIZE
(
names
);
PyObject
*
name_str
,
*
comma
,
*
tail
,
*
tmp
;
assert
(
PyList_CheckExact
(
names
));
assert
(
len
>=
1
);
/* Deal with the joys of natural language. */
switch
(
len
)
{
case
1
:
name_str
=
PyList_GET_ITEM
(
names
,
0
);
Py_INCREF
(
name_str
);
break
;
case
2
:
name_str
=
PyUnicode_FromFormat
(
"%U and %U"
,
PyList_GET_ITEM
(
names
,
len
-
2
),
PyList_GET_ITEM
(
names
,
len
-
1
));
break
;
default:
tail
=
PyUnicode_FromFormat
(
", %U, and %U"
,
PyList_GET_ITEM
(
names
,
len
-
2
),
PyList_GET_ITEM
(
names
,
len
-
1
));
/* Chop off the last two objects in the list. This shouldn't actually
fail, but we can't be too careful. */
err
=
PyList_SetSlice
(
names
,
len
-
2
,
len
,
NULL
);
if
(
err
==
-
1
)
{
Py_DECREF
(
tail
);
return
;
}
/* Stitch everything up into a nice comma-separated list. */
comma
=
PyUnicode_FromString
(
", "
);
if
(
comma
==
NULL
)
{
Py_DECREF
(
tail
);
return
;
}
tmp
=
PyUnicode_Join
(
comma
,
names
);
Py_DECREF
(
comma
);
if
(
tmp
==
NULL
)
{
Py_DECREF
(
tail
);
return
;
}
name_str
=
PyUnicode_Concat
(
tmp
,
tail
);
Py_DECREF
(
tmp
);
Py_DECREF
(
tail
);
break
;
}
if
(
name_str
==
NULL
)
return
;
PyErr_Format
(
PyExc_TypeError
,
"%U() missing %i required %s argument%s: %U"
,
co
->
co_name
,
len
,
kind
,
len
==
1
?
""
:
"s"
,
name_str
);
Py_DECREF
(
name_str
);
}
static
void
missing_arguments
(
PyCodeObject
*
co
,
int
missing
,
int
defcount
,
PyObject
**
fastlocals
)
{
int
i
,
j
=
0
;
int
start
,
end
;
int
positional
=
defcount
!=
-
1
;
const
char
*
kind
=
positional
?
"positional"
:
"keyword-only"
;
PyObject
*
missing_names
;
/* Compute the names of the arguments that are missing. */
missing_names
=
PyList_New
(
missing
);
if
(
missing_names
==
NULL
)
return
;
if
(
positional
)
{
start
=
0
;
end
=
co
->
co_argcount
-
defcount
;
}
else
{
start
=
co
->
co_argcount
;
end
=
start
+
co
->
co_kwonlyargcount
;
}
for
(
i
=
start
;
i
<
end
;
i
++
)
{
if
(
GETLOCAL
(
i
)
==
NULL
)
{
PyObject
*
raw
=
PyTuple_GET_ITEM
(
co
->
co_varnames
,
i
);
PyObject
*
name
=
PyObject_Repr
(
raw
);
if
(
name
==
NULL
)
{
Py_DECREF
(
missing_names
);
return
;
}
PyList_SET_ITEM
(
missing_names
,
j
++
,
name
);
}
}
assert
(
j
==
missing
);
format_missing
(
kind
,
co
,
missing_names
);
Py_DECREF
(
missing_names
);
}
static
void
too_many_positional
(
PyCodeObject
*
co
,
int
given
,
int
defcount
,
PyObject
**
fastlocals
)
{
int
plural
;
int
kwonly_given
=
0
;
int
atleast
=
co
->
co_argcount
-
defcount
;
int
i
;
PyObject
*
sig
,
*
kwonly_sig
;
if
(
given
==
-
1
)
{
given
=
0
;
for
(
i
=
0
;
i
<
co
->
co_argcount
;
i
++
)
if
(
GETLOCAL
(
i
))
given
++
;
}
assert
((
co
->
co_flags
&
CO_VARARGS
)
==
0
);
/* Count missing keyword-only args. */
for
(
i
=
co
->
co_argcount
;
i
<
co
->
co_argcount
+
co
->
co_kwonlyargcount
;
i
++
)
if
(
GETLOCAL
(
i
))
if
(
GETLOCAL
(
i
)
!=
NULL
)
kwonly_given
++
;
if
(
co
->
co_flags
&
CO_VARARGS
)
{
plural
=
atleast
!=
1
;
sig
=
PyUnicode_FromFormat
(
"at least %d"
,
atleast
);
}
else
if
(
defcount
)
{
if
(
defcount
)
{
int
atleast
=
co
->
co_argcount
-
defcount
;
plural
=
1
;
sig
=
PyUnicode_FromFormat
(
"from %d to %d"
,
atleast
,
co
->
co_argcount
);
}
...
...
@@ -3089,6 +3179,7 @@ positional_argument_error(PyCodeObject *co, int given, int defcount, PyObject **
else
{
/* This will not fail. */
kwonly_sig
=
PyUnicode_FromString
(
""
);
assert
(
kwonly_sig
!=
NULL
);
}
PyErr_Format
(
PyExc_TypeError
,
"%U() takes %U positional argument%s but %d%U %s given"
,
...
...
@@ -3217,16 +3308,18 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
SETLOCAL
(
j
,
value
);
}
if
(
argcount
>
co
->
co_argcount
&&
!
(
co
->
co_flags
&
CO_VARARGS
))
{
positional_argument_error
(
co
,
argcount
,
defcount
,
fastlocals
);
too_many_positional
(
co
,
argcount
,
defcount
,
fastlocals
);
goto
fail
;
}
if
(
argcount
<
co
->
co_argcount
)
{
int
m
=
co
->
co_argcount
-
defcount
;
for
(
i
=
argcount
;
i
<
m
;
i
++
)
{
if
(
GETLOCAL
(
i
)
==
NULL
)
{
positional_argument_error
(
co
,
-
1
,
defcount
,
fastlocals
);
goto
fail
;
}
int
missing
=
0
;
for
(
i
=
argcount
;
i
<
m
;
i
++
)
if
(
GETLOCAL
(
i
)
==
NULL
)
missing
++
;
if
(
missing
)
{
missing_arguments
(
co
,
missing
,
defcount
,
fastlocals
);
goto
fail
;
}
if
(
n
>
m
)
i
=
n
-
m
;
...
...
@@ -3241,6 +3334,7 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
}
}
if
(
co
->
co_kwonlyargcount
>
0
)
{
int
missing
=
0
;
for
(
i
=
co
->
co_argcount
;
i
<
total_args
;
i
++
)
{
PyObject
*
name
;
if
(
GETLOCAL
(
i
)
!=
NULL
)
...
...
@@ -3254,9 +3348,10 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
continue
;
}
}
PyErr_Format
(
PyExc_TypeError
,
"%U() requires keyword-only argument '%S'"
,
co
->
co_name
,
name
);
missing
++
;
}
if
(
missing
)
{
missing_arguments
(
co
,
missing
,
-
1
,
fastlocals
);
goto
fail
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment