Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
b86caf18
Commit
b86caf18
authored
Jan 18, 2014
by
Larry Hastings
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #20294: Argument Clinic now supports argument parsing for __new__ and
__init__ functions.
parent
93f0c8dd
Changes
6
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
365 additions
and
239 deletions
+365
-239
Doc/howto/clinic.rst
Doc/howto/clinic.rst
+21
-2
Include/modsupport.h
Include/modsupport.h
+1
-0
Misc/NEWS
Misc/NEWS
+3
-0
Modules/_pickle.c
Modules/_pickle.c
+26
-48
Python/getargs.c
Python/getargs.c
+20
-1
Tools/clinic/clinic.py
Tools/clinic/clinic.py
+294
-188
No files found.
Doc/howto/clinic.rst
View file @
b86caf18
...
...
@@ -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.
========= =================================================================================
``'B'`` ``
byte
(bitwise=True)``
``'b'`` ``
byte
``
``'B'`` ``
unsigned_char
(bitwise=True)``
``'b'`` ``
unsigned_char
``
``'c'`` ``char``
``'C'`` ``int(types='str')``
``'d'`` ``double``
...
...
@@ -1275,6 +1275,25 @@ any arguments.
You can still use a self converter, a return converter, and specify
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
----------------------------------------------
...
...
Include/modsupport.h
View file @
b86caf18
...
...
@@ -36,6 +36,7 @@ PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...);
#endif
#ifndef Py_LIMITED_API
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_VaParseTupleAndKeywords
(
PyObject
*
,
PyObject
*
,
...
...
Misc/NEWS
View file @
b86caf18
...
...
@@ -101,6 +101,9 @@ Tests
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
value of c_default and py_default with a class member.
...
...
Modules/_pickle.c
View file @
b86caf18
...
...
@@ -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
"
"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
);
static
PyObject
*
static
int
_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
};
PyObject
*
file
;
PyObject
*
protocol
=
NULL
;
...
...
@@ -4086,9 +4086,9 @@ exit:
return
return_value
;
}
static
PyObject
*
static
int
_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
(
dispatch_table
);
...
...
@@ -4098,16 +4098,16 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *pro
(
void
)
Pickler_clear
(
self
);
if
(
_Pickler_SetProtocol
(
self
,
protocol
,
fix_imports
)
<
0
)
return
NULL
;
return
-
1
;
if
(
_Pickler_SetOutputStream
(
self
,
file
)
<
0
)
return
NULL
;
return
-
1
;
/* memo and output_buffer may have already been created in _Pickler_New */
if
(
self
->
memo
==
NULL
)
{
self
->
memo
=
PyMemoTable_New
();
if
(
self
->
memo
==
NULL
)
return
NULL
;
return
-
1
;
}
self
->
output_len
=
0
;
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
->
max_output_len
);
if
(
self
->
output_buffer
==
NULL
)
return
NULL
;
return
-
1
;
}
self
->
fast
=
0
;
...
...
@@ -4126,31 +4126,20 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *pro
self
->
pers_func
=
_PyObject_GetAttrId
((
PyObject
*
)
self
,
&
PyId_persistent_id
);
if
(
self
->
pers_func
==
NULL
)
return
NULL
;
return
-
1
;
}
self
->
dispatch_table
=
NULL
;
if
(
_PyObject_HasAttrId
((
PyObject
*
)
self
,
&
PyId_dispatch_table
))
{
self
->
dispatch_table
=
_PyObject_GetAttrId
((
PyObject
*
)
self
,
&
PyId_dispatch_table
);
if
(
self
->
dispatch_table
==
NULL
)
return
NULL
;
}
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
;
}
/* Define a proxy object for the Pickler's internal memo object. This is to
* avoid breaking code like:
* pickler.memo.clear()
...
...
@@ -4543,7 +4532,7 @@ static PyTypeObject Pickler_Type = {
0
,
/*tp_descr_get*/
0
,
/*tp_descr_set*/
0
,
/*tp_dictoffset*/
Pickler_init
,
/*tp_init*/
_pickle_Pickler___init__
,
/*tp_init*/
PyType_GenericAlloc
,
/*tp_alloc*/
PyType_GenericNew
,
/*tp_new*/
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
"
"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
);
static
PyObject
*
static
int
_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
};
PyObject
*
file
;
int
fix_imports
=
1
;
...
...
@@ -6637,9 +6626,9 @@ exit:
return
return_value
;
}
static
PyObject
*
static
int
_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
);
...
...
@@ -6648,20 +6637,20 @@ _pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_i
(
void
)
Unpickler_clear
(
self
);
if
(
_Unpickler_SetInputStream
(
self
,
file
)
<
0
)
return
NULL
;
return
-
1
;
if
(
_Unpickler_SetInputEncoding
(
self
,
encoding
,
errors
)
<
0
)
return
NULL
;
return
-
1
;
self
->
fix_imports
=
fix_imports
;
if
(
self
->
fix_imports
==
-
1
)
return
NULL
;
return
-
1
;
if
(
_PyObject_HasAttrId
((
PyObject
*
)
self
,
&
PyId_persistent_load
))
{
self
->
pers_func
=
_PyObject_GetAttrId
((
PyObject
*
)
self
,
&
PyId_persistent_load
);
if
(
self
->
pers_func
==
NULL
)
return
NULL
;
return
1
;
}
else
{
self
->
pers_func
=
NULL
;
...
...
@@ -6669,30 +6658,19 @@ _pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_i
self
->
stack
=
(
Pdata
*
)
Pdata_New
();
if
(
self
->
stack
==
NULL
)
return
NULL
;
return
1
;
self
->
memo_size
=
32
;
self
->
memo
=
_Unpickler_NewMemo
(
self
->
memo_size
);
if
(
self
->
memo
==
NULL
)
return
NULL
;
return
-
1
;
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
;
}
/* Define a proxy object for the Unpickler's internal memo object. This is to
* avoid breaking code like:
* unpickler.memo.clear()
...
...
@@ -7096,7 +7074,7 @@ static PyTypeObject Unpickler_Type = {
0
,
/*tp_descr_get*/
0
,
/*tp_descr_set*/
0
,
/*tp_dictoffset*/
Unpickler_init
,
/*tp_init*/
_pickle_Unpickler___init__
,
/*tp_init*/
PyType_GenericAlloc
,
/*tp_alloc*/
PyType_GenericNew
,
/*tp_new*/
PyObject_GC_Del
,
/*tp_free*/
...
...
Python/getargs.c
View file @
b86caf18
...
...
@@ -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
*
* 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
*/
int
...
...
@@ -1824,6 +1824,25 @@ _PyArg_NoKeywords(const char *funcname, PyObject *kw)
funcname
);
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
};
#endif
Tools/clinic/clinic.py
View file @
b86caf18
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment