diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2023-07-26 21:03:35 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-26 21:03:35 (GMT) |
commit | 6bbcd792f74148273bf14ab2bad87f190d80b076 (patch) | |
tree | 4adcacc0a9188058be4263c8344cdd656f80c3bd /Doc | |
parent | 4f6d7a5890760434015d9e90a6e81bf9e9b5c52f (diff) | |
download | cpython-6bbcd792f74148273bf14ab2bad87f190d80b076.zip cpython-6bbcd792f74148273bf14ab2bad87f190d80b076.tar.gz cpython-6bbcd792f74148273bf14ab2bad87f190d80b076.tar.bz2 |
[3.12] Docs: Remove the numbered steps from the Argument Clinic tutorial (GH-107203) (#107317)
Instead, order the tutorial as one body of prose, making it easier to
align the tutorial according to Diátaxis principles.
(cherry picked from commit 592395577c679543d899e68a3cff538b8b4df80d)
Co-authored-by: Erlend E. Aasland <erlend@python.org>
Diffstat (limited to 'Doc')
-rw-r--r-- | Doc/howto/clinic.rst | 624 |
1 files changed, 310 insertions, 314 deletions
diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst index 98d3632..ea3b453 100644 --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -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 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"). +using some of the :ref:`advanced concepts <clinic-howtos>` +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. -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 - of the CPython trunk. +Next, find a Python builtin that calls either :c:func:`PyArg_ParseTuple` +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` - or :c:func:`PyArg_ParseTupleAndKeywords`, and hasn't been converted - 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: +If the call to the :c:func:`!PyArg_Parse*` function uses any of the +following format units...: .. code-block:: none @@ -194,388 +194,377 @@ Let's dive in! et et# - or if it has multiple calls to :c:func:`PyArg_ParseTuple`, - you should choose a different function. Argument Clinic *does* - support all of these scenarios. But these are advanced - topics—let's do something simpler for your first function. - - Also, if the function has multiple calls to :c:func:`!PyArg_ParseTuple` - or :c:func:`PyArg_ParseTupleAndKeywords` where it supports different - types for the same argument, or if the function uses something besides - :c:func:`!PyArg_Parse*` functions to parse its arguments, it probably - isn't suitable for conversion to Argument Clinic. Argument Clinic - doesn't support generic functions or polymorphic parameters. - -3. Add the following boilerplate above the function, creating our block:: - - /*[clinic input] - [clinic start generated code]*/ - -4. Cut the docstring and paste it in between the ``[clinic]`` lines, - 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 - margin, with no line wider than 80 characters. - (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.) - - Sample:: +... or if it has multiple calls to :c:func:`PyArg_ParseTuple`, +you should choose a different function. +(See :ref:`clinic-howto-advanced-converters` for those scenarios.) - /*[clinic input] - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - -5. If your docstring doesn't have a "summary" line, Argument Clinic will - complain. So let's make sure it has one. The "summary" line should - 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 - code doesn't have to change for this step.) +Also, if the function has multiple calls to :c:func:`!PyArg_ParseTuple` +or :c:func:`PyArg_ParseTupleAndKeywords` where it supports different +types for the same argument, or if the function uses something besides +:c:func:`!PyArg_Parse*` functions to parse its arguments, it probably +isn't suitable for conversion to Argument Clinic. Argument Clinic +doesn't support generic functions or polymorphic parameters. -6. Above the docstring, enter the name of the function, followed - 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. - - Sample:: +Next, add the following boilerplate above the function, +creating our input block:: /*[clinic input] - _pickle.Pickler.dump - - Write a pickled representation of obj to the open file. [clinic start generated code]*/ -7. If this is the first time that module or class has been used with Argument - 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.) +Cut the docstring and paste it in between the ``[clinic]`` lines, +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 +margin, with no line wider than 80 characters. +Argument Clinic will preserve indents inside the docstring. - The name of the class and module should be the same as the one - seen by Python. Check the name defined in the :c:type:`PyModuleDef` - or :c:type:`PyTypeObject` as appropriate. +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. - When you declare a class, you must also specify two aspects of its type - in C: the type declaration you'd use for a pointer to an instance of - this class, and a pointer to the :c:type:`!PyTypeObject` for this class. +Example docstring summary line:: - Sample:: - - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ - - /*[clinic input] - _pickle.Pickler.dump - - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ - - - - -8. Declare each of the parameters to the function. Each parameter - 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: - - .. code-block:: none - - name_of_parameter: converter - - If the parameter has a default value, add that after the - converter: - - .. code-block:: none + /*[clinic input] + Write a pickled representation of obj to the open file. + [clinic start generated code]*/ - name_of_parameter: converter = default_value +If your docstring doesn't have a "summary" line, Argument Clinic will +complain, so let's make sure it has one. The "summary" line should +be a paragraph consisting of a single 80-column line +at the beginning of the docstring. +(See :pep:`257` regarding docstring conventions.) - Argument Clinic's support for "default values" is quite sophisticated; - please see :ref:`the section below on default values <default_values>` - for more information. +Our example docstring consists solely of a summary line, so the sample +code doesn't have to change for this step. - Add a blank line below the parameters. +Now, above the docstring, enter the name of the function, followed +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. - 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. +In our example, :mod:`!_pickle` is the module, :py:class:`!Pickler` is the class, +and :py:meth:`!dump` is the method, so the name becomes +:py:meth:`!_pickle.Pickler.dump`:: - For each parameter, copy the "format unit" for that - parameter from the :c:func:`PyArg_Parse` format argument and - 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`.) + /*[clinic input] + _pickle.Pickler.dump - For multicharacter format units like ``z#``, use the - entire two-or-three character string. + Write a pickled representation of obj to the open file. + [clinic start generated code]*/ - Sample:: +If this is the first time that module or class has been used with Argument +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. - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ +The name of the class and module should be the same as the one +seen by Python. Check the name defined in the :c:type:`PyModuleDef` +or :c:type:`PyTypeObject` as appropriate. - /*[clinic input] - _pickle.Pickler.dump +When you declare a class, you must also specify two aspects of its type +in C: the type declaration you'd use for a pointer to an instance of +this class, and a pointer to the :c:type:`!PyTypeObject` for this class:: - obj: 'O' + /*[clinic input] + module _pickle + class _pickle.Pickler "PicklerObject *" "&Pickler_Type" + [clinic start generated code]*/ - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ + /*[clinic input] + _pickle.Pickler.dump -9. If your function has ``|`` in the format 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. + Write a pickled representation of obj to the open file. + [clinic start generated code]*/ - 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. +Declare each of the parameters to the function. Each parameter +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: - (:py:meth:`!_pickle.Pickler.dump` has neither, so our sample is unchanged.) +.. code-block:: none + name_of_parameter: converter -10. If the existing C function calls :c:func:`PyArg_ParseTuple` - (as opposed to :c:func:`PyArg_ParseTupleAndKeywords`), then all its - arguments are positional-only. +If the parameter has a default value, add that after the +converter: - To mark all parameters as positional-only in Argument Clinic, - add a ``/`` on a line by itself after the last parameter, - indented the same as the parameter lines. +.. code-block:: none - Currently this is all-or-nothing; either all parameters are - positional-only, or none of them are. (In the future Argument - Clinic may relax this restriction.) + name_of_parameter: converter = default_value - Sample:: +Argument Clinic's support for "default values" is quite sophisticated; +see :ref:`clinic-howto-default-values` for more information. - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ +Next, add a blank line below the parameters. - /*[clinic input] - _pickle.Pickler.dump +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. - obj: 'O' - / +For each parameter, copy the "format unit" for that +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`. - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ +For multicharacter format units like ``z#``, +use the entire two-or-three character string. -11. It's helpful to write a per-parameter docstring for each parameter. - But per-parameter docstrings are optional; you can skip this step - if you prefer. +Sample:: - Here's how to add a per-parameter docstring. The first line - of the per-parameter docstring 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. + /*[clinic input] + module _pickle + class _pickle.Pickler "PicklerObject *" "&Pickler_Type" + [clinic start generated code]*/ - Sample:: + /*[clinic input] + _pickle.Pickler.dump - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ + obj: 'O' - /*[clinic input] - _pickle.Pickler.dump + Write a pickled representation of obj to the open file. + [clinic start generated code]*/ - obj: 'O' - The object to be pickled. - / +If your function has ``|`` in the format 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. - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ +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. -12. Save and close the file, then run ``Tools/clinic/clinic.py`` on - it. With luck everything worked---your block now has output, and - a :file:`.c.h` file has been generated! Reopen the file in your - text editor to see:: +:py:meth:`!_pickle.Pickler.dump` has neither, so our sample is unchanged. - /*[clinic input] - _pickle.Pickler.dump +Next, if the existing C function calls :c:func:`PyArg_ParseTuple` +(as opposed to :c:func:`PyArg_ParseTupleAndKeywords`), then all its +arguments are positional-only. - obj: 'O' - The object to be pickled. - / +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. - [clinic start generated code]*/ +Sample:: - static PyObject * - _pickle_Pickler_dump(PicklerObject *self, PyObject *obj) - /*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/ + /*[clinic input] + module _pickle + class _pickle.Pickler "PicklerObject *" "&Pickler_Type" + [clinic start generated code]*/ - Obviously, if Argument Clinic didn't produce any output, it's because - it found an error in your input. Keep fixing your errors and retrying - until Argument Clinic processes your file without complaint. + /*[clinic input] + _pickle.Pickler.dump - 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:: + obj: 'O' + / - #include "clinic/_pickle.c.h" + Write a pickled representation of obj to the open file. + [clinic start generated code]*/ -13. Double-check that the argument-parsing code Argument Clinic generated - looks basically the same as the existing code. +It can be helpful to write a per-parameter docstring for each parameter. +Since per-parameter docstrings are optional, +you can skip this step if you prefer. - First, ensure both places use the same argument-parsing function. - The existing code must call either - :c:func:`PyArg_ParseTuple` or :c:func:`PyArg_ParseTupleAndKeywords`; - ensure that the code generated by Argument Clinic calls the - *exact* same function. +Nevertheless, here's how to add a per-parameter docstring. +The first line of the per-parameter docstring +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. - 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, up to the colon - or semi-colon. +Sample:: - (Argument Clinic always generates its format strings - with a ``:`` followed by the name of the function. If the - existing code's format string ends with ``;``, to provide - usage help, this change is harmless—don't worry about it.) + /*[clinic input] + module _pickle + class _pickle.Pickler "PicklerObject *" "&Pickler_Type" + [clinic start generated code]*/ - Third, for parameters whose format units require two arguments - (like a length variable, or an encoding string, or a pointer - to a conversion function), ensure that the second argument is - *exactly* the same between the two invocations. + /*[clinic input] + _pickle.Pickler.dump - 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:: + obj: 'O' + The object to be pickled. + / - #define __PICKLE_PICKLER_DUMP_METHODDEF \ - {"dump", (PyCFunction)__pickle_Pickler_dump, METH_O, __pickle_Pickler_dump__doc__}, + Write a pickled representation of obj to the open file. + [clinic start generated code]*/ - This static structure should be *exactly* the same as the existing static - :c:type:`!PyMethodDef` structure for this builtin. +Save and close the file, then run ``Tools/clinic/clinic.py`` on it. +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:: - If any of these items differ in *any way*, - adjust your Argument Clinic function specification and rerun - ``Tools/clinic/clinic.py`` until they *are* the same. + /*[clinic input] + _pickle.Pickler.dump + obj: 'O' + The object to be pickled. + / -14. Notice that the last line of its output is the declaration - of your "impl" function. This is where the builtin's implementation goes. - Delete the existing prototype of the function you're modifying, but leave - the opening curly brace. Now delete its argument parsing code and the - 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:: + static PyObject * + _pickle_Pickler_dump(PicklerObject *self, PyObject *obj) + /*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/ - static return_type - your_function_impl(...) - /*[clinic end generated code: checksum=...]*/ - { - ... +Obviously, if Argument Clinic didn't produce any output, +it's because it found an error in your input. +Keep fixing your errors and retrying until Argument Clinic processes your file +without complaint. - Argument Clinic generated the checksum line and the function prototype just - above it. You should write the opening (and closing) curly braces for the - function, and the implementation inside. +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:: - Sample:: + #include "clinic/_pickle.c.h" - /*[clinic input] - module _pickle - class _pickle.Pickler "PicklerObject *" "&Pickler_Type" - [clinic start generated code]*/ - /*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ +Double-check that the argument-parsing code Argument Clinic generated +looks basically the same as the existing code. - /*[clinic input] - _pickle.Pickler.dump +First, ensure both places use the same argument-parsing function. +The existing code must call either +:c:func:`PyArg_ParseTuple` or :c:func:`PyArg_ParseTupleAndKeywords`; +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, +up to the colon or semi-colon. - Write a pickled representation of obj to the open file. - [clinic start generated code]*/ +Argument Clinic always generates its format strings +with a ``:`` followed by the name of the function. +If the existing code's format string ends with ``;``, +to provide usage help, this change is harmless --- don't worry about it. - PyDoc_STRVAR(__pickle_Pickler_dump__doc__, - "Write a pickled representation of obj to the open file.\n" - "\n" - ... - static PyObject * - _pickle_Pickler_dump_impl(PicklerObject *self, PyObject *obj) - /*[clinic end generated code: checksum=3bd30745bf206a48f8b576a1da3d90f55a0a4187]*/ - { - /* Check whether the Pickler was initialized correctly (issue3664). - Developers often forget to call __init__() in their subclasses, which - would trigger a segfault without this check. */ - if (self->write == NULL) { - PyErr_Format(PicklingError, - "Pickler.__init__() was not called by %s.__init__()", - Py_TYPE(self)->tp_name); - return NULL; - } +Third, for parameters whose format units require two arguments, +like a length variable, an encoding string, or a pointer +to a conversion function, ensure that the second argument is +*exactly* the same between the two invocations. - if (_Pickler_ClearBuffer(self) < 0) - return NULL; +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:: - ... + #define __PICKLE_PICKLER_DUMP_METHODDEF \ + {"dump", (PyCFunction)__pickle_Pickler_dump, METH_O, __pickle_Pickler_dump__doc__}, -15. 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 - is at module scope, this will probably be very near the end of the file; - if the builtin is a class method, this will probably be below but relatively - near to the implementation.) +This static structure should be *exactly* the same as the existing static +:c:type:`!PyMethodDef` structure for this builtin. - 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. +If any of these items differ in *any way*, +adjust your Argument Clinic function specification and rerun +``Tools/clinic/clinic.py`` until they *are* the same. - Sample:: +Notice that the last line of its output is the declaration +of your "impl" function. This is where the builtin's implementation goes. +Delete the existing prototype of the function you're modifying, but leave +the opening curly brace. Now delete its argument parsing code and the +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. - static struct PyMethodDef Pickler_methods[] = { - __PICKLE_PICKLER_DUMP_METHODDEF - __PICKLE_PICKLER_CLEAR_MEMO_METHODDEF - {NULL, NULL} /* sentinel */ - }; +Let's reiterate, just because it's kind of weird. +Your code should now look like this:: + static return_type + your_function_impl(...) + /*[clinic end generated code: input=..., output=...]*/ + { + ... -16. Argument Clinic may generate new instances of ``_Py_ID``. For example:: +Argument Clinic generated the checksum line and the function prototype just +above it. You should write the opening and closing curly braces for the +function, and the implementation inside. - &_Py_ID(new_unique_py_id) +Sample:: - If it does, you'll have to run ``make regen-global-objects`` - to regenerate the list of precompiled identifiers at this point. + /*[clinic input] + module _pickle + class _pickle.Pickler "PicklerObject *" "&Pickler_Type" + [clinic start generated code]*/ + /*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ + /*[clinic input] + _pickle.Pickler.dump -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. + obj: 'O' + The object to be pickled. + / - Well, except for one difference: :py:func:`inspect.signature` run on your function - should now provide a valid signature! + Write a pickled representation of obj to the open file. + [clinic start generated code]*/ - Congratulations, you've ported your first function to work with Argument Clinic! + PyDoc_STRVAR(__pickle_Pickler_dump__doc__, + "Write a pickled representation of obj to the open file.\n" + "\n" + ... + static PyObject * + _pickle_Pickler_dump_impl(PicklerObject *self, PyObject *obj) + /*[clinic end generated code: checksum=3bd30745bf206a48f8b576a1da3d90f55a0a4187]*/ + { + /* Check whether the Pickler was initialized correctly (issue3664). + Developers often forget to call __init__() in their subclasses, which + would trigger a segfault without this check. */ + if (self->write == NULL) { + PyErr_Format(PicklingError, + "Pickler.__init__() was not called by %s.__init__()", + Py_TYPE(self)->tp_name); + return NULL; + } + + if (_Pickler_ClearBuffer(self) < 0) { + return NULL; + } + + ... + +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 +is at module scope, this will probably be very near the end of the file; +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; 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 */ + }; + +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. + +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, +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: @@ -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). +.. _clinic-howto-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``. +.. _clinic-howto-default-values: .. _default_values: How to assign default values to parameter @@ -1053,6 +1045,8 @@ you're not permitted to use: * Tuple/list/set/dict literals. +.. _clinic-howto-return-converters: + How to use return converters ---------------------------- @@ -1195,6 +1189,8 @@ variable to the C code:: /*[python checksum:...]*/ +.. _clinic-howto-self-converter: + How to use the "self converter" ------------------------------- |