#define TEST_PREPROCESSOR_GUARDED_ELSE_METHODDEF
#endif /* !defined(TEST_PREPROCESSOR_GUARDED_ELSE_METHODDEF) */
/*[clinic end generated code: output=3804bb18d454038c input=3fc80c9989d2f2e1]*/
+
+/*[clinic input]
+test_vararg_and_posonly
+
+
+ a: object
+ *args: object
+ /
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_vararg_and_posonly__doc__,
+"test_vararg_and_posonly($module, a, /, *args)\n"
+"--\n"
+"\n");
+
+#define TEST_VARARG_AND_POSONLY_METHODDEF \
+ {"test_vararg_and_posonly", (PyCFunction)(void(*)(void))test_vararg_and_posonly, METH_FASTCALL, test_vararg_and_posonly__doc__},
+
+static PyObject *
+test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args);
+
+static PyObject *
+test_vararg_and_posonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *a;
+ PyObject *__clinic_args = NULL;
+
+ if (!_PyArg_CheckPositional("test_vararg_and_posonly", nargs, 1, PY_SSIZE_T_MAX)) {
+ goto exit;
+ }
+ a = args[0];
+ __clinic_args = PyTuple_New(nargs - 1);
+ for (Py_ssize_t i = 0; i < nargs - 1; ++i) {
+ PyTuple_SET_ITEM(__clinic_args, i, args[1 + i]);
+ }
+ return_value = test_vararg_and_posonly_impl(module, a, __clinic_args);
+
+exit:
+ Py_XDECREF(__clinic_args);
+ return return_value;
+}
+
+static PyObject *
+test_vararg_and_posonly_impl(PyObject *module, PyObject *a, PyObject *args)
+/*[clinic end generated code: output=ada613d2d87c9341 input=08dc2bf7afbf1613]*/
+
+/*[clinic input]
+test_vararg
+
+
+ a: object
+ *args: object
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_vararg__doc__,
+"test_vararg($module, /, a, *args)\n"
+"--\n"
+"\n");
+
+#define TEST_VARARG_METHODDEF \
+ {"test_vararg", (PyCFunction)(void(*)(void))test_vararg, METH_FASTCALL|METH_KEYWORDS, test_vararg__doc__},
+
+static PyObject *
+test_vararg_impl(PyObject *module, PyObject *a, PyObject *args);
+
+static PyObject *
+test_vararg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"a", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "test_vararg", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
+ PyObject *a;
+ PyObject *__clinic_args = NULL;
+
+ args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ a = args[0];
+ __clinic_args = args[1];
+ return_value = test_vararg_impl(module, a, __clinic_args);
+
+exit:
+ Py_XDECREF(__clinic_args);
+ return return_value;
+}
+
+static PyObject *
+test_vararg_impl(PyObject *module, PyObject *a, PyObject *args)
+/*[clinic end generated code: output=f721025731c3bfe8 input=81d33815ad1bae6e]*/
+
+/*[clinic input]
+test_vararg_with_default
+
+
+ a: object
+ *args: object
+ b: bool = False
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_vararg_with_default__doc__,
+"test_vararg_with_default($module, /, a, *args, b=False)\n"
+"--\n"
+"\n");
+
+#define TEST_VARARG_WITH_DEFAULT_METHODDEF \
+ {"test_vararg_with_default", (PyCFunction)(void(*)(void))test_vararg_with_default, METH_FASTCALL|METH_KEYWORDS, test_vararg_with_default__doc__},
+
+static PyObject *
+test_vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args,
+ int b);
+
+static PyObject *
+test_vararg_with_default(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"a", "b", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "test_vararg_with_default", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
+ PyObject *a;
+ PyObject *__clinic_args = NULL;
+ int b = 0;
+
+ args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, 1, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ a = args[0];
+ __clinic_args = args[1];
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ b = PyObject_IsTrue(args[2]);
+ if (b < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = test_vararg_with_default_impl(module, a, __clinic_args, b);
+
+exit:
+ Py_XDECREF(__clinic_args);
+ return return_value;
+}
+
+static PyObject *
+test_vararg_with_default_impl(PyObject *module, PyObject *a, PyObject *args,
+ int b)
+/*[clinic end generated code: output=63b34d3241c52fda input=6e110b54acd9b22d]*/
+
+/*[clinic input]
+test_vararg_with_only_defaults
+
+
+ *args: object
+ b: bool = False
+ c: object = ' '
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(test_vararg_with_only_defaults__doc__,
+"test_vararg_with_only_defaults($module, /, *args, b=False, c=\' \')\n"
+"--\n"
+"\n");
+
+#define TEST_VARARG_WITH_ONLY_DEFAULTS_METHODDEF \
+ {"test_vararg_with_only_defaults", (PyCFunction)(void(*)(void))test_vararg_with_only_defaults, METH_FASTCALL|METH_KEYWORDS, test_vararg_with_only_defaults__doc__},
+
+static PyObject *
+test_vararg_with_only_defaults_impl(PyObject *module, PyObject *args, int b,
+ PyObject *c);
+
+static PyObject *
+test_vararg_with_only_defaults(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"b", "c", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "test_vararg_with_only_defaults", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ PyObject *__clinic_args = NULL;
+ int b = 0;
+ PyObject *c = " ";
+
+ args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ __clinic_args = args[0];
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ if (args[1]) {
+ b = PyObject_IsTrue(args[1]);
+ if (b < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
+ }
+ c = args[2];
+skip_optional_kwonly:
+ return_value = test_vararg_with_only_defaults_impl(module, __clinic_args, b, c);
+
+exit:
+ Py_XDECREF(__clinic_args);
+ return return_value;
+}
+
+static PyObject *
+test_vararg_with_only_defaults_impl(PyObject *module, PyObject *args, int b,
+ PyObject *c)
+/*[clinic end generated code: output=dc29ce6ebc2ec10c input=fa56a709a035666e]*/
version = '1'
NoneType = type(None)
+NO_VARARG = "PY_SSIZE_T_MAX"
+CLINIC_PREFIX = "__clinic_"
+CLINIC_PREFIXED_ARGS = {"args"}
class Unspecified:
def __repr__(self):
new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
- pos_only = min_pos = max_pos = min_kw_only = 0
+ vararg = NO_VARARG
+ pos_only = min_pos = max_pos = min_kw_only = pseudo_args = 0
for i, p in enumerate(parameters, 1):
- if p.is_keyword_only():
+ if p.is_keyword_only() or vararg != NO_VARARG:
assert not p.is_positional_only()
if not p.is_optional():
min_kw_only = i - max_pos
+ elif p.is_vararg():
+ if vararg != NO_VARARG:
+ fail("Too many var args")
+ pseudo_args += 1
+ vararg = i - 1
else:
- max_pos = i
+ if vararg == NO_VARARG:
+ max_pos = i
if p.is_positional_only():
pos_only = i
if not p.is_optional():
parser_definition = parser_body(parser_prototype, ' {option_group_parsing}')
- elif not requires_defining_class and pos_only == len(parameters):
+ elif not requires_defining_class and pos_only == len(parameters) - pseudo_args:
if not new_or_init:
# positional-only, but no option groups
# we only need one call to _PyArg_ParseStack
nargs = 'PyTuple_GET_SIZE(args)'
argname_fmt = 'PyTuple_GET_ITEM(args, %d)'
+
+ left_args = "{} - {}".format(nargs, max_pos)
+ max_args = NO_VARARG if (vararg != NO_VARARG) else max_pos
parser_code = [normalize_snippet("""
- if (!_PyArg_CheckPositional("{name}", %s, %d, %d)) {{
+ if (!_PyArg_CheckPositional("{name}", %s, %d, %s)) {{
goto exit;
}}
- """ % (nargs, min_pos, max_pos), indent=4)]
+ """ % (nargs, min_pos, max_args), indent=4)]
+
has_optional = False
for i, p in enumerate(parameters):
displayname = p.get_displayname(i+1)
- parsearg = p.converter.parse_arg(argname_fmt % i, displayname)
+ argname = argname_fmt % i
+
+ if p.is_vararg():
+ if not new_or_init:
+ parser_code.append(normalize_snippet("""
+ %s = PyTuple_New(%s);
+ for (Py_ssize_t i = 0; i < %s; ++i) {{
+ PyTuple_SET_ITEM(%s, i, args[%d + i]);
+ }}
+ """ % (
+ p.converter.parser_name,
+ left_args,
+ left_args,
+ p.converter.parser_name,
+ max_pos
+ ), indent=4))
+ else:
+ parser_code.append(normalize_snippet("""
+ %s = PyTuple_GetSlice(%d, -1);
+ """ % (
+ p.converter.parser_name,
+ max_pos
+ ), indent=4))
+ continue
+
+ parsearg = p.converter.parse_arg(argname, displayname)
if parsearg is None:
#print('Cannot convert %s %r for %s' % (p.converter.__class__.__name__, p.converter.format_unit, p.converter.name), file=sys.stderr)
parser_code = None
else:
has_optional_kw = (max(pos_only, min_pos) + min_kw_only < len(converters))
+ if vararg == NO_VARARG:
+ args_declaration = "_PyArg_UnpackKeywords", "%s, %s, %s" % (
+ min_pos,
+ max_pos,
+ min_kw_only
+ )
+ else:
+ args_declaration = "_PyArg_UnpackKeywordsWithVararg", "%s, %s, %s, %s" % (
+ min_pos,
+ max_pos,
+ min_kw_only,
+ vararg
+ )
if not new_or_init:
flags = "METH_FASTCALL|METH_KEYWORDS"
parser_prototype = parser_prototype_fastcall_keywords
PyObject *argsbuf[%s];
""" % len(converters))
if has_optional_kw:
- declarations += "\nPy_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - %d;" % (min_pos + min_kw_only)
+ pre_buffer = "0" if vararg != NO_VARARG else "nargs"
+ declarations += "\nPy_ssize_t noptargs = %s + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - %d;" % (pre_buffer, min_pos + min_kw_only)
parser_code = [normalize_snippet("""
- args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, %d, %d, %d, argsbuf);
+ args = %s(args, nargs, NULL, kwnames, &_parser, %s, argsbuf);
if (!args) {{
goto exit;
}}
- """ % (min_pos, max_pos, min_kw_only), indent=4)]
+ """ % args_declaration, indent=4)]
else:
# positional-or-keyword arguments
flags = "METH_VARARGS|METH_KEYWORDS"
if has_optional_kw:
declarations += "\nPy_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - %d;" % (min_pos + min_kw_only)
parser_code = [normalize_snippet("""
- fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, %d, %d, %d, argsbuf);
+ fastargs = %s(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, %s, argsbuf);
if (!fastargs) {{
goto exit;
}}
- """ % (min_pos, max_pos, min_kw_only), indent=4)]
+ """ % args_declaration, indent=4)]
+
if requires_defining_class:
flags = 'METH_METHOD|' + flags
parser_prototype = parser_prototype_def_class
else:
label = 'skip_optional_kwonly'
first_opt = max_pos + min_kw_only
+ if vararg != NO_VARARG:
+ first_opt += 1
if i == first_opt:
add_label = label
parser_code.append(normalize_snippet("""
if (i != -1) and (p.default is not unspecified):
first_optional = min(first_optional, i)
+ if p.is_vararg():
+ data.cleanup.append("Py_XDECREF({});".format(c.parser_name))
+
# insert group variable
group = p.group
if last_group != group:
def is_positional_only(self):
return self.kind == inspect.Parameter.POSITIONAL_ONLY
+ def is_vararg(self):
+ return self.kind == inspect.Parameter.VAR_POSITIONAL
+
def is_optional(self):
- return (self.default is not unspecified)
+ return not self.is_vararg() and (self.default is not unspecified)
def copy(self, **overrides):
kwargs = {
def _render_self(self, parameter, data):
self.parameter = parameter
- name = self.name
+ name = self.parser_name
# impl_arguments
s = ("&" if self.impl_by_reference else "") + name
name = self.name
# declarations
- d = self.declaration()
+ d = self.declaration(in_parser=True)
data.declarations.append(d)
# initializers
data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
# keywords
- if parameter.is_positional_only():
+ if parameter.is_vararg():
+ pass
+ elif parameter.is_positional_only():
data.keywords.append('')
else:
data.keywords.append(parameter.name)
"""Computes the name of the associated "length" variable."""
if not self.length:
return None
- return self.name + "_length"
+ return self.parser_name + "_length"
# Why is this one broken out separately?
# For "positional-only" function parsing,
# All the functions after here are intended as extension points.
#
- def simple_declaration(self, by_reference=False):
+ def simple_declaration(self, by_reference=False, *, in_parser=False):
"""
Computes the basic declaration of the variable.
Used in computing the prototype declaration and the
prototype.append(" ")
if by_reference:
prototype.append('*')
- prototype.append(self.name)
+ if in_parser:
+ name = self.parser_name
+ else:
+ name = self.name
+ prototype.append(name)
return "".join(prototype)
- def declaration(self):
+ def declaration(self, *, in_parser=False):
"""
The C statement to declare this variable.
"""
- declaration = [self.simple_declaration()]
+ declaration = [self.simple_declaration(in_parser=True)]
default = self.c_default
if not default and self.parameter.group:
default = self.c_ignored_default
if (!{converter}({argname}, &{paramname})) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
converter=self.converter)
if self.format_unit == 'O!':
cast = '(%s)' % self.type if self.type != 'PyObject *' else ''
goto exit;
}}}}
{paramname} = {cast}{argname};
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname, typecheck=typecheck,
typename=typename, cast=cast)
return """
goto exit;
}}}}
{paramname} = {cast}{argname};
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
subclass_of=self.subclass_of, cast=cast,
displayname=displayname)
if self.format_unit == 'O':
cast = '(%s)' % self.type if self.type != 'PyObject *' else ''
return """
{paramname} = {cast}{argname};
- """.format(argname=argname, paramname=self.name, cast=cast)
+ """.format(argname=argname, paramname=self.parser_name, cast=cast)
return None
def set_template_dict(self, template_dict):
pass
+ @property
+ def parser_name(self):
+ if self.name in CLINIC_PREFIXED_ARGS: # bpo-39741
+ return CLINIC_PREFIX + self.name
+ else:
+ return self.name
type_checks = {
'&PyLong_Type': ('PyLong_Check', 'int'),
if ({paramname} == -1 && PyErr_Occurred()) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
elif self.format_unit == 'p':
return """
{paramname} = PyObject_IsTrue({argname});
if ({paramname} < 0) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
class defining_class_converter(CConverter):
_PyArg_BadArgument("{{name}}", {displayname}, "a byte string of length 1", {argname});
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname)
return super().parse_arg(argname, displayname)
{paramname} = (unsigned char) ival;
}}}}
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
elif self.format_unit == 'B':
return """
{{{{
{paramname} = (unsigned char) ival;
}}}}
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
class byte_converter(unsigned_char_converter): pass
{paramname} = (short) ival;
}}}}
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
class unsigned_short_converter(CConverter):
if ({paramname} == (unsigned short)-1 && PyErr_Occurred()) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
@add_legacy_c_converter('C', accept={str})
if ({paramname} == -1 && PyErr_Occurred()) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
elif self.format_unit == 'C':
return """
if (!PyUnicode_Check({argname})) {{{{
goto exit;
}}}}
{paramname} = PyUnicode_READ_CHAR({argname}, 0);
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname)
return super().parse_arg(argname, displayname)
if ({paramname} == (unsigned int)-1 && PyErr_Occurred()) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
class long_converter(CConverter):
if ({paramname} == -1 && PyErr_Occurred()) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
class unsigned_long_converter(CConverter):
goto exit;
}}}}
{paramname} = PyLong_AsUnsignedLongMask({argname});
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname)
return super().parse_arg(argname, displayname)
if ({paramname} == -1 && PyErr_Occurred()) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
class unsigned_long_long_converter(CConverter):
goto exit;
}}}}
{paramname} = PyLong_AsUnsignedLongLongMask({argname});
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname)
return super().parse_arg(argname, displayname)
}}}}
{paramname} = ival;
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
if ({paramname} == -1 && PyErr_Occurred()) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
goto exit;
}}}}
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
class double_converter(CConverter):
goto exit;
}}}}
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
if (PyErr_Occurred()) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name)
+ """.format(argname=argname, paramname=self.parser_name)
return super().parse_arg(argname, displayname)
PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname)
if self.format_unit == 'z':
return """
_PyArg_BadArgument("{{name}}", {displayname}, "str or None", {argname});
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname)
return super().parse_arg(argname, displayname)
goto exit;
}}}}
{paramname} = ({type}){argname};
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
type=self.type, displayname=displayname)
return super().parse_arg(argname, displayname)
goto exit;
}}}}
{paramname} = ({type}){argname};
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
type=self.type, displayname=displayname)
return super().parse_arg(argname, displayname)
goto exit;
}}}}
{paramname} = {argname};
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname)
return super().parse_arg(argname, displayname)
_PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname});
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname)
elif self.format_unit == 's*':
return """
goto exit;
}}}}
}}}}
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname)
elif self.format_unit == 'w*':
return """
_PyArg_BadArgument("{{name}}", {displayname}, "contiguous buffer", {argname});
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name,
+ """.format(argname=argname, paramname=self.parser_name,
displayname=displayname)
return super().parse_arg(argname, displayname)
def directive_dump(self, name):
self.block.output.append(self.clinic.get_destination(name).dump())
- def directive_print(self, *args):
+ def directive_printout(self, *args):
self.block.output.append(' '.join(args))
self.block.output.append('\n')
fail("Function " + self.function.name + " has an invalid parameter declaration (comma?):\n\t" + line)
if function_args.defaults or function_args.kw_defaults:
fail("Function " + self.function.name + " has an invalid parameter declaration (default value?):\n\t" + line)
- if function_args.vararg or function_args.kwarg:
- fail("Function " + self.function.name + " has an invalid parameter declaration (*args? **kwargs?):\n\t" + line)
+ if function_args.kwarg:
+ fail("Function " + self.function.name + " has an invalid parameter declaration (**kwargs?):\n\t" + line)
- parameter = function_args.args[0]
+ if function_args.vararg:
+ is_vararg = True
+ parameter = function_args.vararg
+ else:
+ is_vararg = False
+ parameter = function_args.args[0]
parameter_name = parameter.arg
name, legacy, kwargs = self.parse_converter(parameter.annotation)
if not default:
if self.parameter_state == self.ps_optional:
fail("Can't have a parameter without a default (" + repr(parameter_name) + ")\nafter a parameter with a default!")
- value = unspecified
+ if is_vararg:
+ value = NULL
+ kwargs.setdefault('c_default', "NULL")
+ else:
+ value = unspecified
if 'py_default' in kwargs:
fail("You can't specify py_default without specifying a default value!")
else:
+ if is_vararg:
+ fail("Vararg can't take a default value!")
+
if self.parameter_state == self.ps_required:
self.parameter_state = self.ps_optional
default = default.strip()
# but the parameter object gets the python name
converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs)
- kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
+ if is_vararg:
+ kind = inspect.Parameter.VAR_POSITIONAL
+ elif self.keyword_only:
+ kind = inspect.Parameter.KEYWORD_ONLY
+ else:
+ kind = inspect.Parameter.POSITIONAL_OR_KEYWORD
if isinstance(converter, self_converter):
if len(self.function.parameters) == 1:
fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
# fixup preceding parameters
for p in self.function.parameters.values():
+ if p.is_vararg():
+ continue
if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
p.kind = inspect.Parameter.POSITIONAL_ONLY
# calling the class to construct a new instance.
p_add('$')
+ if p.is_vararg():
+ p_add("*")
+
name = p.converter.signature_name or p.name
p_add(name)
- if p.converter.is_optional():
+ if not p.is_vararg() and p.converter.is_optional():
p_add('=')
value = p.converter.py_default
if not value: