Docs: Remove the numbered steps from the Argument Clinic tutorial (#107203)

Instead, order the tutorial as one body of prose, making it easier to
align the tutorial according to Diátaxis principles.
This commit is contained in:
Erlend E. Aasland 2023-07-26 22:54:25 +02:00 committed by GitHub
parent 5aa6964a5c
commit 592395577c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 333 additions and 337 deletions

View File

@ -167,23 +167,23 @@ convert a function to work with it. Here, then, are the bare
minimum steps you'd need to follow to convert a function to minimum steps you'd need to follow to convert a function to
work with Argument Clinic. Note that for code you plan to work with Argument Clinic. Note that for code you plan to
check in to CPython, you really should take the conversion farther, check in to CPython, you really should take the conversion farther,
using some of the advanced concepts you'll see later on in using some of the :ref:`advanced concepts <clinic-howtos>`
the document (like "return converters" and "self converters"). you'll see later on in the document,
like :ref:`clinic-howto-return-converters`
and :ref:`clinic-howto-self-converter`.
But we'll keep it simple for this walkthrough so you can learn. But we'll keep it simple for this walkthrough so you can learn.
Let's dive in! First, make sure you're working with a freshly updated checkout
of the CPython trunk.
0. Make sure you're working with a freshly updated checkout Next, find a Python builtin that calls either :c:func:`PyArg_ParseTuple`
of the CPython trunk. or :c:func:`PyArg_ParseTupleAndKeywords`, and hasn't been converted
to work with Argument Clinic yet.
For this tutorial, we'll be using
:py:meth:`_pickle.Pickler.dump <pickle.Pickler.dump>`.
1. Find a Python builtin that calls either :c:func:`PyArg_ParseTuple` If the call to the :c:func:`!PyArg_Parse*` function uses any of the
or :c:func:`PyArg_ParseTupleAndKeywords`, and hasn't been converted following format units...:
to work with Argument Clinic yet.
For my example I'm using
:py:meth:`_pickle.Pickler.dump <pickle.Pickler.dump>`.
2. If the call to the :c:func:`!PyArg_Parse*` function uses any of the
following format units:
.. code-block:: none .. code-block:: none
@ -194,388 +194,377 @@ Let's dive in!
et et
et# et#
or if it has multiple calls to :c:func:`PyArg_ParseTuple`, ... or if it has multiple calls to :c:func:`PyArg_ParseTuple`,
you should choose a different function. Argument Clinic *does* you should choose a different function.
support all of these scenarios. But these are advanced (See :ref:`clinic-howto-advanced-converters` for those scenarios.)
topics—let's do something simpler for your first function.
Also, if the function has multiple calls to :c:func:`!PyArg_ParseTuple` Also, if the function has multiple calls to :c:func:`!PyArg_ParseTuple`
or :c:func:`PyArg_ParseTupleAndKeywords` where it supports different or :c:func:`PyArg_ParseTupleAndKeywords` where it supports different
types for the same argument, or if the function uses something besides types for the same argument, or if the function uses something besides
:c:func:`!PyArg_Parse*` functions to parse its arguments, it probably :c:func:`!PyArg_Parse*` functions to parse its arguments, it probably
isn't suitable for conversion to Argument Clinic. Argument Clinic isn't suitable for conversion to Argument Clinic. Argument Clinic
doesn't support generic functions or polymorphic parameters. doesn't support generic functions or polymorphic parameters.
3. Add the following boilerplate above the function, creating our block:: Next, add the following boilerplate above the function,
creating our input block::
/*[clinic input] /*[clinic input]
[clinic start generated code]*/ [clinic start generated code]*/
4. Cut the docstring and paste it in between the ``[clinic]`` lines, Cut the docstring and paste it in between the ``[clinic]`` lines,
removing all the junk that makes it a properly quoted C string. removing all the junk that makes it a properly quoted C string.
When you're done you should have just the text, based at the left When you're done you should have just the text, based at the left
margin, with no line wider than 80 characters. margin, with no line wider than 80 characters.
(Argument Clinic will preserve indents inside the docstring.) Argument Clinic will preserve indents inside the docstring.
If the old docstring had a first line that looked like a function
signature, throw that line away; The docstring doesn't need it anymore ---
when you use :py:func:`help` on your builtin in the future,
the first line will be built automatically based on the function's signature.
If the old docstring had a first line that looked like a function Example docstring summary line::
signature, throw that line away. (The docstring doesn't need it
anymore—when you use :py:func:`help` on your builtin in the future,
the first line will be built automatically based on the function's
signature.)
Sample:: /*[clinic input]
Write a pickled representation of obj to the open file.
[clinic start generated code]*/
/*[clinic input] If your docstring doesn't have a "summary" line, Argument Clinic will
Write a pickled representation of obj to the open file. complain, so let's make sure it has one. The "summary" line should
[clinic start generated code]*/ be a paragraph consisting of a single 80-column line
at the beginning of the docstring.
(See :pep:`257` regarding docstring conventions.)
5. If your docstring doesn't have a "summary" line, Argument Clinic will Our example docstring consists solely of a summary line, so the sample
complain. So let's make sure it has one. The "summary" line should code doesn't have to change for this step.
be a paragraph consisting of a single 80-column line
at the beginning of the docstring.
(Our example docstring consists solely of a summary line, so the sample Now, above the docstring, enter the name of the function, followed
code doesn't have to change for this step.) by a blank line. This should be the Python name of the function,
and should be the full dotted path to the function ---
it should start with the name of the module,
include any sub-modules, and if the function is a method on
a class it should include the class name too.
6. Above the docstring, enter the name of the function, followed In our example, :mod:`!_pickle` is the module, :py:class:`!Pickler` is the class,
by a blank line. This should be the Python name of the function, and :py:meth:`!dump` is the method, so the name becomes
and should be the full dotted path :py:meth:`!_pickle.Pickler.dump`::
to the function—it should start with the name of the module,
include any sub-modules, and if the function is a method on
a class it should include the class name too.
Sample:: /*[clinic input]
_pickle.Pickler.dump
/*[clinic input] Write a pickled representation of obj to the open file.
_pickle.Pickler.dump [clinic start generated code]*/
Write a pickled representation of obj to the open file. If this is the first time that module or class has been used with Argument
[clinic start generated code]*/ Clinic in this C file,
you must declare the module and/or class. Proper Argument Clinic hygiene
prefers declaring these in a separate block somewhere near the
top of the C file, in the same way that include files and statics go at
the top.
In our sample code we'll just show the two blocks next to each other.
7. If this is the first time that module or class has been used with Argument The name of the class and module should be the same as the one
Clinic in this C file, seen by Python. Check the name defined in the :c:type:`PyModuleDef`
you must declare the module and/or class. Proper Argument Clinic hygiene or :c:type:`PyTypeObject` as appropriate.
prefers declaring these in a separate block somewhere near the
top of the C file, in the same way that include files and statics go at
the top. (In our sample code we'll just show the two blocks next to
each other.)
The name of the class and module should be the same as the one When you declare a class, you must also specify two aspects of its type
seen by Python. Check the name defined in the :c:type:`PyModuleDef` in C: the type declaration you'd use for a pointer to an instance of
or :c:type:`PyTypeObject` as appropriate. this class, and a pointer to the :c:type:`!PyTypeObject` for this class::
When you declare a class, you must also specify two aspects of its type /*[clinic input]
in C: the type declaration you'd use for a pointer to an instance of module _pickle
this class, and a pointer to the :c:type:`!PyTypeObject` for this class. class _pickle.Pickler "PicklerObject *" "&Pickler_Type"
[clinic start generated code]*/
Sample:: /*[clinic input]
_pickle.Pickler.dump
/*[clinic input] Write a pickled representation of obj to the open file.
module _pickle [clinic start generated code]*/
class _pickle.Pickler "PicklerObject *" "&Pickler_Type"
[clinic start generated code]*/
/*[clinic input] Declare each of the parameters to the function. Each parameter
_pickle.Pickler.dump should get its own line. All the parameter lines should be
indented from the function name and the docstring.
The general form of these parameter lines is as follows:
Write a pickled representation of obj to the open file. .. code-block:: none
[clinic start generated code]*/
name_of_parameter: converter
If the parameter has a default value, add that after the
converter:
.. code-block:: none
8. Declare each of the parameters to the function. Each parameter name_of_parameter: converter = default_value
should get its own line. All the parameter lines should be
indented from the function name and the docstring.
The general form of these parameter lines is as follows: Argument Clinic's support for "default values" is quite sophisticated;
see :ref:`clinic-howto-default-values` for more information.
.. code-block:: none Next, add a blank line below the parameters.
name_of_parameter: converter What's a "converter"?
It establishes both the type of the variable used in C,
and the method to convert the Python value into a C value at runtime.
For now you're going to use what's called a "legacy converter" ---
a convenience syntax intended to make porting old code into Argument
Clinic easier.
If the parameter has a default value, add that after the For each parameter, copy the "format unit" for that
converter: parameter from the :c:func:`PyArg_Parse` format argument and
specify *that* as its converter, as a quoted string.
The "format unit" is the formal name for the one-to-three
character substring of the *format* parameter that tells
the argument parsing function what the type of the variable
is and how to convert it.
For more on format units please see :ref:`arg-parsing`.
.. code-block:: none For multicharacter format units like ``z#``,
use the entire two-or-three character string.
name_of_parameter: converter = default_value Sample::
Argument Clinic's support for "default values" is quite sophisticated; /*[clinic input]
please see :ref:`the section below on default values <default_values>` module _pickle
for more information. class _pickle.Pickler "PicklerObject *" "&Pickler_Type"
[clinic start generated code]*/
Add a blank line below the parameters. /*[clinic input]
_pickle.Pickler.dump
What's a "converter"? It establishes both the type obj: 'O'
of the variable used in C, and the method to convert the Python
value into a C value at runtime.
For now you're going to use what's called a "legacy converter"—a
convenience syntax intended to make porting old code into Argument
Clinic easier.
For each parameter, copy the "format unit" for that Write a pickled representation of obj to the open file.
parameter from the :c:func:`PyArg_Parse` format argument and [clinic start generated code]*/
specify *that* as its converter, as a quoted
string. ("format unit" is the formal name for the one-to-three
character substring of the *format* parameter that tells
the argument parsing function what the type of the variable
is and how to convert it. For more on format units please
see :ref:`arg-parsing`.)
For multicharacter format units like ``z#``, use the If your function has ``|`` in the format string,
entire two-or-three character string. meaning some parameters have default values, you can ignore it.
Argument Clinic infers which parameters are optional
based on whether or not they have default values.
Sample:: If your function has ``$`` in the format string,
meaning it takes keyword-only arguments,
specify ``*`` on a line by itself before the first keyword-only argument,
indented the same as the parameter lines.
/*[clinic input] :py:meth:`!_pickle.Pickler.dump` has neither, so our sample is unchanged.
module _pickle
class _pickle.Pickler "PicklerObject *" "&Pickler_Type"
[clinic start generated code]*/
/*[clinic input] Next, if the existing C function calls :c:func:`PyArg_ParseTuple`
_pickle.Pickler.dump (as opposed to :c:func:`PyArg_ParseTupleAndKeywords`), then all its
arguments are positional-only.
obj: 'O' To mark parameters as positional-only in Argument Clinic,
add a ``/`` on a line by itself after the last positional-only parameter,
indented the same as the parameter lines.
Write a pickled representation of obj to the open file. Sample::
[clinic start generated code]*/
9. If your function has ``|`` in the format string, meaning some /*[clinic input]
parameters have default values, you can ignore it. Argument module _pickle
Clinic infers which parameters are optional based on whether class _pickle.Pickler "PicklerObject *" "&Pickler_Type"
or not they have default values. [clinic start generated code]*/
If your function has ``$`` in the format string, meaning it /*[clinic input]
takes keyword-only arguments, specify ``*`` on a line by _pickle.Pickler.dump
itself before the first keyword-only argument, indented the
same as the parameter lines.
(:py:meth:`!_pickle.Pickler.dump` has neither, so our sample is unchanged.) obj: 'O'
/
Write a pickled representation of obj to the open file.
[clinic start generated code]*/
10. If the existing C function calls :c:func:`PyArg_ParseTuple` It can be helpful to write a per-parameter docstring for each parameter.
(as opposed to :c:func:`PyArg_ParseTupleAndKeywords`), then all its Since per-parameter docstrings are optional,
arguments are positional-only. you can skip this step if you prefer.
To mark all parameters as positional-only in Argument Clinic, Nevertheless, here's how to add a per-parameter docstring.
add a ``/`` on a line by itself after the last parameter, The first line of the per-parameter docstring
indented the same as the parameter lines. must be indented further than the parameter definition.
The left margin of this first line establishes
the left margin for the whole per-parameter docstring;
all the text you write will be outdented by this amount.
You can write as much text as you like, across multiple lines if you wish.
Currently this is all-or-nothing; either all parameters are Sample::
positional-only, or none of them are. (In the future Argument
Clinic may relax this restriction.)
Sample:: /*[clinic input]
module _pickle
class _pickle.Pickler "PicklerObject *" "&Pickler_Type"
[clinic start generated code]*/
/*[clinic input] /*[clinic input]
module _pickle _pickle.Pickler.dump
class _pickle.Pickler "PicklerObject *" "&Pickler_Type"
[clinic start generated code]*/
/*[clinic input] obj: 'O'
_pickle.Pickler.dump The object to be pickled.
/
obj: 'O' Write a pickled representation of obj to the open file.
/ [clinic start generated code]*/
Write a pickled representation of obj to the open file. Save and close the file, then run ``Tools/clinic/clinic.py`` on it.
[clinic start generated code]*/ With luck everything worked---your block now has output,
and a :file:`.c.h` file has been generated!
Reload the file in your text editor to see the generated code::
11. It's helpful to write a per-parameter docstring for each parameter. /*[clinic input]
But per-parameter docstrings are optional; you can skip this step _pickle.Pickler.dump
if you prefer.
Here's how to add a per-parameter docstring. The first line obj: 'O'
of the per-parameter docstring must be indented further than the The object to be pickled.
parameter definition. The left margin of this first line establishes /
the left margin for the whole per-parameter docstring; all the text
you write will be outdented by this amount. You can write as much
text as you like, across multiple lines if you wish.
Sample:: Write a pickled representation of obj to the open file.
[clinic start generated code]*/
/*[clinic input] static PyObject *
module _pickle _pickle_Pickler_dump(PicklerObject *self, PyObject *obj)
class _pickle.Pickler "PicklerObject *" "&Pickler_Type" /*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/
[clinic start generated code]*/
Obviously, if Argument Clinic didn't produce any output,
/*[clinic input] it's because it found an error in your input.
_pickle.Pickler.dump Keep fixing your errors and retrying until Argument Clinic processes your file
without complaint.
obj: 'O'
The object to be pickled. For readability, most of the glue code has been generated to a :file:`.c.h`
/ file. You'll need to include that in your original :file:`.c` file,
typically right after the clinic module block::
Write a pickled representation of obj to the open file.
[clinic start generated code]*/ #include "clinic/_pickle.c.h"
12. Save and close the file, then run ``Tools/clinic/clinic.py`` on Double-check that the argument-parsing code Argument Clinic generated
it. With luck everything worked---your block now has output, and looks basically the same as the existing code.
a :file:`.c.h` file has been generated! Reopen the file in your
text editor to see:: First, ensure both places use the same argument-parsing function.
The existing code must call either
/*[clinic input] :c:func:`PyArg_ParseTuple` or :c:func:`PyArg_ParseTupleAndKeywords`;
_pickle.Pickler.dump ensure that the code generated by Argument Clinic calls the
*exact* same function.
obj: 'O'
The object to be pickled. Second, the format string passed in to :c:func:`!PyArg_ParseTuple` or
/ :c:func:`!PyArg_ParseTupleAndKeywords` should be *exactly* the same
as the hand-written one in the existing function,
Write a pickled representation of obj to the open file. up to the colon or semi-colon.
[clinic start generated code]*/
Argument Clinic always generates its format strings
static PyObject * with a ``:`` followed by the name of the function.
_pickle_Pickler_dump(PicklerObject *self, PyObject *obj) If the existing code's format string ends with ``;``,
/*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/ to provide usage help, this change is harmless --- don't worry about it.
Obviously, if Argument Clinic didn't produce any output, it's because Third, for parameters whose format units require two arguments,
it found an error in your input. Keep fixing your errors and retrying like a length variable, an encoding string, or a pointer
until Argument Clinic processes your file without complaint. to a conversion function, ensure that the second argument is
*exactly* the same between the two invocations.
For readability, most of the glue code has been generated to a :file:`.c.h`
file. You'll need to include that in your original :file:`.c` file, Fourth, inside the output portion of the block,
typically right after the clinic module block:: you'll find a preprocessor macro defining the appropriate static
:c:type:`PyMethodDef` structure for this builtin::
#include "clinic/_pickle.c.h"
#define __PICKLE_PICKLER_DUMP_METHODDEF \
13. Double-check that the argument-parsing code Argument Clinic generated {"dump", (PyCFunction)__pickle_Pickler_dump, METH_O, __pickle_Pickler_dump__doc__},
looks basically the same as the existing code.
This static structure should be *exactly* the same as the existing static
First, ensure both places use the same argument-parsing function. :c:type:`!PyMethodDef` structure for this builtin.
The existing code must call either
:c:func:`PyArg_ParseTuple` or :c:func:`PyArg_ParseTupleAndKeywords`; If any of these items differ in *any way*,
ensure that the code generated by Argument Clinic calls the adjust your Argument Clinic function specification and rerun
*exact* same function. ``Tools/clinic/clinic.py`` until they *are* the same.
Second, the format string passed in to :c:func:`!PyArg_ParseTuple` or Notice that the last line of its output is the declaration
:c:func:`!PyArg_ParseTupleAndKeywords` should be *exactly* the same of your "impl" function. This is where the builtin's implementation goes.
as the hand-written one in the existing function, up to the colon Delete the existing prototype of the function you're modifying, but leave
or semi-colon. the opening curly brace. Now delete its argument parsing code and the
declarations of all the variables it dumps the arguments into.
(Argument Clinic always generates its format strings Notice how the Python arguments are now arguments to this impl function;
with a ``:`` followed by the name of the function. If the if the implementation used different names for these variables, fix it.
existing code's format string ends with ``;``, to provide
usage help, this change is harmless—don't worry about it.) Let's reiterate, just because it's kind of weird.
Your code should now look like this::
Third, for parameters whose format units require two arguments
(like a length variable, or an encoding string, or a pointer static return_type
to a conversion function), ensure that the second argument is your_function_impl(...)
*exactly* the same between the two invocations. /*[clinic end generated code: input=..., output=...]*/
{
Fourth, inside the output portion of the block you'll find a preprocessor ...
macro defining the appropriate static :c:type:`PyMethodDef` structure for
this builtin:: Argument Clinic generated the checksum line and the function prototype just
above it. You should write the opening and closing curly braces for the
#define __PICKLE_PICKLER_DUMP_METHODDEF \ function, and the implementation inside.
{"dump", (PyCFunction)__pickle_Pickler_dump, METH_O, __pickle_Pickler_dump__doc__},
Sample::
This static structure should be *exactly* the same as the existing static
:c:type:`!PyMethodDef` structure for this builtin. /*[clinic input]
module _pickle
If any of these items differ in *any way*, class _pickle.Pickler "PicklerObject *" "&Pickler_Type"
adjust your Argument Clinic function specification and rerun [clinic start generated code]*/
``Tools/clinic/clinic.py`` until they *are* the same. /*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
/*[clinic input]
14. Notice that the last line of its output is the declaration _pickle.Pickler.dump
of your "impl" function. This is where the builtin's implementation goes.
Delete the existing prototype of the function you're modifying, but leave obj: 'O'
the opening curly brace. Now delete its argument parsing code and the The object to be pickled.
declarations of all the variables it dumps the arguments into. /
Notice how the Python arguments are now arguments to this impl function;
if the implementation used different names for these variables, fix it. Write a pickled representation of obj to the open file.
[clinic start generated code]*/
Let's reiterate, just because it's kind of weird. Your code should now
look like this:: PyDoc_STRVAR(__pickle_Pickler_dump__doc__,
"Write a pickled representation of obj to the open file.\n"
static return_type "\n"
your_function_impl(...) ...
/*[clinic end generated code: checksum=...]*/ static PyObject *
{ _pickle_Pickler_dump_impl(PicklerObject *self, PyObject *obj)
... /*[clinic end generated code: checksum=3bd30745bf206a48f8b576a1da3d90f55a0a4187]*/
{
Argument Clinic generated the checksum line and the function prototype just /* Check whether the Pickler was initialized correctly (issue3664).
above it. You should write the opening (and closing) curly braces for the Developers often forget to call __init__() in their subclasses, which
function, and the implementation inside. would trigger a segfault without this check. */
if (self->write == NULL) {
Sample:: PyErr_Format(PicklingError,
"Pickler.__init__() was not called by %s.__init__()",
/*[clinic input] Py_TYPE(self)->tp_name);
module _pickle return NULL;
class _pickle.Pickler "PicklerObject *" "&Pickler_Type" }
[clinic start generated code]*/
/*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ if (_Pickler_ClearBuffer(self) < 0) {
return NULL;
/*[clinic input] }
_pickle.Pickler.dump
...
obj: 'O'
The object to be pickled. Remember the macro with the :c:type:`PyMethodDef` structure for this function?
/ Find the existing :c:type:`!PyMethodDef` structure for this
function and replace it with a reference to the macro. If the builtin
Write a pickled representation of obj to the open file. is at module scope, this will probably be very near the end of the file;
[clinic start generated code]*/ if the builtin is a class method, this will probably be below but relatively
near to the implementation.
PyDoc_STRVAR(__pickle_Pickler_dump__doc__,
"Write a pickled representation of obj to the open file.\n" Note that the body of the macro contains a trailing comma; when you
"\n" replace the existing static :c:type:`!PyMethodDef` structure with the macro,
... *don't* add a comma to the end.
static PyObject *
_pickle_Pickler_dump_impl(PicklerObject *self, PyObject *obj) Sample::
/*[clinic end generated code: checksum=3bd30745bf206a48f8b576a1da3d90f55a0a4187]*/
{ static struct PyMethodDef Pickler_methods[] = {
/* Check whether the Pickler was initialized correctly (issue3664). __PICKLE_PICKLER_DUMP_METHODDEF
Developers often forget to call __init__() in their subclasses, which __PICKLE_PICKLER_CLEAR_MEMO_METHODDEF
would trigger a segfault without this check. */ {NULL, NULL} /* sentinel */
if (self->write == NULL) { };
PyErr_Format(PicklingError,
"Pickler.__init__() was not called by %s.__init__()", Argument Clinic may generate new instances of ``_Py_ID``. For example::
Py_TYPE(self)->tp_name);
return NULL; &_Py_ID(new_unique_py_id)
}
If it does, you'll have to run ``make regen-global-objects``
if (_Pickler_ClearBuffer(self) < 0) to regenerate the list of precompiled identifiers at this point.
return NULL;
Finally, compile, then run the relevant portions of the regression-test suite.
... This change should not introduce any new compile-time warnings or errors,
and there should be no externally visible change to Python's behavior,
15. Remember the macro with the :c:type:`PyMethodDef` structure for this except for one difference: :py:func:`inspect.signature` run on your function
function? Find the existing :c:type:`!PyMethodDef` structure for this should now provide a valid signature!
function and replace it with a reference to the macro. (If the builtin
is at module scope, this will probably be very near the end of the file; Congratulations, you've ported your first function to work with Argument Clinic!
if the builtin is a class method, this will probably be below but relatively
near to the implementation.)
Note that the body of the macro contains a trailing comma. So when you
replace the existing static :c:type:`!PyMethodDef` structure with the macro,
*don't* add a comma to the end.
Sample::
static struct PyMethodDef Pickler_methods[] = {
__PICKLE_PICKLER_DUMP_METHODDEF
__PICKLE_PICKLER_CLEAR_MEMO_METHODDEF
{NULL, NULL} /* sentinel */
};
16. Argument Clinic may generate new instances of ``_Py_ID``. For example::
&_Py_ID(new_unique_py_id)
If it does, you'll have to run ``make regen-global-objects``
to regenerate the list of precompiled identifiers at this point.
17. Compile, then run the relevant portions of the regression-test suite.
This change should not introduce any new compile-time warnings or errors,
and there should be no externally visible change to Python's behavior.
Well, except for one difference: :py:func:`inspect.signature` run on your function
should now provide a valid signature!
Congratulations, you've ported your first function to work with Argument Clinic!
.. _clinic-howtos: .. _clinic-howtos:
@ -913,6 +902,8 @@ you *must* not call :c:func:`PyBuffer_Release` on the provided buffer.
Argument Clinic generates code that does it for you (in the parsing function). Argument Clinic generates code that does it for you (in the parsing function).
.. _clinic-howto-advanced-converters:
How to use advanced converters How to use advanced converters
------------------------------ ------------------------------
@ -943,6 +934,7 @@ This restriction doesn't seem unreasonable; CPython itself always passes in stat
hard-coded encoding strings for parameters whose format units start with ``e``. hard-coded encoding strings for parameters whose format units start with ``e``.
.. _clinic-howto-default-values:
.. _default_values: .. _default_values:
How to assign default values to parameter How to assign default values to parameter
@ -1053,6 +1045,8 @@ you're not permitted to use:
* Tuple/list/set/dict literals. * Tuple/list/set/dict literals.
.. _clinic-howto-return-converters:
How to use return converters How to use return converters
---------------------------- ----------------------------
@ -1195,6 +1189,8 @@ variable to the C code::
/*[python checksum:...]*/ /*[python checksum:...]*/
.. _clinic-howto-self-converter:
How to use the "self converter" How to use the "self converter"
------------------------------- -------------------------------