Issue #20287: Argument Clinic's output is now configurable, allowing
delaying its output or even redirecting it to a separate file.
This commit is contained in:
parent
601d366844
commit
bebf73511a
|
@ -23,6 +23,58 @@ Argument Clinic How-To
|
||||||
version of Argument Clinic that ships with CPython 3.5 *could*
|
version of Argument Clinic that ships with CPython 3.5 *could*
|
||||||
be totally incompatible and break all your code.
|
be totally incompatible and break all your code.
|
||||||
|
|
||||||
|
============================
|
||||||
|
The Goals Of Argument Clinic
|
||||||
|
============================
|
||||||
|
|
||||||
|
Argument Clinic's primary goal
|
||||||
|
is to take over responsibility for all argument parsing code
|
||||||
|
inside CPython. This means that, when you convert a function
|
||||||
|
to work with Argument Clinic, that function should no longer
|
||||||
|
do any of its own argument parsing--the code generated by
|
||||||
|
Argument Clinic should be a "black box" to you, where CPython
|
||||||
|
calls in at the top, and your code gets called at the bottom,
|
||||||
|
with ``PyObject *args`` (and maybe ``PyObject *kwargs``)
|
||||||
|
magically converted into the C variables and types you need.
|
||||||
|
|
||||||
|
In order for Argument Clinic to accomplish its primary goal,
|
||||||
|
it must be easy to use. Currently, working with CPython's
|
||||||
|
argument parsing library is a chore, requiring maintaining
|
||||||
|
redundant information in a surprising number of places.
|
||||||
|
When you use Argument Clinic, you don't have to repeat yourself.
|
||||||
|
|
||||||
|
Obviously, no one would want to use Argument Clinic unless
|
||||||
|
it's solving a their problem without creating problems of
|
||||||
|
its own.
|
||||||
|
So Argument Clinic should generate correct code, and its
|
||||||
|
code should preferably be slower, and definitely should
|
||||||
|
not introduce a major speed regression. (Eventually Argument
|
||||||
|
Clinic should enable a major speedup--we should be able
|
||||||
|
to rewrite its code generator so it produces tailor-made
|
||||||
|
parsing code, rather than using the general-purpose functions
|
||||||
|
from the CPython code base, which would make for the fastest
|
||||||
|
argument parsing possible.)
|
||||||
|
|
||||||
|
Additionally, Argument Clinic must be flexible enough to
|
||||||
|
work with any approach to argument parsing. Python has
|
||||||
|
some functions with some very strange parsing behaviors;
|
||||||
|
Argument Clinic's goal is to support all of them.
|
||||||
|
|
||||||
|
Finally, the original motivation for Argument Clinic was
|
||||||
|
to provide introspection "signatures" for CPython builtins.
|
||||||
|
It used to be, the introspection query functions would throw
|
||||||
|
an exception if you passed in a builtin. With Argument
|
||||||
|
Clinic, that's a thing of the past!
|
||||||
|
|
||||||
|
One idea you should keep in mind, as you work with
|
||||||
|
Argument Clinic: the more information you give it, the
|
||||||
|
better job it'll be able to do.
|
||||||
|
Argument Clinic is admittedly relatively simple right
|
||||||
|
now. But as it evolves it will get more sophisticated,
|
||||||
|
and it should be able to do many interesting and smart
|
||||||
|
things with all the information you give it.
|
||||||
|
|
||||||
|
|
||||||
========================
|
========================
|
||||||
Basic Concepts And Usage
|
Basic Concepts And Usage
|
||||||
========================
|
========================
|
||||||
|
@ -84,7 +136,15 @@ Converting Your First Function
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
The best way to get a sense of how Argument Clinic works is to
|
The best way to get a sense of how Argument Clinic works is to
|
||||||
convert a function to work with it. Let's dive in!
|
convert a function to work with it. Here, then, are the bare
|
||||||
|
minimum steps you'd need to follow to convert a function to
|
||||||
|
work with Argument Clinic. Note that for code you plan to
|
||||||
|
check in to CPython, you really should take the conversion farther,
|
||||||
|
using some of the advanced concepts you'll see later on in
|
||||||
|
the document (like "return converters" and "self converters").
|
||||||
|
But we'll keep it simple for this walkthrough so you can learn.
|
||||||
|
|
||||||
|
Let's dive in!
|
||||||
|
|
||||||
0. Make sure you're working with a freshly updated checkout
|
0. Make sure you're working with a freshly updated checkout
|
||||||
of the CPython trunk.
|
of the CPython trunk.
|
||||||
|
@ -1282,6 +1342,264 @@ available, the macro turns into nothing. Perfect!
|
||||||
(This is the preferred approach for optional functions; in the future,
|
(This is the preferred approach for optional functions; in the future,
|
||||||
Argument Clinic may generate the entire ``PyMethodDef`` structure.)
|
Argument Clinic may generate the entire ``PyMethodDef`` structure.)
|
||||||
|
|
||||||
|
|
||||||
|
Changing and redirecting Clinic's output
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
It can be inconvenient to have Clinic's output interspersed with
|
||||||
|
your conventional hand-edited C code. Luckily, Clinic is configurable:
|
||||||
|
you can buffer up its output for printing later (or earlier!), or write
|
||||||
|
its output to a separate file. You can also add a prefix or suffix to
|
||||||
|
every line of Clinic's generated output.
|
||||||
|
|
||||||
|
While changing Clinic's output in this manner can be a boon to readability,
|
||||||
|
it may result in Clinic code using types before they are defined, or
|
||||||
|
your code attempting to use Clinic-generated code befire it is defined.
|
||||||
|
These problems can be easily solved by rearranging the declarations in your file,
|
||||||
|
or moving where Clinic's generated code goes. (This is why the default behavior
|
||||||
|
of Clinic is to output everything into the current block; while many people
|
||||||
|
consider this hampers readability, it will never require rearranging your
|
||||||
|
code to fix definition-before-use problems.)
|
||||||
|
|
||||||
|
Let's start with defining some terminology:
|
||||||
|
|
||||||
|
*field*
|
||||||
|
A field, in this context, is a subsection of Clinic's output.
|
||||||
|
For example, the ``#define`` for the ``PyMethodDef`` structure
|
||||||
|
is a field, called ``methoddef_define``. Clinic has seven
|
||||||
|
different fields it can output per function definition::
|
||||||
|
|
||||||
|
docstring_prototype
|
||||||
|
docstring_definition
|
||||||
|
methoddef_define
|
||||||
|
impl_prototype
|
||||||
|
parser_prototype
|
||||||
|
parser_definition
|
||||||
|
impl_definition
|
||||||
|
|
||||||
|
All the names are of the form ``"<a>_<b>"``,
|
||||||
|
where ``"<a>"`` is the semantic object represented (the parsing function,
|
||||||
|
the impl function, the docstring, or the methoddef structure) and ``"<b>"``
|
||||||
|
represents what kind of statement the field is. Field names that end in
|
||||||
|
``"_prototype"``
|
||||||
|
represent forward declarations of that thing, without the actual body/data
|
||||||
|
of the thing; field names that end in ``"_definition"`` represent the actual
|
||||||
|
definition of the thing, with the body/data of the thing. (``"methoddef"``
|
||||||
|
is special, it's the only one that ends with ``"_define"``, representing that
|
||||||
|
it's a preprocessor #define.)
|
||||||
|
|
||||||
|
*destination*
|
||||||
|
A destination is a place Clinic can write output to. There are
|
||||||
|
five built-in destinations:
|
||||||
|
|
||||||
|
``block``
|
||||||
|
The default destination: printed in the output section of
|
||||||
|
the current Clinic block.
|
||||||
|
|
||||||
|
``buffer``
|
||||||
|
A text buffer where you can save text for later. Text sent
|
||||||
|
here is appended to the end of any exsiting text. It's an
|
||||||
|
error to have any text left in the buffer when Clinic finishes
|
||||||
|
processing a file.
|
||||||
|
|
||||||
|
``file``
|
||||||
|
A separate "clinic file" that will be created automatically by Clinic.
|
||||||
|
The filename chosen for the file is ``{basename}.clinic{extension}``,
|
||||||
|
where ``basename`` and ``extension`` were assigned the output
|
||||||
|
from ``os.path.splitext()`` run on the current file. (Example:
|
||||||
|
the ``file`` destination for ``_pickle.c`` would be written to
|
||||||
|
``_pickle.clinic.c``.)
|
||||||
|
|
||||||
|
**Important: When using a** ``file`` **destination, you**
|
||||||
|
*must check in* **the generated file!**
|
||||||
|
|
||||||
|
``two-pass``
|
||||||
|
A buffer like ``buffer``. However, a two-pass buffer can only
|
||||||
|
be written once, and it prints out all text sent to it during
|
||||||
|
all of processing, even from Clinic blocks *after* the
|
||||||
|
|
||||||
|
``suppress``
|
||||||
|
The text is suppressed--thrown away.
|
||||||
|
|
||||||
|
|
||||||
|
Clinic defines five new directives that let you reconfigure its output.
|
||||||
|
|
||||||
|
The first new directive is ``dump``::
|
||||||
|
|
||||||
|
dump <destination>
|
||||||
|
|
||||||
|
This dumps the current contents of the named destination into the output of
|
||||||
|
the current block, and empties it. This only works with ``buffer`` and
|
||||||
|
``two-pass`` destinations.
|
||||||
|
|
||||||
|
The second new directive is ``output``. The most basic form of ``output``
|
||||||
|
is like this::
|
||||||
|
|
||||||
|
output <field> <destination>
|
||||||
|
|
||||||
|
This tells Clinic to output *field* to *destination*. ``output`` also
|
||||||
|
supports a special meta-destination, called ``everything``, which tells
|
||||||
|
Clinic to output *all* fields to that *destination*.
|
||||||
|
|
||||||
|
``output`` has a number of other functions::
|
||||||
|
|
||||||
|
output push
|
||||||
|
output pop
|
||||||
|
output preset <preset>
|
||||||
|
|
||||||
|
|
||||||
|
``output push`` and ``output pop`` allow you to push and pop
|
||||||
|
configurations on an internal configuration stack, so that you
|
||||||
|
can temporarily modify the output configuration, then easily restore
|
||||||
|
the previous configuration. Simply push before your change to save
|
||||||
|
the current configuration, then pop when you wish to restore the
|
||||||
|
previous configuration.
|
||||||
|
|
||||||
|
``output preset`` sets Clinic's output to one of several built-in
|
||||||
|
preset configurations, as follows:
|
||||||
|
|
||||||
|
``original``
|
||||||
|
Clinic's starting configuration.
|
||||||
|
|
||||||
|
Suppress the ``parser_prototype``
|
||||||
|
and ``docstring_prototype``, write everything else to ``block``.
|
||||||
|
|
||||||
|
``file``
|
||||||
|
Designed to write everything to the "clinic file" that it can.
|
||||||
|
You then ``#include`` this file near the top of your file.
|
||||||
|
You may need to rearrange your file to make this work, though
|
||||||
|
usually this just means creating forward declarations for various
|
||||||
|
``typedef`` and ``PyTypeObject`` definitions.
|
||||||
|
|
||||||
|
Suppress the ``parser_prototype``
|
||||||
|
and ``docstring_prototype``, write the ``impl_definition`` to
|
||||||
|
``block``, and write everything else to ``file``.
|
||||||
|
|
||||||
|
``buffer``
|
||||||
|
Save up all most of the output from Clinic, to be written into
|
||||||
|
your file near the end. For Python files implementing modules
|
||||||
|
or builtin types, it's recommended that you dump the buffer
|
||||||
|
just above the static structures for your module or
|
||||||
|
builtin type; these are normally very near the end. Using
|
||||||
|
``buffer`` may require even more editing than ``file``, if
|
||||||
|
your file has static ``PyMethodDef`` arrays defined in the
|
||||||
|
middle of the file.
|
||||||
|
|
||||||
|
Suppress the ``parser_prototype``, ``impl_prototype``,
|
||||||
|
and ``docstring_prototype``, write the ``impl_definition`` to
|
||||||
|
``block``, and write everything else to ``file``.
|
||||||
|
|
||||||
|
``two-pass``
|
||||||
|
Similar to the ``buffer`` preset, but writes forward declarations to
|
||||||
|
the ``two-pass`` buffer, and definitions to the ``buffer``.
|
||||||
|
This is similar to the ``buffer`` preset, but may require
|
||||||
|
less editing than ``buffer``. Dump the ``two-pass`` buffer
|
||||||
|
near the top of your file, and dump the ``buffer`` near
|
||||||
|
the end just like you would when using the ``buffer`` preset.
|
||||||
|
|
||||||
|
Suppresses the ``impl_prototype``, write the ``impl_definition``
|
||||||
|
to ``block``, write ``docstring_prototype``, ``methoddef_define``,
|
||||||
|
and ``parser_prototype`` to ``two-pass``, write everything else
|
||||||
|
to ``buffer``.
|
||||||
|
|
||||||
|
``partial-buffer``
|
||||||
|
Similar to the ``buffer`` preset, but writes more things to ``block``,
|
||||||
|
only writing the really big chunks of generated code to ``buffer``.
|
||||||
|
This avoids the definition-before-use problem of ``buffer`` completely,
|
||||||
|
at the small cost of having slightly more stuff in the block's output.
|
||||||
|
Dump the ``buffer`` near the end, just like you would when using
|
||||||
|
the ``buffer`` preset.
|
||||||
|
|
||||||
|
Suppresses the ``impl_prototype``, write the ``docstring_definition``
|
||||||
|
and ``parser_defintion`` to ``buffer``, write everything else to ``block``.
|
||||||
|
|
||||||
|
The third new directive is ``destination``::
|
||||||
|
|
||||||
|
destination <name> <command> [...]
|
||||||
|
|
||||||
|
This performs an operation on the destination named ``name``.
|
||||||
|
|
||||||
|
There are two defined subcommands: ``new`` and ``clear``.
|
||||||
|
|
||||||
|
The ``new`` subcommand works like this::
|
||||||
|
|
||||||
|
destination <name> new <type>
|
||||||
|
|
||||||
|
This creates a new destination with name ``<name>`` and type ``<type>``.
|
||||||
|
|
||||||
|
There are five destination types::
|
||||||
|
|
||||||
|
``suppress``
|
||||||
|
Throws the text away.
|
||||||
|
|
||||||
|
``block``
|
||||||
|
Writes the text to the current block. This is what Clinic
|
||||||
|
originally did.
|
||||||
|
|
||||||
|
``buffer``
|
||||||
|
A simple text buffer, like the "buffer" builtin destination above.
|
||||||
|
|
||||||
|
``file``
|
||||||
|
A text file. The file destination takes an extra argument,
|
||||||
|
a template to use for building the filename, like so:
|
||||||
|
|
||||||
|
destination <name> new <type> <file_template>
|
||||||
|
|
||||||
|
The template can use three strings internally that will be replaced
|
||||||
|
by bits of the filename:
|
||||||
|
|
||||||
|
{filename}
|
||||||
|
The full filename.
|
||||||
|
{basename}
|
||||||
|
Everything up to but not including the last '.'.
|
||||||
|
{extension}
|
||||||
|
The last '.' and everything after it.
|
||||||
|
|
||||||
|
If there are no periods in the filename, {basename} and {filename}
|
||||||
|
are the same, and {extension} is empty. "{basename}{extension}"
|
||||||
|
is always exactly the same as "{filename}"."
|
||||||
|
|
||||||
|
``two-pass``
|
||||||
|
A two-pass buffer, like the "two-pass" builtin destination above.
|
||||||
|
|
||||||
|
|
||||||
|
The ``clear`` subcommand works like this::
|
||||||
|
|
||||||
|
destination <name> clear
|
||||||
|
|
||||||
|
It removes all the accumulated text up to this point in the destination.
|
||||||
|
(I don't know what you'd need this for, but I thought maybe it'd be
|
||||||
|
useful while someone's experimenting.)
|
||||||
|
|
||||||
|
The fourth new directive is ``set``::
|
||||||
|
|
||||||
|
set line_prefix "string"
|
||||||
|
set line_suffix "string"
|
||||||
|
|
||||||
|
``set`` lets you set two internal variables in Clinic.
|
||||||
|
``line_prefix`` is a string that will be prepended to every line of Clinic's output;
|
||||||
|
``line_suffix`` is a string that will be appended to every line of Clinic's output.
|
||||||
|
|
||||||
|
Both of these suport two format strings:
|
||||||
|
|
||||||
|
``{block comment start}``
|
||||||
|
Turns into the string ``/*``, the start-comment text sequence for C files.
|
||||||
|
|
||||||
|
``{block comment end}``
|
||||||
|
Turns into the string ``*/``, the end-comment text sequence for C files.
|
||||||
|
|
||||||
|
The final new directive is one you shouldn't need to use directly,
|
||||||
|
called ``preserve``::
|
||||||
|
|
||||||
|
preserve
|
||||||
|
|
||||||
|
This tells Clinic that the current contents of the output should be kept, unmodifed.
|
||||||
|
This is used internally by Clinic when dumping output into ``file`` files; wrapping
|
||||||
|
it in a Clinic block lets Clinic use its existing checksum functionality to ensure
|
||||||
|
the file was not modified by hand before it gets overwritten.
|
||||||
|
|
||||||
|
|
||||||
|
Using Argument Clinic in Python files
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
It's actually possible to use Argument Clinic to preprocess Python files.
|
It's actually possible to use Argument Clinic to preprocess Python files.
|
||||||
|
|
|
@ -88,6 +88,9 @@ Tests
|
||||||
Tools/Demos
|
Tools/Demos
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
- Issue #20287: Argument Clinic's output is now configurable, allowing
|
||||||
|
delaying its output or even redirecting it to a separate file.
|
||||||
|
|
||||||
- Issue #20226: Argument Clinic now permits simple expressions
|
- Issue #20226: Argument Clinic now permits simple expressions
|
||||||
(e.g. "sys.maxsize - 1") as default values for parameters.
|
(e.g. "sys.maxsize - 1") as default values for parameters.
|
||||||
|
|
||||||
|
|
|
@ -3906,16 +3906,12 @@ _pickle_Pickler_clear_memo_impl(PicklerObject *self);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_Pickler_clear_memo(PyObject *self, PyObject *Py_UNUSED(ignored))
|
_pickle_Pickler_clear_memo(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _pickle_Pickler_clear_memo_impl((PicklerObject *)self);
|
||||||
|
|
||||||
return_value = _pickle_Pickler_clear_memo_impl((PicklerObject *)self);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_Pickler_clear_memo_impl(PicklerObject *self)
|
_pickle_Pickler_clear_memo_impl(PicklerObject *self)
|
||||||
/*[clinic end generated code: checksum=0574593b102fffb8e781d7bb9b536ceffc525ac1]*/
|
/*[clinic end generated code: checksum=015cc3c5befea86cb08b9396938477bebbea4157]*/
|
||||||
{
|
{
|
||||||
if (self->memo)
|
if (self->memo)
|
||||||
PyMemoTable_Clear(self->memo);
|
PyMemoTable_Clear(self->memo);
|
||||||
|
@ -4191,16 +4187,12 @@ _pickle_PicklerMemoProxy_clear_impl(PicklerMemoProxyObject *self);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_PicklerMemoProxy_clear(PyObject *self, PyObject *Py_UNUSED(ignored))
|
_pickle_PicklerMemoProxy_clear(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _pickle_PicklerMemoProxy_clear_impl((PicklerMemoProxyObject *)self);
|
||||||
|
|
||||||
return_value = _pickle_PicklerMemoProxy_clear_impl((PicklerMemoProxyObject *)self);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_PicklerMemoProxy_clear_impl(PicklerMemoProxyObject *self)
|
_pickle_PicklerMemoProxy_clear_impl(PicklerMemoProxyObject *self)
|
||||||
/*[clinic end generated code: checksum=c6ca252530ccb3ea2f4b33507b51b183f23b24c7]*/
|
/*[clinic end generated code: checksum=bf8dd8c8688d0c0f7a2e59a804c47375b740f2f0]*/
|
||||||
{
|
{
|
||||||
if (self->pickler->memo)
|
if (self->pickler->memo)
|
||||||
PyMemoTable_Clear(self->pickler->memo);
|
PyMemoTable_Clear(self->pickler->memo);
|
||||||
|
@ -4228,16 +4220,12 @@ _pickle_PicklerMemoProxy_copy_impl(PicklerMemoProxyObject *self);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_PicklerMemoProxy_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
|
_pickle_PicklerMemoProxy_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _pickle_PicklerMemoProxy_copy_impl((PicklerMemoProxyObject *)self);
|
||||||
|
|
||||||
return_value = _pickle_PicklerMemoProxy_copy_impl((PicklerMemoProxyObject *)self);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_PicklerMemoProxy_copy_impl(PicklerMemoProxyObject *self)
|
_pickle_PicklerMemoProxy_copy_impl(PicklerMemoProxyObject *self)
|
||||||
/*[clinic end generated code: checksum=808c4d5a37359ed5fb2efe81dbe5ff480719f470]*/
|
/*[clinic end generated code: checksum=72d46879dc658adbd3d28b5c82dd8dcfa6b9b124]*/
|
||||||
{
|
{
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
PyMemoTable *memo;
|
PyMemoTable *memo;
|
||||||
|
@ -4295,16 +4283,12 @@ _pickle_PicklerMemoProxy___reduce___impl(PicklerMemoProxyObject *self);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_PicklerMemoProxy___reduce__(PyObject *self, PyObject *Py_UNUSED(ignored))
|
_pickle_PicklerMemoProxy___reduce__(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _pickle_PicklerMemoProxy___reduce___impl((PicklerMemoProxyObject *)self);
|
||||||
|
|
||||||
return_value = _pickle_PicklerMemoProxy___reduce___impl((PicklerMemoProxyObject *)self);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_PicklerMemoProxy___reduce___impl(PicklerMemoProxyObject *self)
|
_pickle_PicklerMemoProxy___reduce___impl(PicklerMemoProxyObject *self)
|
||||||
/*[clinic end generated code: checksum=2293152bdf53951a012d430767b608f5fb4213b5]*/
|
/*[clinic end generated code: checksum=aad71c4d81d1ed8bf0d32362dd80a29b9f3b0d03]*/
|
||||||
{
|
{
|
||||||
PyObject *reduce_value, *dict_args;
|
PyObject *reduce_value, *dict_args;
|
||||||
PyObject *contents = _pickle_PicklerMemoProxy_copy_impl(self);
|
PyObject *contents = _pickle_PicklerMemoProxy_copy_impl(self);
|
||||||
|
@ -6342,16 +6326,12 @@ _pickle_Unpickler_load_impl(PyObject *self);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_Unpickler_load(PyObject *self, PyObject *Py_UNUSED(ignored))
|
_pickle_Unpickler_load(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _pickle_Unpickler_load_impl(self);
|
||||||
|
|
||||||
return_value = _pickle_Unpickler_load_impl(self);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_Unpickler_load_impl(PyObject *self)
|
_pickle_Unpickler_load_impl(PyObject *self)
|
||||||
/*[clinic end generated code: checksum=55f35fcaf034817e75c355ec50b7878577355899]*/
|
/*[clinic end generated code: checksum=9477099fe6a90748c13ff1a6dd92ba7ab7a89602]*/
|
||||||
{
|
{
|
||||||
UnpicklerObject *unpickler = (UnpicklerObject*)self;
|
UnpicklerObject *unpickler = (UnpicklerObject*)self;
|
||||||
|
|
||||||
|
@ -6417,8 +6397,8 @@ _pickle_Unpickler_find_class(PyObject *self, PyObject *args)
|
||||||
PyObject *module_name;
|
PyObject *module_name;
|
||||||
PyObject *global_name;
|
PyObject *global_name;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args,
|
if (!PyArg_UnpackTuple(args, "find_class",
|
||||||
"OO:find_class",
|
2, 2,
|
||||||
&module_name, &global_name))
|
&module_name, &global_name))
|
||||||
goto exit;
|
goto exit;
|
||||||
return_value = _pickle_Unpickler_find_class_impl((UnpicklerObject *)self, module_name, global_name);
|
return_value = _pickle_Unpickler_find_class_impl((UnpicklerObject *)self, module_name, global_name);
|
||||||
|
@ -6429,7 +6409,7 @@ exit:
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyObject *module_name, PyObject *global_name)
|
_pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyObject *module_name, PyObject *global_name)
|
||||||
/*[clinic end generated code: checksum=1f353d13a32c9d94feb1466b3c2d0529a7e5650e]*/
|
/*[clinic end generated code: checksum=15ed4836fd5860425fff9ea7855d4f1f4413c170]*/
|
||||||
{
|
{
|
||||||
PyObject *global;
|
PyObject *global;
|
||||||
PyObject *modules_dict;
|
PyObject *modules_dict;
|
||||||
|
@ -6752,16 +6732,12 @@ _pickle_UnpicklerMemoProxy_clear_impl(UnpicklerMemoProxyObject *self);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_UnpicklerMemoProxy_clear(PyObject *self, PyObject *Py_UNUSED(ignored))
|
_pickle_UnpicklerMemoProxy_clear(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _pickle_UnpicklerMemoProxy_clear_impl((UnpicklerMemoProxyObject *)self);
|
||||||
|
|
||||||
return_value = _pickle_UnpicklerMemoProxy_clear_impl((UnpicklerMemoProxyObject *)self);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_UnpicklerMemoProxy_clear_impl(UnpicklerMemoProxyObject *self)
|
_pickle_UnpicklerMemoProxy_clear_impl(UnpicklerMemoProxyObject *self)
|
||||||
/*[clinic end generated code: checksum=e0f99c26d48444a3f58f598bec3190c66595fce7]*/
|
/*[clinic end generated code: checksum=07adecee2181e5e268b2ff184360b1d88ad947f2]*/
|
||||||
{
|
{
|
||||||
_Unpickler_MemoCleanup(self->unpickler);
|
_Unpickler_MemoCleanup(self->unpickler);
|
||||||
self->unpickler->memo = _Unpickler_NewMemo(self->unpickler->memo_size);
|
self->unpickler->memo = _Unpickler_NewMemo(self->unpickler->memo_size);
|
||||||
|
@ -6791,16 +6767,12 @@ _pickle_UnpicklerMemoProxy_copy_impl(UnpicklerMemoProxyObject *self);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_UnpicklerMemoProxy_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
|
_pickle_UnpicklerMemoProxy_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _pickle_UnpicklerMemoProxy_copy_impl((UnpicklerMemoProxyObject *)self);
|
||||||
|
|
||||||
return_value = _pickle_UnpicklerMemoProxy_copy_impl((UnpicklerMemoProxyObject *)self);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_UnpicklerMemoProxy_copy_impl(UnpicklerMemoProxyObject *self)
|
_pickle_UnpicklerMemoProxy_copy_impl(UnpicklerMemoProxyObject *self)
|
||||||
/*[clinic end generated code: checksum=8c0ab91c0b694ea71a1774650898a760d1ab4765]*/
|
/*[clinic end generated code: checksum=47b9f0cc12c5a54004252e1b4916822cdfa8a881]*/
|
||||||
{
|
{
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
PyObject *new_memo = PyDict_New();
|
PyObject *new_memo = PyDict_New();
|
||||||
|
@ -6851,16 +6823,12 @@ _pickle_UnpicklerMemoProxy___reduce___impl(UnpicklerMemoProxyObject *self);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_UnpicklerMemoProxy___reduce__(PyObject *self, PyObject *Py_UNUSED(ignored))
|
_pickle_UnpicklerMemoProxy___reduce__(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _pickle_UnpicklerMemoProxy___reduce___impl((UnpicklerMemoProxyObject *)self);
|
||||||
|
|
||||||
return_value = _pickle_UnpicklerMemoProxy___reduce___impl((UnpicklerMemoProxyObject *)self);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_pickle_UnpicklerMemoProxy___reduce___impl(UnpicklerMemoProxyObject *self)
|
_pickle_UnpicklerMemoProxy___reduce___impl(UnpicklerMemoProxyObject *self)
|
||||||
/*[clinic end generated code: checksum=4ee76a65511291f0de2e9e63db395d2e5d6d8df6]*/
|
/*[clinic end generated code: checksum=2f061bb9ecd9ee8500184c135148a131c46a3b88]*/
|
||||||
{
|
{
|
||||||
PyObject *reduce_value;
|
PyObject *reduce_value;
|
||||||
PyObject *constructor_args;
|
PyObject *constructor_args;
|
||||||
|
|
|
@ -34,6 +34,7 @@ _weakref_getweakrefcount(PyModuleDef *module, PyObject *object)
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
Py_ssize_t _return_value;
|
Py_ssize_t _return_value;
|
||||||
|
|
||||||
_return_value = _weakref_getweakrefcount_impl(module, object);
|
_return_value = _weakref_getweakrefcount_impl(module, object);
|
||||||
if ((_return_value == -1) && PyErr_Occurred())
|
if ((_return_value == -1) && PyErr_Occurred())
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -45,7 +46,7 @@ exit:
|
||||||
|
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
_weakref_getweakrefcount_impl(PyModuleDef *module, PyObject *object)
|
_weakref_getweakrefcount_impl(PyModuleDef *module, PyObject *object)
|
||||||
/*[clinic end generated code: checksum=436e8fbe0297434375f039d8c2d9fc3a9bbe773c]*/
|
/*[clinic end generated code: checksum=744fa73ba68c0ee89567e9cb9bea11863270d516]*/
|
||||||
{
|
{
|
||||||
PyWeakReference **list;
|
PyWeakReference **list;
|
||||||
|
|
||||||
|
|
|
@ -1047,16 +1047,12 @@ zlib_Compress_copy_impl(compobject *self);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
zlib_Compress_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
|
zlib_Compress_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return zlib_Compress_copy_impl((compobject *)self);
|
||||||
|
|
||||||
return_value = zlib_Compress_copy_impl((compobject *)self);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
zlib_Compress_copy_impl(compobject *self)
|
zlib_Compress_copy_impl(compobject *self)
|
||||||
/*[clinic end generated code: checksum=2f454ee15be3bc53cfb4e845c3f891f68be4c8e4]*/
|
/*[clinic end generated code: checksum=d57a7911deb7940e85a8d7e65af20b6e2df69000]*/
|
||||||
{
|
{
|
||||||
compobject *retval = NULL;
|
compobject *retval = NULL;
|
||||||
int err;
|
int err;
|
||||||
|
|
|
@ -246,16 +246,12 @@ _imp_lock_held_impl(PyModuleDef *module);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_imp_lock_held(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
|
_imp_lock_held(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _imp_lock_held_impl(module);
|
||||||
|
|
||||||
return_value = _imp_lock_held_impl(module);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_imp_lock_held_impl(PyModuleDef *module)
|
_imp_lock_held_impl(PyModuleDef *module)
|
||||||
/*[clinic end generated code: checksum=c5858b257881f94dee95526229a8d1a57ccff158]*/
|
/*[clinic end generated code: checksum=ede1cafb78eb22e3009602f684c8b780e2b82d62]*/
|
||||||
{
|
{
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
return PyBool_FromLong(import_lock_thread != -1);
|
return PyBool_FromLong(import_lock_thread != -1);
|
||||||
|
@ -289,16 +285,12 @@ _imp_acquire_lock_impl(PyModuleDef *module);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_imp_acquire_lock(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
|
_imp_acquire_lock(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _imp_acquire_lock_impl(module);
|
||||||
|
|
||||||
return_value = _imp_acquire_lock_impl(module);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_imp_acquire_lock_impl(PyModuleDef *module)
|
_imp_acquire_lock_impl(PyModuleDef *module)
|
||||||
/*[clinic end generated code: checksum=badb56ed0079a6b902c9616fe068d572765b1863]*/
|
/*[clinic end generated code: checksum=5b520b2416c5954a7cf0ed30955d68abe20b5868]*/
|
||||||
{
|
{
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
_PyImport_AcquireLock();
|
_PyImport_AcquireLock();
|
||||||
|
@ -330,16 +322,12 @@ _imp_release_lock_impl(PyModuleDef *module);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_imp_release_lock(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
|
_imp_release_lock(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _imp_release_lock_impl(module);
|
||||||
|
|
||||||
return_value = _imp_release_lock_impl(module);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_imp_release_lock_impl(PyModuleDef *module)
|
_imp_release_lock_impl(PyModuleDef *module)
|
||||||
/*[clinic end generated code: checksum=f1c2a75e3136a113184e0af2a676d5f0b5b685b4]*/
|
/*[clinic end generated code: checksum=efcd9d2923294c04371596e7f6d66a706d43fcac]*/
|
||||||
{
|
{
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
if (_PyImport_ReleaseLock() < 0) {
|
if (_PyImport_ReleaseLock() < 0) {
|
||||||
|
@ -1847,16 +1835,12 @@ _imp_extension_suffixes_impl(PyModuleDef *module);
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_imp_extension_suffixes(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
|
_imp_extension_suffixes(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
PyObject *return_value = NULL;
|
return _imp_extension_suffixes_impl(module);
|
||||||
|
|
||||||
return_value = _imp_extension_suffixes_impl(module);
|
|
||||||
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_imp_extension_suffixes_impl(PyModuleDef *module)
|
_imp_extension_suffixes_impl(PyModuleDef *module)
|
||||||
/*[clinic end generated code: checksum=835921e67fd698e22e101eea64839d1ad62b6451]*/
|
/*[clinic end generated code: checksum=82fb35d8429a429a4dc80c84b45b1aad73ff1de7]*/
|
||||||
{
|
{
|
||||||
PyObject *list;
|
PyObject *list;
|
||||||
const char *suffix;
|
const char *suffix;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -34,6 +34,9 @@ class FakeConvertersDict:
|
||||||
def get(self, name, default):
|
def get(self, name, default):
|
||||||
return self.used_converters.setdefault(name, FakeConverterFactory(name))
|
return self.used_converters.setdefault(name, FakeConverterFactory(name))
|
||||||
|
|
||||||
|
clinic.Clinic.presets_text = ''
|
||||||
|
c = clinic.Clinic(language='C')
|
||||||
|
|
||||||
class FakeClinic:
|
class FakeClinic:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.converters = FakeConvertersDict()
|
self.converters = FakeConvertersDict()
|
||||||
|
@ -44,6 +47,32 @@ class FakeClinic:
|
||||||
self.modules = collections.OrderedDict()
|
self.modules = collections.OrderedDict()
|
||||||
clinic.clinic = self
|
clinic.clinic = self
|
||||||
self.name = "FakeClinic"
|
self.name = "FakeClinic"
|
||||||
|
self.line_prefix = self.line_suffix = ''
|
||||||
|
self.destinations = {}
|
||||||
|
self.add_destination("block", "buffer")
|
||||||
|
self.add_destination("file", "buffer")
|
||||||
|
self.add_destination("suppress", "suppress")
|
||||||
|
d = self.destinations.get
|
||||||
|
self.field_destinations = collections.OrderedDict((
|
||||||
|
('docstring_prototype', d('suppress')),
|
||||||
|
('docstring_definition', d('block')),
|
||||||
|
('methoddef_define', d('block')),
|
||||||
|
('impl_prototype', d('block')),
|
||||||
|
('parser_prototype', d('suppress')),
|
||||||
|
('parser_definition', d('block')),
|
||||||
|
('impl_definition', d('block')),
|
||||||
|
))
|
||||||
|
|
||||||
|
def get_destination(self, name):
|
||||||
|
d = self.destinations.get(name)
|
||||||
|
if not d:
|
||||||
|
sys.exit("Destination does not exist: " + repr(name))
|
||||||
|
return d
|
||||||
|
|
||||||
|
def add_destination(self, name, type, *args):
|
||||||
|
if name in self.destinations:
|
||||||
|
sys.exit("Destination already exists: " + repr(name))
|
||||||
|
self.destinations[name] = clinic.Destination(name, type, self, *args)
|
||||||
|
|
||||||
def is_directive(self, name):
|
def is_directive(self, name):
|
||||||
return name == "module"
|
return name == "module"
|
||||||
|
|
Loading…
Reference in New Issue