Commit 086f4098 authored by Stefan Behnel's avatar Stefan Behnel

almost complete in-place implementation of Python's ParseTupleAndKeywords()

use argument exception messages from Python 2.6
TODO: handling of keyword-only arguments seems to require more work
TODO: clean up helper functions (currently somewhat redundant)
parent 5091aefd
......@@ -1336,17 +1336,18 @@ class DefNode(FuncDefNode):
self.declare_pyfunction(env)
self.analyse_signature(env)
self.return_type = self.entry.signature.return_type()
env.use_utility_code(raise_argtuple_too_long_utility_code)
env.use_utility_code(keyword_check_utility_code)
env.use_utility_code(check_double_keywords_utility_code)
if self.signature_has_generic_args():
if self.star_arg:
env.use_utility_code(get_stararg_utility_code)
elif self.signature_has_generic_args():
env.use_utility_code(raise_argtuple_too_long_utility_code)
if not self.signature_has_nongeneric_args():
env.use_utility_code(get_keyword_string_check_utility_code)
env.use_utility_code(keyword_string_check_utility_code)
elif self.starstar_arg:
env.use_utility_code(get_splitkeywords_utility_code)
env.use_utility_code(split_keywords_utility_code)
if self.num_required_kw_args:
env.use_utility_code(get_checkkeywords_utility_code)
env.use_utility_code(check_keywords_utility_code)
def analyse_signature(self, env):
any_type_tests_needed = 0
......@@ -1644,7 +1645,7 @@ class DefNode(FuncDefNode):
if has_star_or_kw_args:
self.generate_stararg_getting_code(code)
self.generate_argument_tuple_parsing_code(
self.generate_tuple_and_keyword_parsing_code(
positional_args, arg_formats, arg_addrs, code)
code.error_label = old_error_label
......@@ -1663,7 +1664,7 @@ class DefNode(FuncDefNode):
code.putln("return %s;" % self.error_value())
code.put_label(end_label)
def generate_argument_tuple_parsing_code(self, positional_args,
def _generate_argument_tuple_parsing_code(self, positional_args,
arg_formats, arg_addrs, code):
# Unpack inplace if it's simple
if not self.num_required_kw_args:
......@@ -1689,20 +1690,7 @@ class DefNode(FuncDefNode):
code.putln('if (PyTuple_GET_SIZE(%s) > %s) {' % (Naming.args_cname, i))
closing += 1
item = "PyTuple_GET_ITEM(%s, %s)" % (Naming.args_cname, i)
if arg.type.is_pyobject:
if arg.is_generic:
item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
code.putln("%s = %s;" % (arg.entry.cname, item))
else:
func = arg.type.from_py_function
if func:
code.putln("%s = %s(%s); %s" % (
arg.entry.cname,
func,
item,
code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
else:
error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
self.generate_arg_assignment(arg, item, code)
i += 1
for _ in range(closing):
code.putln('}')
......@@ -1722,6 +1710,22 @@ class DefNode(FuncDefNode):
if not self.num_required_kw_args:
code.putln('}')
def generate_arg_assignment(self, arg, item, code):
if arg.type.is_pyobject:
if arg.is_generic:
item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
code.putln("%s = %s;" % (arg.entry.cname, item))
else:
func = arg.type.from_py_function
if func:
code.putln("%s = %s(%s); %s" % (
arg.entry.cname,
func,
item,
code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
else:
error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
def put_stararg_decrefs(self, code):
if self.star_arg:
code.put_decref(Naming.args_cname, py_object_type)
......@@ -1778,8 +1782,7 @@ class DefNode(FuncDefNode):
code.put_incref(Naming.args_cname, py_object_type)
code.put("%s = %s; " % (star_arg_cname, Naming.empty_tuple))
code.put_incref(Naming.empty_tuple, py_object_type)
code.putln("}")
code.putln("else {")
code.putln("} else {")
code.putln(
"if (unlikely(__Pyx_SplitStarArg(&%s, %d, &%s) < 0)) return %s;" % (
Naming.args_cname,
......@@ -1788,7 +1791,7 @@ class DefNode(FuncDefNode):
self.error_value()))
code.putln("}")
self.star_arg.entry.xdecref_cleanup = 0
elif self.signature_has_generic_args():
else:
# make sure supernumerous positional arguments do not run
# into keyword-only arguments and provide a more helpful
# message than PyArg_ParseTupelAndKeywords()
......@@ -1798,18 +1801,31 @@ class DefNode(FuncDefNode):
if self.starstar_arg:
handle_error = 1
code.put(
"if (unlikely(__Pyx_SplitKeywords(&%s, %s, &%s, %s) < 0)) " % (
'if (unlikely(__Pyx_SplitKeywords(&%s, %s, &%s, %s, PyTuple_GET_SIZE(%s), "%s") < 0)) ' % (
Naming.kwds_cname,
Naming.kwdlist_cname,
self.starstar_arg.entry.cname,
self.reqd_kw_flags_cname))
self.reqd_kw_flags_cname,
Naming.args_cname,
self.name.utf8encode()))
self.starstar_arg.entry.xdecref_cleanup = 0
elif self.num_required_kw_args:
handle_error = 1
code.put("if (unlikely(__Pyx_CheckRequiredKeywords(%s, %s, %s) < 0)) " % (
code.put('if (unlikely(__Pyx_CheckRequiredKeywords(%s, %s, %s, PyTuple_GET_SIZE(%s), "%s") < 0)) ' % (
Naming.kwds_cname,
Naming.kwdlist_cname,
self.reqd_kw_flags_cname,
Naming.args_cname,
self.name.utf8encode()))
else:
# check that positional arguments are not passed as keywords also
handle_error = 1
code.put('if (unlikely(%s) && unlikely(__Pyx_CheckDoubleKeywords(%s, %s, PyTuple_GET_SIZE(%s), "%s") < 0)) ' % (
Naming.kwds_cname,
Naming.kwds_cname,
Naming.kwdlist_cname,
self.reqd_kw_flags_cname))
Naming.args_cname,
self.name.utf8encode()))
if handle_error:
if self.star_arg:
......@@ -1821,11 +1837,109 @@ class DefNode(FuncDefNode):
else:
code.putln(error_return)
def generate_tuple_and_keyword_parsing_code(self, positional_args,
arg_formats, arg_addrs, code):
min_positional_args = self.num_required_args - self.num_required_kw_args
if len(self.args) > 0 and self.args[0].is_self_arg:
min_positional_args -= 1
max_positional_args = len(positional_args)
# just a quick check to start with
if not self.star_arg:
code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > %d)) {" % (
Naming.args_cname, max_positional_args))
code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, PyTuple_GET_SIZE(%s)); ' % (
self.name.utf8encode(), min_positional_args,
max_positional_args, Naming.args_cname))
code.putln(code.error_goto(self.pos))
code.putln("}")
# --- optimised code when we receive keyword arguments
code.putln("if (unlikely(%s) && (PyDict_Size(%s) > 0)) {" % (
Naming.kwds_cname, Naming.kwds_cname))
code.putln("PyObject* values[%d];" % max_positional_args)
code.putln("Py_ssize_t kw_args = PyDict_Size(%s), arg;" %
Naming.kwds_cname)
code.putln("for (arg=0; arg < PyTuple_GET_SIZE(%s); arg++) {" %
Naming.args_cname)
code.putln("values[arg] = PyTuple_GET_ITEM(%s, arg);" %
Naming.args_cname)
code.putln("if (unlikely(PyDict_GetItemString(%s, %s[arg]))) {" % (
Naming.kwds_cname, Naming.kwdlist_cname))
code.put( '__Pyx_RaiseDoubleKeywordsError("%s", %s[arg]); ' % (
self.name.utf8encode(), Naming.kwdlist_cname))
code.putln(code.error_goto(self.pos))
code.putln('}')
code.putln('}')
code.putln("for (arg=PyTuple_GET_SIZE(%s); arg < %d; arg++) {" % (
Naming.args_cname, max_positional_args))
code.putln('values[arg] = PyDict_GetItemString(%s, %s[arg]);' % (
Naming.kwds_cname, Naming.kwdlist_cname))
code.putln('if (values[arg]) kw_args--;');
code.putln('}')
code.putln('if (unlikely(kw_args > 0)) {')
code.put('if (!__Pyx_CheckKeywords(%s, "%s", %s)) ' % (
Naming.kwds_cname, self.name.utf8encode(), Naming.kwdlist_cname))
code.putln(code.error_goto(self.pos))
code.putln('}')
default_seen = False
for i, arg in enumerate(positional_args):
if arg.default:
default_seen = True
if default_seen:
code.putln("if (values[%d]) {" % i)
self.generate_arg_assignment(arg, "values[%d]" % i, code)
if default_seen:
if not arg.default:
code.putln('} else {')
code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d); ' % (
self.name.utf8encode(), min_positional_args,
max_positional_args, i))
code.putln(code.error_goto(self.pos))
code.putln('}')
# --- optimised code when we did not receive any keyword arguments
code.putln('} else if (unlikely(PyTuple_GET_SIZE(%s) < %d)) {' % (
Naming.args_cname, min_positional_args))
code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, PyTuple_GET_SIZE(%s)); ' % (
self.name.utf8encode(), min_positional_args,
max_positional_args, Naming.args_cname))
code.putln(code.error_goto(self.pos))
code.putln('} else {')
closing = 0
for i, arg in enumerate(positional_args):
if arg.default:
code.putln('if (PyTuple_GET_SIZE(%s) > %s) {' % (Naming.args_cname, i))
closing += 1
item = "PyTuple_GET_ITEM(%s, %s)" % (Naming.args_cname, i)
self.generate_arg_assignment(arg, item, code)
for _ in range(closing):
code.putln('}')
code.putln('}')
return
argformat = '"%s"' % string.join(arg_formats, "")
pt_arglist = [Naming.args_cname, Naming.kwds_cname, argformat, Naming.kwdlist_cname] + arg_addrs
pt_argstring = string.join(pt_arglist, ", ")
code.putln(
'if (unlikely(!PyArg_ParseTupleAndKeywords(%s))) %s' % (
pt_argstring,
code.error_goto(self.pos)))
self.generate_argument_conversion_code(code)
code.putln('}')
def generate_positional_args_check(self, code, nargs):
code.putln("if (unlikely(PyTuple_GET_SIZE(%s) > %d)) {" % (
Naming.args_cname, nargs))
code.putln("__Pyx_RaiseArgtupleTooLong(%d, PyTuple_GET_SIZE(%s));" % (
nargs, Naming.args_cname))
code.putln('__Pyx_RaiseArgtupleInvalid("%s", 0, %d, PyTuple_GET_SIZE(%s));' % (
self.name.utf8encode(), nargs, Naming.args_cname))
code.putln("return %s;" % self.error_value())
code.putln("}")
......@@ -4267,25 +4381,42 @@ static INLINE int __Pyx_SplitStarArg(
#------------------------------------------------------------------------------------
#
# __Pyx_RaiseArgtupleTooLong raises the correct exception when too
# many positional arguments were found. This handles Py_ssize_t
# formatting correctly.
# __Pyx_RaiseArgtupleInvalid raises the correct exception when too
# many or too few positional arguments were found. This handles
# Py_ssize_t formatting correctly.
raise_argtuple_too_long_utility_code = [
"""
static INLINE void __Pyx_RaiseArgtupleTooLong(Py_ssize_t num_expected, Py_ssize_t num_found); /*proto*/
static INLINE void __Pyx_RaiseArgtupleInvalid(char* func_name,
Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
""","""
static INLINE void __Pyx_RaiseArgtupleTooLong(
Py_ssize_t num_expected,
static INLINE void __Pyx_RaiseArgtupleInvalid(
char* func_name,
Py_ssize_t num_min,
Py_ssize_t num_max,
Py_ssize_t num_found)
{
const char* error_message =
#if PY_VERSION_HEX < 0x02050000
"function takes at most %d positional arguments (%d given)";
#else
"function takes at most %zd positional arguments (%zd given)";
#endif
PyErr_Format(PyExc_TypeError, error_message, num_expected, num_found);
if (num_found < num_min) {
PyErr_Format(PyExc_TypeError,
#if PY_VERSION_HEX < 0x02050000
"%s() takes at least %d positional arguments (%d given)",
#elif PY_MAJOR_VERSION >= 3
"%U() takes at most %zd positional arguments (%zd given)",
#else
"%s() takes at least %zd positional arguments (%zd given)",
#endif
func_name, num_min, num_found);
} else {
PyErr_Format(PyExc_TypeError,
#if PY_VERSION_HEX < 0x02050000
"%s() takes at most %d positional arguments (%d given)",
#elif PY_MAJOR_VERSION >= 3
"%U() takes at most %zd positional arguments (%zd given)",
#else
"%s() takes at most %zd positional arguments (%zd given)",
#endif
func_name, num_max, num_found);
}
}
"""]
......@@ -4295,7 +4426,7 @@ static INLINE void __Pyx_RaiseArgtupleTooLong(
# were passed to a function, or if any keywords were passed to a
# function that does not accept them.
get_keyword_string_check_utility_code = [
keyword_string_check_utility_code = [
"""
static int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); /*proto*/
""","""
......@@ -4332,6 +4463,68 @@ static int __Pyx_CheckKeywordStrings(
}
"""]
#------------------------------------------------------------------------------------
#
# __Pyx_CheckKeywords raises an error if non-string keywords were
# passed to a function, or if any unsupported keywords were passed to
# a function.
keyword_check_utility_code = [
"""
static int __Pyx_CheckKeywords(PyObject *kwdict, const char* function_name,
char** argnames); /*proto*/
""","""
static int __Pyx_CheckKeywords(
PyObject *kwdict,
const char* function_name,
char** argnames)
{
PyObject* key = 0;
Py_ssize_t pos = 0;
char** name;
while (PyDict_Next(kwdict, &pos, &key, 0)) {
#if PY_MAJOR_VERSION < 3
if (unlikely(!PyString_Check(key))) {
#else
if (unlikely(!PyUnicode_Check(key))) {
#endif
PyErr_Format(PyExc_TypeError,
"%s() keywords must be strings", function_name);
return 0;
} else if (argnames) {
name = argnames;
while (*name) {
#if PY_MAJOR_VERSION >= 3
PyObject* utf8_key = PyUnicode_AsUTF8String(key);
if (!utf8_key) return -1;
if (strcmp(*name, PyString_AS_STRING(utf8_key)) == 0) {
Py_DECREF(utf8_key);
break;
}
Py_DECREF(utf8_key);
#else
if (strcmp(*name, PyString_AS_STRING(key)) == 0)
break;
#endif
name++;
}
if (!*name) {
PyErr_Format(PyExc_TypeError,
#if PY_MAJOR_VERSION < 3
"'%s' is an invalid keyword argument for this function",
PyString_AS_STRING(key));
#else
"'%U' is an invalid keyword argument for this function",
key);
#endif
return 0;
}
}
}
return 1;
}
"""]
#------------------------------------------------------------------------------------
#
# __Pyx_SplitKeywords splits the kwds dict into two parts one part
......@@ -4349,17 +4542,24 @@ static int __Pyx_CheckKeywordStrings(
# the names in kwd_list, indicating required keyword arguments. If
# any of these are not present in kwds, an exception is raised.
#
# If num_posargs is greater 0, it denotes the number of positional
# arguments that were passed and that must therefore not get passed
# as keyword arguments as well.
#
get_splitkeywords_utility_code = [
split_keywords_utility_code = [
"""
static int __Pyx_SplitKeywords(PyObject **kwds, char *kwd_list[], \
PyObject **kwds2, char rqd_kwds[]); /*proto*/
PyObject **kwds2, char rqd_kwds[],
Py_ssize_t num_posargs, char* func_name); /*proto*/
""","""
static int __Pyx_SplitKeywords(
PyObject **kwds,
char *kwd_list[],
PyObject **kwds2,
char rqd_kwds[])
char rqd_kwds[],
Py_ssize_t num_posargs,
char* func_name)
{
PyObject *s = 0, *x = 0, *kwds1 = 0;
int i;
......@@ -4380,6 +4580,8 @@ static int __Pyx_SplitKeywords(
#endif
x = PyDict_GetItem(*kwds, s);
if (x) {
if (i < num_posargs)
goto arg_passed_twice;
if (PyDict_SetItem(kwds1, s, x) < 0)
goto bad;
if (PyDict_DelItem(*kwds2, s) < 0)
......@@ -4404,6 +4606,10 @@ static int __Pyx_SplitKeywords(
*kwds = kwds1;
return 0;
arg_passed_twice:
PyErr_Format(PyExc_TypeError,
"%s() got multiple values for keyword argument '%s'", func_name, *p);
goto bad;
missing_kwarg:
PyErr_Format(PyExc_TypeError,
"required keyword argument '%s' is missing", *p);
......@@ -4415,23 +4621,32 @@ bad:
}
"""]
get_checkkeywords_utility_code = [
check_keywords_utility_code = [
"""
static INLINE int __Pyx_CheckRequiredKeywords(PyObject *kwds, char *kwd_list[],
char rqd_kwds[]); /*proto*/
char rqd_kwds[], Py_ssize_t num_posargs, char* func_name); /*proto*/
""","""
static INLINE int __Pyx_CheckRequiredKeywords(
PyObject *kwds,
char *kwd_list[],
char rqd_kwds[])
char rqd_kwds[],
Py_ssize_t num_posargs,
char* func_name)
{
int i;
char **p;
if (kwds) {
for (i = 0, p = kwd_list; *p; i++, p++)
p = kwd_list;
for (i=0; i < num_posargs && *p; i++, p++) {
if (PyDict_GetItemString(kwds, *p))
goto arg_passed_twice;
}
while (*p) {
if (rqd_kwds[i] && !PyDict_GetItemString(kwds, *p))
goto missing_kwarg;
i++; p++;
}
}
else {
for (i = 0, p = kwd_list; *p; i++, p++)
......@@ -4440,6 +4655,10 @@ static INLINE int __Pyx_CheckRequiredKeywords(
}
return 0;
arg_passed_twice:
PyErr_Format(PyExc_TypeError,
"%s() got multiple values for keyword argument '%s'", func_name, *p);
return -1;
missing_kwarg:
PyErr_Format(PyExc_TypeError,
"required keyword argument '%s' is missing", *p);
......@@ -4447,6 +4666,36 @@ missing_kwarg:
}
"""]
check_double_keywords_utility_code = [
"""
static INLINE int __Pyx_CheckDoubleKeywords(PyObject *kwds, char *kwd_list[],
Py_ssize_t num_posargs, const char* func_name); /*proto*/
static int __Pyx_RaiseDoubleKeywordsError(const char* func_name,
const char* kw_name); /*proto*/
""","""
static INLINE int __Pyx_CheckDoubleKeywords(
PyObject *kwds,
char *kwd_list[],
Py_ssize_t num_posargs,
const char* func_name)
{
int i;
char** p = kwd_list;
for (i=0; i < num_posargs && *p; i++, p++) {
if (PyDict_GetItemString(kwds, *p))
return __Pyx_RaiseDoubleKeywordsError(func_name, *p);
}
return 0;
}
static int __Pyx_RaiseDoubleKeywordsError(const char* func_name, const char* kw_name) {
PyErr_Format(PyExc_TypeError,
"%s() got multiple values for keyword argument '%s'", func_name, kw_name);
return -1;
}
"""]
#------------------------------------------------------------------------------------
unraisable_exception_utility_code = [
......
def f(*args, **kwargs):
pass
args = (1,2,3)
kwargs = {u"test" : "toast"}
def test():
f(*args, 1, 2, 3)
f(**kwargs, 1, 2, c=3)
f(*args, **kwargs, *args)
f(1, 2, c=3, *args, **kwargs, *args)
f(1, 2, c=3, *args, d=5, **kwargs, **kwargs)
f(1, 2, c=3, *args, d=5, **kwargs, x=6)
f(1=2)
# too bad we don't get more errors here ...
_ERRORS = u"""
8:13: Non-keyword arg following star-arg
"""
__doc__ = u"""
>>> test()
1 2 3 * 0 0
1 2 3 * 0 0
1 2 9 * 2 1
1 2 7 * 2 1
1 2 9 * 2 2
1 2 9 * 2 2
1 2 9 * 2 3
"""
def f(a, b, c, *args, **kwargs):
print a, b, c, u'*', len(args), len(kwargs)
args = (9,8,7)
import sys
if sys.version_info[0] >= 3:
kwargs = {u"test" : u"toast"}
else:
kwargs = {"test" : u"toast"}
def test():
f(1,2,3)
f(1,2, c=3)
f(1,2, d=3, *args)
f(1,2, d=3, *(7,8,9))
f(1,2, d=3, *args, **kwargs)
f(1,2, d=3, *args, e=5)
f(1,2, d=3, *args, e=5, **kwargs)
......@@ -5,20 +5,20 @@ __doc__ = u"""
>>> b(1,2,3)
>>> b(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes exactly 4 arguments (5 given)
TypeError: b() takes at most 4 positional arguments (5 given)
>>> c(1,2)
>>> c(1,2,3)
>>> c(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes at most 4 arguments (5 given)
TypeError: c() takes at most 4 positional arguments (5 given)
>>> d(1,2)
>>> d(1,2, c=1)
>>> d(1,2,3)
Traceback (most recent call last):
TypeError: function takes at most 3 positional arguments (4 given)
TypeError: d() takes at most 3 positional arguments (4 given)
>>> d(1,2, d=1)
Traceback (most recent call last):
TypeError: 'd' is an invalid keyword argument for this function
......@@ -30,14 +30,14 @@ __doc__ = u"""
>>> e(1,2,3)
>>> e(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes at most 4 positional arguments (5 given)
TypeError: e() takes at most 4 positional arguments (5 given)
>>> f(1,2, c=1)
>>> f(1,2, c=1, d=2)
>>> f(1,2,3)
Traceback (most recent call last):
TypeError: function takes at most 3 positional arguments (4 given)
TypeError: f() takes at most 3 positional arguments (4 given)
>>> f(1,2)
Traceback (most recent call last):
TypeError: required keyword argument 'c' is missing
......@@ -51,7 +51,7 @@ __doc__ = u"""
>>> g(1,2,3) #doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: function takes at most 3 positional arguments (4 given)
TypeError: g() takes at most 3 positional arguments (4 given)
>>> g(1,2)
Traceback (most recent call last):
TypeError: required keyword argument 'c' is missing
......
......@@ -5,20 +5,20 @@ __doc__ = u"""
>>> b(1,2,3)
>>> b(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes exactly 3 arguments (4 given)
TypeError: b() takes at most 3 positional arguments (4 given)
>>> c(1,2)
>>> c(1,2,3)
>>> c(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes at most 3 arguments (4 given)
TypeError: c() takes at most 3 positional arguments (4 given)
>>> d(1,2)
>>> d(1,2, c=1)
>>> d(1,2,3)
Traceback (most recent call last):
TypeError: function takes at most 2 positional arguments (3 given)
TypeError: d() takes at most 2 positional arguments (3 given)
>>> d(1,2, d=1)
Traceback (most recent call last):
TypeError: 'd' is an invalid keyword argument for this function
......@@ -30,14 +30,14 @@ __doc__ = u"""
>>> e(1,2,3)
>>> e(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes at most 3 positional arguments (4 given)
TypeError: e() takes at most 3 positional arguments (4 given)
>>> f(1,2, c=1)
>>> f(1,2, c=1, d=2)
>>> f(1,2,3)
Traceback (most recent call last):
TypeError: function takes at most 2 positional arguments (3 given)
TypeError: f() takes at most 2 positional arguments (3 given)
>>> f(1,2)
Traceback (most recent call last):
TypeError: required keyword argument 'c' is missing
......@@ -51,7 +51,7 @@ __doc__ = u"""
>>> g(1,2,3)
Traceback (most recent call last):
TypeError: function takes at most 2 positional arguments (3 given)
TypeError: g() takes at most 2 positional arguments (3 given)
>>> g(1,2)
Traceback (most recent call last):
TypeError: required keyword argument 'c' is missing
......@@ -84,10 +84,6 @@ __doc__ = u"""
TypeError: required keyword argument 'f' is missing
"""
import sys, re
if sys.version_info >= (2,6):
__doc__ = re.sub(u"Error: (.*)exactly(.*)", u"Error: \\1at most\\2", __doc__)
cdef class Ext:
def b(self, a, b, c):
pass
......
......@@ -7,10 +7,10 @@ __doc__ = u"""
(1, 2, 3)
>>> spam(1,2) #doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: function takes exactly 3 arguments (2 given)
TypeError: spam() takes at least 3 positional arguments (2 given)
>>> spam(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes exactly 3 arguments (4 given)
TypeError: spam() takes at most 3 positional arguments (4 given)
>>> spam(1,2,3, a=1) #doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: 'a' is an invalid keyword argument for this function
......@@ -23,7 +23,7 @@ __doc__ = u"""
(1, 2, 3, (4, 5, 6, 7, 8, 9))
>>> grail(1,2) #doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: function takes exactly 3 arguments (2 given)
TypeError: grail() takes exactly 3 arguments (2 given)
>>> grail(1,2,3, a=1) #doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: 'a' is an invalid keyword argument for this function
......@@ -32,7 +32,7 @@ __doc__ = u"""
(1, 2, 3, ())
>>> swallow(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes at most 3 positional arguments (4 given)
TypeError: swallow() takes at most 3 positional arguments (4 given)
>>> swallow(1,2,3, a=1, b=2)
(1, 2, 3, (('a', 1), ('b', 2)))
>>> swallow(1,2,3, x=1) #doctest: +ELLIPSIS
......@@ -68,13 +68,13 @@ __doc__ = u"""
(('a', 1), ('b', 2))
>>> onlyk(1)
Traceback (most recent call last):
TypeError: function takes at most 0 positional arguments (1 given)
TypeError: onlyk() takes at most 0 positional arguments (1 given)
>>> onlyk(1, 2)
Traceback (most recent call last):
TypeError: function takes at most 0 positional arguments (2 given)
TypeError: onlyk() takes at most 0 positional arguments (2 given)
>>> onlyk(1, a=1, b=2)
Traceback (most recent call last):
TypeError: function takes at most 0 positional arguments (1 given)
TypeError: onlyk() takes at most 0 positional arguments (1 given)
>>> tk(a=1)
(('a', 1),)
......@@ -88,10 +88,6 @@ __doc__ = u"""
(1, ('a', 1), ('b', 2))
"""
import sys, re
if sys.version_info >= (2,6):
__doc__ = re.sub(u"Error: (.*)exactly(.*)", u"Error: \\1at most\\2", __doc__)
import sys, re
if sys.version_info >= (2,6):
__doc__ = re.sub(u"(ELLIPSIS[^>]*Error: )[^\n]*\n", u"\\1...\n", __doc__, re.M)
......
......@@ -2,20 +2,20 @@ __doc__ = u"""
>>> b(1,2,3)
>>> b(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes exactly 3 arguments (4 given)
TypeError: b() takes at most 3 positional arguments (4 given)
>>> c(1,2)
>>> c(1,2,3)
>>> c(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes at most 3 arguments (4 given)
TypeError: c() takes at most 3 positional arguments (4 given)
>>> d(1,2)
>>> d(1,2, c=1)
>>> d(1,2,3)
Traceback (most recent call last):
TypeError: function takes at most 2 positional arguments (3 given)
TypeError: d() takes at most 2 positional arguments (3 given)
>>> d(1,2, d=1)
Traceback (most recent call last):
TypeError: 'd' is an invalid keyword argument for this function
......@@ -27,14 +27,14 @@ __doc__ = u"""
>>> e(1,2,3)
>>> e(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes at most 3 positional arguments (4 given)
TypeError: e() takes at most 3 positional arguments (4 given)
>>> f(1,2, c=1)
>>> f(1,2, c=1, d=2)
>>> f(1,2,3)
Traceback (most recent call last):
TypeError: function takes at most 2 positional arguments (3 given)
TypeError: f() takes at most 2 positional arguments (3 given)
>>> f(1,2)
Traceback (most recent call last):
TypeError: required keyword argument 'c' is missing
......@@ -48,7 +48,7 @@ __doc__ = u"""
>>> g(1,2,3)
Traceback (most recent call last):
TypeError: function takes at most 2 positional arguments (3 given)
TypeError: g() takes at most 2 positional arguments (3 given)
>>> g(1,2)
Traceback (most recent call last):
TypeError: required keyword argument 'c' is missing
......@@ -81,10 +81,6 @@ __doc__ = u"""
TypeError: required keyword argument 'f' is missing
"""
import sys, re
if sys.version_info >= (2,6):
__doc__ = re.sub(u"Error: (.*)exactly(.*)", u"Error: \\1at most\\2", __doc__)
def b(a, b, c):
pass
......
......@@ -2,20 +2,20 @@ __doc__ = u"""
>>> call3(b)
>>> call4(b)
Traceback (most recent call last):
TypeError: function takes exactly 3 arguments (4 given)
TypeError: b() takes at most 3 positional arguments (4 given)
>>> call2(c)
>>> call3(c)
>>> call4(c)
Traceback (most recent call last):
TypeError: function takes at most 3 arguments (4 given)
TypeError: c() takes at most 3 positional arguments (4 given)
>>> call2(d)
>>> call2c(d)
>>> call3(d)
Traceback (most recent call last):
TypeError: function takes at most 2 positional arguments (3 given)
TypeError: d() takes at most 2 positional arguments (3 given)
>>> call2d(d)
Traceback (most recent call last):
TypeError: 'd' is an invalid keyword argument for this function
......@@ -27,14 +27,14 @@ __doc__ = u"""
>>> call3(e)
>>> call4(e)
Traceback (most recent call last):
TypeError: function takes at most 3 positional arguments (4 given)
TypeError: e() takes at most 3 positional arguments (4 given)
>>> call2c(f)
>>> call2cd(f)
>>> call3(f)
Traceback (most recent call last):
TypeError: function takes at most 2 positional arguments (3 given)
TypeError: f() takes at most 2 positional arguments (3 given)
>>> call2(f)
Traceback (most recent call last):
TypeError: required keyword argument 'c' is missing
......@@ -48,7 +48,7 @@ __doc__ = u"""
>>> call3(g)
Traceback (most recent call last):
TypeError: function takes at most 2 positional arguments (3 given)
TypeError: g() takes at most 2 positional arguments (3 given)
>>> call2(g)
Traceback (most recent call last):
TypeError: required keyword argument 'c' is missing
......@@ -132,6 +132,10 @@ def call2cefd(f):
def call2cfex(f):
f(1,2, c=1, f=2, e=0, x=25)
def call6argscfexy(f):
args = (1,2,3,4,5,6)
f(*args, c=1, f=2, e=3, x=25, y=11)
def call6cfexy(f):
f(1,2,3,4,5,6, c=1, f=2, e=3, x=25, y=11)
......
......@@ -3,10 +3,10 @@ __doc__ = u"""
(1, 2, 3)
>>> spam(1,2) #doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: function takes exactly 3 arguments (2 given)
TypeError: spam() takes at least 3 positional arguments (2 given)
>>> spam(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes exactly 3 arguments (4 given)
TypeError: spam() takes at most 3 positional arguments (4 given)
>>> spam(1,2,3, a=1) #doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: 'a' is an invalid keyword argument for this function
......@@ -19,7 +19,7 @@ __doc__ = u"""
(1, 2, 3, (4, 5, 6, 7, 8, 9))
>>> grail(1,2) #doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: function takes exactly 3 arguments (2 given)
TypeError: grail() takes at least 3 positional arguments (2 given)
>>> grail(1,2,3, a=1) #doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: 'a' is an invalid keyword argument for this function
......@@ -28,7 +28,7 @@ __doc__ = u"""
(1, 2, 3, ())
>>> swallow(1,2,3,4)
Traceback (most recent call last):
TypeError: function takes at most 3 positional arguments (4 given)
TypeError: swallow() takes at most 3 positional arguments (4 given)
>>> swallow(1,2,3, a=1, b=2)
(1, 2, 3, (('a', 1), ('b', 2)))
>>> swallow(1,2,3, x=1) #doctest: +ELLIPSIS
......@@ -64,13 +64,13 @@ __doc__ = u"""
(('a', 1), ('b', 2))
>>> onlyk(1)
Traceback (most recent call last):
TypeError: function takes at most 0 positional arguments (1 given)
TypeError: onlyk() takes at most 0 positional arguments (1 given)
>>> onlyk(1, 2)
Traceback (most recent call last):
TypeError: function takes at most 0 positional arguments (2 given)
TypeError: onlyk() takes at most 0 positional arguments (2 given)
>>> onlyk(1, a=1, b=2)
Traceback (most recent call last):
TypeError: function takes at most 0 positional arguments (1 given)
TypeError: onlyk() takes at most 0 positional arguments (1 given)
>>> tk(a=1)
(('a', 1),)
......@@ -84,10 +84,6 @@ __doc__ = u"""
(1, ('a', 1), ('b', 2))
"""
import sys, re
if sys.version_info >= (2,6):
__doc__ = re.sub(u"Error: (.*)exactly(.*)", u"Error: \\1at most\\2", __doc__)
import sys, re
if sys.version_info >= (2,6):
__doc__ = re.sub(u"(ELLIPSIS[^>]*Error: )[^\n]*\n", u"\\1...\n", __doc__, re.M)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment