Issue #20294: Argument Clinic now supports argument parsing for __new__ and
__init__ functions.
This commit is contained in:
parent
b470575e24
commit
b7ccb20423
@ -784,8 +784,8 @@ Argument Clinic converters. On the left is the legacy converter,
|
|||||||
on the right is the text you'd replace it with.
|
on the right is the text you'd replace it with.
|
||||||
|
|
||||||
========= =================================================================================
|
========= =================================================================================
|
||||||
``'B'`` ``byte(bitwise=True)``
|
``'B'`` ``unsigned_char(bitwise=True)``
|
||||||
``'b'`` ``byte``
|
``'b'`` ``unsigned_char``
|
||||||
``'c'`` ``char``
|
``'c'`` ``char``
|
||||||
``'C'`` ``int(types='str')``
|
``'C'`` ``int(types='str')``
|
||||||
``'d'`` ``double``
|
``'d'`` ``double``
|
||||||
@ -1275,6 +1275,25 @@ any arguments.
|
|||||||
You can still use a self converter, a return converter, and specify
|
You can still use a self converter, a return converter, and specify
|
||||||
a ``type`` argument to the object converter for ``METH_O``.
|
a ``type`` argument to the object converter for ``METH_O``.
|
||||||
|
|
||||||
|
tp_new and tp_init functions
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
You can convert ``tp_new`` and ``tp_init``
|
||||||
|
functions. Just name them ``__new__`` or
|
||||||
|
``__init__`` as appropriate. Notes:
|
||||||
|
|
||||||
|
* The function name generated for ``__new__`` doesn't end in ``__new__``
|
||||||
|
like it would by default. It's just the name of the class, converted
|
||||||
|
into a valid C identifier.
|
||||||
|
|
||||||
|
* No ``PyMethodDef`` ``#define`` is generated for these functions.
|
||||||
|
|
||||||
|
* ``__init__`` functions return ``int``, not ``PyObject *``.
|
||||||
|
|
||||||
|
* Argument Clinic supports any signature for these functions, even though
|
||||||
|
the parsing function is required to always take ``args`` and ``kwargs``
|
||||||
|
objects.
|
||||||
|
|
||||||
The #ifdef trick
|
The #ifdef trick
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...);
|
|||||||
#endif
|
#endif
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
PyAPI_FUNC(int) _PyArg_NoKeywords(const char *funcname, PyObject *kw);
|
PyAPI_FUNC(int) _PyArg_NoKeywords(const char *funcname, PyObject *kw);
|
||||||
|
PyAPI_FUNC(int) _PyArg_NoPositional(const char *funcname, PyObject *args);
|
||||||
|
|
||||||
PyAPI_FUNC(int) PyArg_VaParse(PyObject *, const char *, va_list);
|
PyAPI_FUNC(int) PyArg_VaParse(PyObject *, const char *, va_list);
|
||||||
PyAPI_FUNC(int) PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,
|
PyAPI_FUNC(int) PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,
|
||||||
|
@ -101,6 +101,9 @@ Tests
|
|||||||
Tools/Demos
|
Tools/Demos
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
- Issue #20294: Argument Clinic now supports argument parsing for __new__ and
|
||||||
|
__init__ functions.
|
||||||
|
|
||||||
- Issue #20299: Argument Clinic custom converters may now change the default
|
- Issue #20299: Argument Clinic custom converters may now change the default
|
||||||
value of c_default and py_default with a class member.
|
value of c_default and py_default with a class member.
|
||||||
|
|
||||||
|
@ -4064,13 +4064,13 @@ PyDoc_STRVAR(_pickle_Pickler___init____doc__,
|
|||||||
"to map the new Python 3 names to the old module names used in Python\n"
|
"to map the new Python 3 names to the old module names used in Python\n"
|
||||||
"2, so that the pickle data stream is readable with Python 2.");
|
"2, so that the pickle data stream is readable with Python 2.");
|
||||||
|
|
||||||
static PyObject *
|
static int
|
||||||
_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *protocol, int fix_imports);
|
_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *protocol, int fix_imports);
|
||||||
|
|
||||||
static PyObject *
|
static int
|
||||||
_pickle_Pickler___init__(PyObject *self, PyObject *args, PyObject *kwargs)
|
_pickle_Pickler___init__(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
int return_value = -1;
|
||||||
static char *_keywords[] = {"file", "protocol", "fix_imports", NULL};
|
static char *_keywords[] = {"file", "protocol", "fix_imports", NULL};
|
||||||
PyObject *file;
|
PyObject *file;
|
||||||
PyObject *protocol = NULL;
|
PyObject *protocol = NULL;
|
||||||
@ -4086,9 +4086,9 @@ exit:
|
|||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static int
|
||||||
_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *protocol, int fix_imports)
|
_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *protocol, int fix_imports)
|
||||||
/*[clinic end generated code: checksum=defa3d9e9f8b51fb257d4fdfca99db503db0e6df]*/
|
/*[clinic end generated code: checksum=10c8ea05194d08108471163d8202cf5e12975544]*/
|
||||||
{
|
{
|
||||||
_Py_IDENTIFIER(persistent_id);
|
_Py_IDENTIFIER(persistent_id);
|
||||||
_Py_IDENTIFIER(dispatch_table);
|
_Py_IDENTIFIER(dispatch_table);
|
||||||
@ -4098,16 +4098,16 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *pro
|
|||||||
(void)Pickler_clear(self);
|
(void)Pickler_clear(self);
|
||||||
|
|
||||||
if (_Pickler_SetProtocol(self, protocol, fix_imports) < 0)
|
if (_Pickler_SetProtocol(self, protocol, fix_imports) < 0)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
if (_Pickler_SetOutputStream(self, file) < 0)
|
if (_Pickler_SetOutputStream(self, file) < 0)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
/* memo and output_buffer may have already been created in _Pickler_New */
|
/* memo and output_buffer may have already been created in _Pickler_New */
|
||||||
if (self->memo == NULL) {
|
if (self->memo == NULL) {
|
||||||
self->memo = PyMemoTable_New();
|
self->memo = PyMemoTable_New();
|
||||||
if (self->memo == NULL)
|
if (self->memo == NULL)
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
self->output_len = 0;
|
self->output_len = 0;
|
||||||
if (self->output_buffer == NULL) {
|
if (self->output_buffer == NULL) {
|
||||||
@ -4115,7 +4115,7 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *pro
|
|||||||
self->output_buffer = PyBytes_FromStringAndSize(NULL,
|
self->output_buffer = PyBytes_FromStringAndSize(NULL,
|
||||||
self->max_output_len);
|
self->max_output_len);
|
||||||
if (self->output_buffer == NULL)
|
if (self->output_buffer == NULL)
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->fast = 0;
|
self->fast = 0;
|
||||||
@ -4126,31 +4126,20 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *pro
|
|||||||
self->pers_func = _PyObject_GetAttrId((PyObject *)self,
|
self->pers_func = _PyObject_GetAttrId((PyObject *)self,
|
||||||
&PyId_persistent_id);
|
&PyId_persistent_id);
|
||||||
if (self->pers_func == NULL)
|
if (self->pers_func == NULL)
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
self->dispatch_table = NULL;
|
self->dispatch_table = NULL;
|
||||||
if (_PyObject_HasAttrId((PyObject *)self, &PyId_dispatch_table)) {
|
if (_PyObject_HasAttrId((PyObject *)self, &PyId_dispatch_table)) {
|
||||||
self->dispatch_table = _PyObject_GetAttrId((PyObject *)self,
|
self->dispatch_table = _PyObject_GetAttrId((PyObject *)self,
|
||||||
&PyId_dispatch_table);
|
&PyId_dispatch_table);
|
||||||
if (self->dispatch_table == NULL)
|
if (self->dispatch_table == NULL)
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wrap the Clinic generated signature to slot it in tp_init. */
|
|
||||||
static int
|
|
||||||
Pickler_init(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
||||||
{
|
|
||||||
PyObject *result = _pickle_Pickler___init__(self, args, kwargs);
|
|
||||||
if (result == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Py_DECREF(result);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Define a proxy object for the Pickler's internal memo object. This is to
|
/* Define a proxy object for the Pickler's internal memo object. This is to
|
||||||
* avoid breaking code like:
|
* avoid breaking code like:
|
||||||
* pickler.memo.clear()
|
* pickler.memo.clear()
|
||||||
@ -4543,7 +4532,7 @@ static PyTypeObject Pickler_Type = {
|
|||||||
0, /*tp_descr_get*/
|
0, /*tp_descr_get*/
|
||||||
0, /*tp_descr_set*/
|
0, /*tp_descr_set*/
|
||||||
0, /*tp_dictoffset*/
|
0, /*tp_dictoffset*/
|
||||||
Pickler_init, /*tp_init*/
|
_pickle_Pickler___init__, /*tp_init*/
|
||||||
PyType_GenericAlloc, /*tp_alloc*/
|
PyType_GenericAlloc, /*tp_alloc*/
|
||||||
PyType_GenericNew, /*tp_new*/
|
PyType_GenericNew, /*tp_new*/
|
||||||
PyObject_GC_Del, /*tp_free*/
|
PyObject_GC_Del, /*tp_free*/
|
||||||
@ -6614,13 +6603,13 @@ PyDoc_STRVAR(_pickle_Unpickler___init____doc__,
|
|||||||
"respectively. The *encoding* can be \'bytes\' to read these 8-bit\n"
|
"respectively. The *encoding* can be \'bytes\' to read these 8-bit\n"
|
||||||
"string instances as bytes objects.");
|
"string instances as bytes objects.");
|
||||||
|
|
||||||
static PyObject *
|
static int
|
||||||
_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_imports, const char *encoding, const char *errors);
|
_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_imports, const char *encoding, const char *errors);
|
||||||
|
|
||||||
static PyObject *
|
static int
|
||||||
_pickle_Unpickler___init__(PyObject *self, PyObject *args, PyObject *kwargs)
|
_pickle_Unpickler___init__(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
int return_value = -1;
|
||||||
static char *_keywords[] = {"file", "fix_imports", "encoding", "errors", NULL};
|
static char *_keywords[] = {"file", "fix_imports", "encoding", "errors", NULL};
|
||||||
PyObject *file;
|
PyObject *file;
|
||||||
int fix_imports = 1;
|
int fix_imports = 1;
|
||||||
@ -6637,9 +6626,9 @@ exit:
|
|||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static int
|
||||||
_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_imports, const char *encoding, const char *errors)
|
_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_imports, const char *encoding, const char *errors)
|
||||||
/*[clinic end generated code: checksum=26c1d4a06841a8e51d29a0c244ba7f4607ff358a]*/
|
/*[clinic end generated code: checksum=6936e9188104e45b1b15e1c11fe77b3965409471]*/
|
||||||
{
|
{
|
||||||
_Py_IDENTIFIER(persistent_load);
|
_Py_IDENTIFIER(persistent_load);
|
||||||
|
|
||||||
@ -6648,20 +6637,20 @@ _pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_i
|
|||||||
(void)Unpickler_clear(self);
|
(void)Unpickler_clear(self);
|
||||||
|
|
||||||
if (_Unpickler_SetInputStream(self, file) < 0)
|
if (_Unpickler_SetInputStream(self, file) < 0)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
if (_Unpickler_SetInputEncoding(self, encoding, errors) < 0)
|
if (_Unpickler_SetInputEncoding(self, encoding, errors) < 0)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
self->fix_imports = fix_imports;
|
self->fix_imports = fix_imports;
|
||||||
if (self->fix_imports == -1)
|
if (self->fix_imports == -1)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
if (_PyObject_HasAttrId((PyObject *)self, &PyId_persistent_load)) {
|
if (_PyObject_HasAttrId((PyObject *)self, &PyId_persistent_load)) {
|
||||||
self->pers_func = _PyObject_GetAttrId((PyObject *)self,
|
self->pers_func = _PyObject_GetAttrId((PyObject *)self,
|
||||||
&PyId_persistent_load);
|
&PyId_persistent_load);
|
||||||
if (self->pers_func == NULL)
|
if (self->pers_func == NULL)
|
||||||
return NULL;
|
return 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self->pers_func = NULL;
|
self->pers_func = NULL;
|
||||||
@ -6669,30 +6658,19 @@ _pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_i
|
|||||||
|
|
||||||
self->stack = (Pdata *)Pdata_New();
|
self->stack = (Pdata *)Pdata_New();
|
||||||
if (self->stack == NULL)
|
if (self->stack == NULL)
|
||||||
return NULL;
|
return 1;
|
||||||
|
|
||||||
self->memo_size = 32;
|
self->memo_size = 32;
|
||||||
self->memo = _Unpickler_NewMemo(self->memo_size);
|
self->memo = _Unpickler_NewMemo(self->memo_size);
|
||||||
if (self->memo == NULL)
|
if (self->memo == NULL)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
self->proto = 0;
|
self->proto = 0;
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wrap the Clinic generated signature to slot it in tp_init. */
|
|
||||||
static int
|
|
||||||
Unpickler_init(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
||||||
{
|
|
||||||
PyObject *result = _pickle_Unpickler___init__(self, args, kwargs);
|
|
||||||
if (result == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Py_DECREF(result);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Define a proxy object for the Unpickler's internal memo object. This is to
|
/* Define a proxy object for the Unpickler's internal memo object. This is to
|
||||||
* avoid breaking code like:
|
* avoid breaking code like:
|
||||||
* unpickler.memo.clear()
|
* unpickler.memo.clear()
|
||||||
@ -7096,7 +7074,7 @@ static PyTypeObject Unpickler_Type = {
|
|||||||
0, /*tp_descr_get*/
|
0, /*tp_descr_get*/
|
||||||
0, /*tp_descr_set*/
|
0, /*tp_descr_set*/
|
||||||
0, /*tp_dictoffset*/
|
0, /*tp_dictoffset*/
|
||||||
Unpickler_init, /*tp_init*/
|
_pickle_Unpickler___init__, /*tp_init*/
|
||||||
PyType_GenericAlloc, /*tp_alloc*/
|
PyType_GenericAlloc, /*tp_alloc*/
|
||||||
PyType_GenericNew, /*tp_new*/
|
PyType_GenericNew, /*tp_new*/
|
||||||
PyObject_GC_Del, /*tp_free*/
|
PyObject_GC_Del, /*tp_free*/
|
||||||
|
@ -1805,7 +1805,7 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m
|
|||||||
|
|
||||||
/* For type constructors that don't take keyword args
|
/* For type constructors that don't take keyword args
|
||||||
*
|
*
|
||||||
* Sets a TypeError and returns 0 if the kwds dict is
|
* Sets a TypeError and returns 0 if the args/kwargs is
|
||||||
* not empty, returns 1 otherwise
|
* not empty, returns 1 otherwise
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -1824,6 +1824,25 @@ _PyArg_NoKeywords(const char *funcname, PyObject *kw)
|
|||||||
funcname);
|
funcname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyArg_NoPositional(const char *funcname, PyObject *args)
|
||||||
|
{
|
||||||
|
if (args == NULL)
|
||||||
|
return 1;
|
||||||
|
if (!PyTuple_CheckExact(args)) {
|
||||||
|
PyErr_BadInternalCall();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (PyTuple_GET_SIZE(args) == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
PyErr_Format(PyExc_TypeError, "%s does not take positional arguments",
|
||||||
|
funcname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -169,6 +169,8 @@ def linear_format(s, **kwargs):
|
|||||||
themselves. (This line is the "source line".)
|
themselves. (This line is the "source line".)
|
||||||
* If the substitution text is empty, the source line
|
* If the substitution text is empty, the source line
|
||||||
is removed in the output.
|
is removed in the output.
|
||||||
|
* If the field is not recognized, the original line
|
||||||
|
is passed unmodified through to the output.
|
||||||
* If the substitution text is not empty:
|
* If the substitution text is not empty:
|
||||||
* Each line of the substituted text is indented
|
* Each line of the substituted text is indented
|
||||||
by the indent of the source line.
|
by the indent of the source line.
|
||||||
@ -454,6 +456,182 @@ class CLanguage(Language):
|
|||||||
add('"')
|
add('"')
|
||||||
return ''.join(text)
|
return ''.join(text)
|
||||||
|
|
||||||
|
_templates = {}
|
||||||
|
# the templates will be run through str.format(),
|
||||||
|
# so actual curly-braces need to be doubled up.
|
||||||
|
templates_source = """
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
docstring_prototype
|
||||||
|
|
||||||
|
PyDoc_VAR({c_basename}__doc__);
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
docstring_definition
|
||||||
|
|
||||||
|
PyDoc_STRVAR({c_basename}__doc__,
|
||||||
|
{docstring});
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
impl_definition
|
||||||
|
|
||||||
|
static {impl_return_type}
|
||||||
|
{c_basename}_impl({impl_parameters})
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_prototype_noargs
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_prototype_meth_o
|
||||||
|
|
||||||
|
# SLIGHT HACK
|
||||||
|
# METH_O uses {impl_parameters} for the parser!
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
{c_basename}({impl_parameters})
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_prototype_varargs
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
{c_basename}({self_type}{self_name}, PyObject *args)
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_prototype_keyword
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_prototype_init
|
||||||
|
|
||||||
|
static int
|
||||||
|
{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_definition_simple_no_parsing
|
||||||
|
|
||||||
|
{{
|
||||||
|
return {c_basename}_impl({impl_arguments});
|
||||||
|
}}
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_definition_start
|
||||||
|
|
||||||
|
{{
|
||||||
|
{return_value_declaration}
|
||||||
|
{declarations}
|
||||||
|
{initializers}
|
||||||
|
{empty line}
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_definition_end
|
||||||
|
|
||||||
|
{return_conversion}
|
||||||
|
|
||||||
|
{exit_label}
|
||||||
|
{cleanup}
|
||||||
|
return return_value;
|
||||||
|
}}
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_definition_impl_call
|
||||||
|
|
||||||
|
{return_value} = {c_basename}_impl({impl_arguments});
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_definition_unpack_tuple
|
||||||
|
|
||||||
|
if (!PyArg_UnpackTuple(args, "{name}",
|
||||||
|
{unpack_min}, {unpack_max},
|
||||||
|
{parse_arguments}))
|
||||||
|
goto exit;
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_definition_parse_tuple
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args,
|
||||||
|
"{format_units}:{name}",
|
||||||
|
{parse_arguments}))
|
||||||
|
goto exit;
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_definition_option_groups
|
||||||
|
{option_group_parsing}
|
||||||
|
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_definition_parse_tuple_and_keywords
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
||||||
|
"{format_units}:{name}", _keywords,
|
||||||
|
{parse_arguments}))
|
||||||
|
goto exit;
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_definition_no_positional
|
||||||
|
|
||||||
|
if (!_PyArg_NoPositional("{name}", args))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
parser_definition_no_keywords
|
||||||
|
|
||||||
|
if (!_PyArg_NoKeywords("{name}", kwargs))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
__________________________________________________
|
||||||
|
|
||||||
|
methoddef_define
|
||||||
|
|
||||||
|
#define {methoddef_name} \\
|
||||||
|
{{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
|
||||||
|
__________________________________________________
|
||||||
|
""".rstrip()
|
||||||
|
|
||||||
|
title = ''
|
||||||
|
buffer = []
|
||||||
|
line = None
|
||||||
|
for line in templates_source.split('\n'):
|
||||||
|
line = line.rstrip()
|
||||||
|
if line.startswith('# '):
|
||||||
|
# comment
|
||||||
|
continue
|
||||||
|
if line.startswith("_____"):
|
||||||
|
if not buffer:
|
||||||
|
continue
|
||||||
|
assert title not in _templates, "defined template twice: " + repr(title)
|
||||||
|
buffer = '\n'.join(buffer).rstrip()
|
||||||
|
buffer = buffer.replace('{empty line}', '')
|
||||||
|
_templates[title] = buffer
|
||||||
|
buffer = []
|
||||||
|
title = ''
|
||||||
|
continue
|
||||||
|
if not title:
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
title = line
|
||||||
|
continue
|
||||||
|
if not (line or buffer):
|
||||||
|
# throw away leading blank lines
|
||||||
|
continue
|
||||||
|
buffer.append(line)
|
||||||
|
|
||||||
|
assert not title, 'ensure templates_source ends with ______ (still adding to ' + repr(title) + ")"
|
||||||
|
|
||||||
|
del templates_source
|
||||||
|
del title
|
||||||
|
del buffer
|
||||||
|
del line
|
||||||
|
|
||||||
|
# for name, value in _templates.items():
|
||||||
|
# print(name + ":")
|
||||||
|
# pprint.pprint(value)
|
||||||
|
# print()
|
||||||
|
|
||||||
def output_templates(self, f):
|
def output_templates(self, f):
|
||||||
parameters = list(f.parameters.values())
|
parameters = list(f.parameters.values())
|
||||||
@ -477,12 +655,14 @@ class CLanguage(Language):
|
|||||||
else:
|
else:
|
||||||
all_boring_objects = True
|
all_boring_objects = True
|
||||||
|
|
||||||
|
new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
|
||||||
|
|
||||||
meth_o = (len(parameters) == 1 and
|
meth_o = (len(parameters) == 1 and
|
||||||
parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
|
parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
|
||||||
not converters[0].is_optional() and
|
not converters[0].is_optional() and
|
||||||
isinstance(converters[0], object_converter) and
|
isinstance(converters[0], object_converter) and
|
||||||
converters[0].format_unit == 'O')
|
converters[0].format_unit == 'O' and
|
||||||
|
not new_or_init)
|
||||||
|
|
||||||
# we have to set seven things before we're done:
|
# we have to set seven things before we're done:
|
||||||
#
|
#
|
||||||
@ -493,246 +673,144 @@ class CLanguage(Language):
|
|||||||
# parser_prototype
|
# parser_prototype
|
||||||
# parser_definition
|
# parser_definition
|
||||||
# impl_definition
|
# impl_definition
|
||||||
#
|
|
||||||
# since impl_prototype is always just impl_definition + ';'
|
|
||||||
# we just define impl_definition at the top
|
|
||||||
|
|
||||||
docstring_prototype = "PyDoc_VAR({c_basename}__doc__);"
|
templates = self._templates
|
||||||
|
|
||||||
docstring_definition = """
|
return_value_declaration = "PyObject *return_value = NULL;"
|
||||||
PyDoc_STRVAR({c_basename}__doc__,
|
|
||||||
{docstring});
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
impl_definition = """
|
|
||||||
static {impl_return_type}
|
|
||||||
{c_basename}_impl({impl_parameters})""".strip()
|
|
||||||
|
|
||||||
|
methoddef_define = templates['methoddef_define']
|
||||||
|
docstring_prototype = templates['docstring_prototype']
|
||||||
|
docstring_definition = templates['docstring_definition']
|
||||||
|
impl_definition = templates['impl_definition']
|
||||||
impl_prototype = parser_prototype = parser_definition = None
|
impl_prototype = parser_prototype = parser_definition = None
|
||||||
|
|
||||||
def meth_varargs():
|
parser_body_fields = None
|
||||||
nonlocal flags
|
def parser_body(prototype, *fields):
|
||||||
nonlocal parser_prototype
|
nonlocal parser_body_fields
|
||||||
|
add, output = text_accumulator()
|
||||||
|
add(prototype)
|
||||||
|
parser_body_fields = fields
|
||||||
|
fields = list(fields)
|
||||||
|
fields.insert(0, 'parser_definition_start')
|
||||||
|
fields.append('parser_definition_impl_call')
|
||||||
|
fields.append('parser_definition_end')
|
||||||
|
for field in fields:
|
||||||
|
add('\n')
|
||||||
|
add(templates[field])
|
||||||
|
return output()
|
||||||
|
|
||||||
flags = "METH_VARARGS"
|
def insert_keywords(s):
|
||||||
|
return linear_format(s, declarations="static char *_keywords[] = {{{keywords}, NULL}};\n{declarations}")
|
||||||
parser_prototype = """
|
|
||||||
static PyObject *
|
|
||||||
{c_basename}({self_type}{self_name}, PyObject *args)
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
if not parameters:
|
if not parameters:
|
||||||
# no parameters, METH_NOARGS
|
# no parameters, METH_NOARGS
|
||||||
|
|
||||||
flags = "METH_NOARGS"
|
flags = "METH_NOARGS"
|
||||||
|
|
||||||
parser_prototype = """
|
parser_prototype = templates['parser_prototype_noargs']
|
||||||
static PyObject *
|
parser_definition = parser_prototype
|
||||||
{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
if default_return_converter:
|
if default_return_converter:
|
||||||
parser_definition = parser_prototype + """
|
parser_definition = parser_prototype + '\n' + templates['parser_definition_simple_no_parsing']
|
||||||
{{
|
|
||||||
return {c_basename}_impl({impl_arguments});
|
|
||||||
}}
|
|
||||||
""".rstrip()
|
|
||||||
else:
|
else:
|
||||||
parser_definition = parser_prototype + """
|
parser_definition = parser_body(parser_prototype)
|
||||||
{{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
{declarations}
|
|
||||||
{initializers}
|
|
||||||
|
|
||||||
{return_value} = {c_basename}_impl({impl_arguments});
|
|
||||||
{return_conversion}
|
|
||||||
|
|
||||||
{exit_label}
|
|
||||||
{cleanup}
|
|
||||||
return return_value;
|
|
||||||
}}
|
|
||||||
""".rstrip()
|
|
||||||
|
|
||||||
elif meth_o:
|
elif meth_o:
|
||||||
|
flags = "METH_O"
|
||||||
|
# impl_definition = templates['parser_prototype_meth_o']
|
||||||
|
|
||||||
if default_return_converter:
|
if default_return_converter:
|
||||||
# maps perfectly to METH_O, doesn't need a return converter,
|
# maps perfectly to METH_O, doesn't need a return converter.
|
||||||
# so we skip the parse function and call
|
# so we skip making a parse function
|
||||||
# directly into the impl function
|
# and call directly into the impl function.
|
||||||
|
|
||||||
# SLIGHT HACK
|
|
||||||
# METH_O uses {impl_parameters} for the parser.
|
|
||||||
|
|
||||||
flags = "METH_O"
|
|
||||||
|
|
||||||
impl_definition = """
|
|
||||||
static PyObject *
|
|
||||||
{c_basename}({impl_parameters})
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
impl_prototype = parser_prototype = parser_definition = ''
|
impl_prototype = parser_prototype = parser_definition = ''
|
||||||
|
impl_definition = templates['parser_prototype_meth_o']
|
||||||
else:
|
else:
|
||||||
# SLIGHT HACK
|
parser_prototype = templates['parser_prototype_meth_o']
|
||||||
# METH_O uses {impl_parameters} for the parser.
|
parser_definition = parser_body(parser_prototype)
|
||||||
|
|
||||||
flags = "METH_O"
|
|
||||||
|
|
||||||
parser_prototype = """
|
|
||||||
static PyObject *
|
|
||||||
{c_basename}({impl_parameters})
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
parser_definition = parser_prototype + """
|
|
||||||
{{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
{declarations}
|
|
||||||
{initializers}
|
|
||||||
|
|
||||||
_return_value = {c_basename}_impl({impl_arguments});
|
|
||||||
{return_conversion}
|
|
||||||
|
|
||||||
{exit_label}
|
|
||||||
{cleanup}
|
|
||||||
return return_value;
|
|
||||||
}}
|
|
||||||
""".rstrip()
|
|
||||||
|
|
||||||
elif has_option_groups:
|
elif has_option_groups:
|
||||||
# positional parameters with option groups
|
# positional parameters with option groups
|
||||||
# (we have to generate lots of PyArg_ParseTuple calls
|
# (we have to generate lots of PyArg_ParseTuple calls
|
||||||
# in a big switch statement)
|
# in a big switch statement)
|
||||||
|
|
||||||
meth_varargs()
|
flags = "METH_VARARGS"
|
||||||
|
parser_prototype = templates['parser_prototype_varargs']
|
||||||
|
|
||||||
parser_definition = parser_prototype + """
|
parser_definition = parser_body(parser_prototype, 'parser_definition_option_groups')
|
||||||
{{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
{declarations}
|
|
||||||
{initializers}
|
|
||||||
|
|
||||||
{option_group_parsing}
|
|
||||||
{return_value} = {c_basename}_impl({impl_arguments});
|
|
||||||
{return_conversion}
|
|
||||||
|
|
||||||
{exit_label}
|
|
||||||
{cleanup}
|
|
||||||
return return_value;
|
|
||||||
}}
|
|
||||||
""".rstrip()
|
|
||||||
|
|
||||||
elif positional and all_boring_objects:
|
elif positional and all_boring_objects:
|
||||||
# positional-only, but no option groups,
|
# positional-only, but no option groups,
|
||||||
# and nothing but normal objects:
|
# and nothing but normal objects:
|
||||||
# PyArg_UnpackTuple!
|
# PyArg_UnpackTuple!
|
||||||
|
|
||||||
meth_varargs()
|
flags = "METH_VARARGS"
|
||||||
|
parser_prototype = templates['parser_prototype_varargs']
|
||||||
|
|
||||||
# substitute in the min and max by hand right here
|
parser_definition = parser_body(parser_prototype, 'parser_definition_unpack_tuple')
|
||||||
assert parameters
|
|
||||||
min_o = first_optional
|
|
||||||
max_o = len(parameters)
|
|
||||||
if isinstance(parameters[0].converter, self_converter):
|
|
||||||
min_o -= 1
|
|
||||||
max_o -= 1
|
|
||||||
min_o = str(min_o)
|
|
||||||
max_o = str(max_o)
|
|
||||||
|
|
||||||
parser_definition = parser_prototype + """
|
|
||||||
{{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
{declarations}
|
|
||||||
{initializers}
|
|
||||||
|
|
||||||
if (!PyArg_UnpackTuple(args, "{name}",
|
|
||||||
{min}, {max},
|
|
||||||
{parse_arguments}))
|
|
||||||
goto exit;
|
|
||||||
{return_value} = {c_basename}_impl({impl_arguments});
|
|
||||||
{return_conversion}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
{cleanup}
|
|
||||||
return return_value;
|
|
||||||
}}
|
|
||||||
""".rstrip().replace('{min}', min_o).replace('{max}', max_o)
|
|
||||||
|
|
||||||
elif positional:
|
elif positional:
|
||||||
# positional-only, but no option groups
|
# positional-only, but no option groups
|
||||||
# we only need one call to PyArg_ParseTuple
|
# we only need one call to PyArg_ParseTuple
|
||||||
|
|
||||||
meth_varargs()
|
flags = "METH_VARARGS"
|
||||||
|
parser_prototype = templates['parser_prototype_varargs']
|
||||||
|
|
||||||
parser_definition = parser_prototype + """
|
parser_definition = parser_body(parser_prototype, 'parser_definition_parse_tuple')
|
||||||
{{
|
|
||||||
PyObject *return_value = NULL;
|
|
||||||
{declarations}
|
|
||||||
{initializers}
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args,
|
|
||||||
"{format_units}:{name}",
|
|
||||||
{parse_arguments}))
|
|
||||||
goto exit;
|
|
||||||
{return_value} = {c_basename}_impl({impl_arguments});
|
|
||||||
{return_conversion}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
{cleanup}
|
|
||||||
return return_value;
|
|
||||||
}}
|
|
||||||
""".rstrip()
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# positional-or-keyword arguments
|
# positional-or-keyword arguments
|
||||||
flags = "METH_VARARGS|METH_KEYWORDS"
|
flags = "METH_VARARGS|METH_KEYWORDS"
|
||||||
|
|
||||||
parser_prototype = """
|
parser_prototype = templates['parser_prototype_keyword']
|
||||||
static PyObject *
|
|
||||||
{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
parser_definition = parser_prototype + """
|
parser_definition = parser_body(parser_prototype, 'parser_definition_parse_tuple_and_keywords')
|
||||||
{{
|
parser_definition = insert_keywords(parser_definition)
|
||||||
PyObject *return_value = NULL;
|
|
||||||
static char *_keywords[] = {{{keywords}, NULL}};
|
|
||||||
{declarations}
|
|
||||||
{initializers}
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
||||||
"{format_units}:{name}", _keywords,
|
|
||||||
{parse_arguments}))
|
|
||||||
goto exit;
|
|
||||||
{return_value} = {c_basename}_impl({impl_arguments});
|
|
||||||
{return_conversion}
|
|
||||||
|
|
||||||
exit:
|
if new_or_init:
|
||||||
{cleanup}
|
methoddef_define = ''
|
||||||
return return_value;
|
|
||||||
}}
|
if f.kind == METHOD_NEW:
|
||||||
""".rstrip()
|
parser_prototype = templates['parser_prototype_keyword']
|
||||||
|
else:
|
||||||
|
return_value_declaration = "int return_value = -1;"
|
||||||
|
parser_prototype = templates['parser_prototype_init']
|
||||||
|
|
||||||
|
fields = list(parser_body_fields)
|
||||||
|
parses_positional = 'METH_NOARGS' not in flags
|
||||||
|
parses_keywords = 'METH_KEYWORDS' in flags
|
||||||
|
if parses_keywords:
|
||||||
|
assert parses_positional
|
||||||
|
|
||||||
|
if not parses_keywords:
|
||||||
|
fields.insert(0, 'parser_definition_no_keywords')
|
||||||
|
if not parses_positional:
|
||||||
|
fields.insert(0, 'parser_definition_no_positional')
|
||||||
|
|
||||||
|
parser_definition = parser_body(parser_prototype, *fields)
|
||||||
|
if parses_keywords:
|
||||||
|
parser_definition = insert_keywords(parser_definition)
|
||||||
|
|
||||||
|
|
||||||
if f.methoddef_flags:
|
if f.methoddef_flags:
|
||||||
assert flags
|
|
||||||
flags += '|' + f.methoddef_flags
|
flags += '|' + f.methoddef_flags
|
||||||
|
|
||||||
methoddef_define = """
|
methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
|
||||||
#define {methoddef_name} \\
|
|
||||||
{{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
|
|
||||||
""".strip().replace('{methoddef_flags}', flags)
|
|
||||||
|
|
||||||
# parser_prototype mustn't be None, but it could be an empty string.
|
# add ';' to the end of parser_prototype and impl_prototype
|
||||||
|
# (they mustn't be None, but they could be an empty string.)
|
||||||
assert parser_prototype is not None
|
assert parser_prototype is not None
|
||||||
assert not parser_prototype.endswith(';')
|
|
||||||
|
|
||||||
if parser_prototype:
|
if parser_prototype:
|
||||||
|
assert not parser_prototype.endswith(';')
|
||||||
parser_prototype += ';'
|
parser_prototype += ';'
|
||||||
|
|
||||||
assert impl_definition
|
|
||||||
if impl_prototype is None:
|
if impl_prototype is None:
|
||||||
impl_prototype = impl_definition + ";"
|
impl_prototype = impl_definition
|
||||||
|
if impl_prototype:
|
||||||
|
impl_prototype += ";"
|
||||||
|
|
||||||
# __new__ and __init__ don't need methoddefs
|
parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
|
||||||
if f.kind in (METHOD_NEW, METHOD_INIT):
|
|
||||||
methoddef_define = ''
|
|
||||||
|
|
||||||
d = {
|
d = {
|
||||||
"docstring_prototype" : docstring_prototype,
|
"docstring_prototype" : docstring_prototype,
|
||||||
@ -744,8 +822,11 @@ exit:
|
|||||||
"impl_definition" : impl_definition,
|
"impl_definition" : impl_definition,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# make sure we didn't forget to assign something,
|
||||||
|
# and wrap each non-empty value in \n's
|
||||||
d2 = {}
|
d2 = {}
|
||||||
for name, value in d.items():
|
for name, value in d.items():
|
||||||
|
assert value is not None, "got a None value for template " + repr(name)
|
||||||
if value:
|
if value:
|
||||||
value = '\n' + value + '\n'
|
value = '\n' + value + '\n'
|
||||||
d2[name] = value
|
d2[name] = value
|
||||||
@ -881,12 +962,17 @@ exit:
|
|||||||
|
|
||||||
positional = has_option_groups = False
|
positional = has_option_groups = False
|
||||||
|
|
||||||
|
first_optional = len(parameters)
|
||||||
|
|
||||||
if parameters:
|
if parameters:
|
||||||
last_group = 0
|
last_group = 0
|
||||||
|
|
||||||
for p in parameters:
|
for i, p in enumerate(parameters):
|
||||||
c = p.converter
|
c = p.converter
|
||||||
|
|
||||||
|
if p.default is not unspecified:
|
||||||
|
first_optional = min(first_optional, i)
|
||||||
|
|
||||||
# insert group variable
|
# insert group variable
|
||||||
group = p.group
|
group = p.group
|
||||||
if last_group != group:
|
if last_group != group:
|
||||||
@ -950,6 +1036,10 @@ exit:
|
|||||||
template_dict['cleanup'] = "".join(data.cleanup)
|
template_dict['cleanup'] = "".join(data.cleanup)
|
||||||
template_dict['return_value'] = data.return_value
|
template_dict['return_value'] = data.return_value
|
||||||
|
|
||||||
|
# used by unpack tuple
|
||||||
|
template_dict['unpack_min'] = str(first_optional)
|
||||||
|
template_dict['unpack_max'] = str(len(parameters))
|
||||||
|
|
||||||
if has_option_groups:
|
if has_option_groups:
|
||||||
self.render_option_group_parsing(f, template_dict)
|
self.render_option_group_parsing(f, template_dict)
|
||||||
|
|
||||||
@ -2063,7 +2153,7 @@ class char_converter(CConverter):
|
|||||||
|
|
||||||
|
|
||||||
@add_legacy_c_converter('B', bitwise=True)
|
@add_legacy_c_converter('B', bitwise=True)
|
||||||
class byte_converter(CConverter):
|
class unsigned_char_converter(CConverter):
|
||||||
type = 'unsigned char'
|
type = 'unsigned char'
|
||||||
default_type = int
|
default_type = int
|
||||||
format_unit = 'b'
|
format_unit = 'b'
|
||||||
@ -2073,6 +2163,8 @@ class byte_converter(CConverter):
|
|||||||
if bitwise:
|
if bitwise:
|
||||||
self.format_unit = 'B'
|
self.format_unit = 'B'
|
||||||
|
|
||||||
|
class byte_converter(unsigned_char_converter): pass
|
||||||
|
|
||||||
class short_converter(CConverter):
|
class short_converter(CConverter):
|
||||||
type = 'short'
|
type = 'short'
|
||||||
default_type = int
|
default_type = int
|
||||||
@ -2455,6 +2547,16 @@ class int_return_converter(long_return_converter):
|
|||||||
type = 'int'
|
type = 'int'
|
||||||
cast = '(long)'
|
cast = '(long)'
|
||||||
|
|
||||||
|
class init_return_converter(long_return_converter):
|
||||||
|
"""
|
||||||
|
Special return converter for __init__ functions.
|
||||||
|
"""
|
||||||
|
type = 'int'
|
||||||
|
cast = '(long)'
|
||||||
|
|
||||||
|
def render(self, function, data):
|
||||||
|
pass
|
||||||
|
|
||||||
class unsigned_long_return_converter(long_return_converter):
|
class unsigned_long_return_converter(long_return_converter):
|
||||||
type = 'unsigned long'
|
type = 'unsigned long'
|
||||||
conversion_fn = 'PyLong_FromUnsignedLong'
|
conversion_fn = 'PyLong_FromUnsignedLong'
|
||||||
@ -2858,9 +2960,8 @@ class DSLParser:
|
|||||||
if c_basename and not is_legal_c_identifier(c_basename):
|
if c_basename and not is_legal_c_identifier(c_basename):
|
||||||
fail("Illegal C basename: {}".format(c_basename))
|
fail("Illegal C basename: {}".format(c_basename))
|
||||||
|
|
||||||
if not returns:
|
return_converter = None
|
||||||
return_converter = CReturnConverter()
|
if returns:
|
||||||
else:
|
|
||||||
ast_input = "def x() -> {}: pass".format(returns)
|
ast_input = "def x() -> {}: pass".format(returns)
|
||||||
module = None
|
module = None
|
||||||
try:
|
try:
|
||||||
@ -2893,9 +2994,14 @@ class DSLParser:
|
|||||||
if (self.kind != CALLABLE) or (not cls):
|
if (self.kind != CALLABLE) or (not cls):
|
||||||
fail("__init__ must be a normal method, not a class or static method!")
|
fail("__init__ must be a normal method, not a class or static method!")
|
||||||
self.kind = METHOD_INIT
|
self.kind = METHOD_INIT
|
||||||
|
if not return_converter:
|
||||||
|
return_converter = init_return_converter()
|
||||||
elif fields[-1] in unsupported_special_methods:
|
elif fields[-1] in unsupported_special_methods:
|
||||||
fail(fields[-1] + " should not be converted to Argument Clinic! (Yet.)")
|
fail(fields[-1] + " should not be converted to Argument Clinic! (Yet.)")
|
||||||
|
|
||||||
|
if not return_converter:
|
||||||
|
return_converter = CReturnConverter()
|
||||||
|
|
||||||
if not module:
|
if not module:
|
||||||
fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
|
fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
|
||||||
self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
|
self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user