1806 lines
129 KiB
HTML
1806 lines
129 KiB
HTML
|
|
|||
|
<!DOCTYPE html>
|
|||
|
|
|||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|||
|
<head>
|
|||
|
<meta charset="utf-8" />
|
|||
|
<title>Argument Clinic How-To — Python 3.7.4 documentation</title>
|
|||
|
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
|||
|
|
|||
|
<script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/language_data.js"></script>
|
|||
|
|
|||
|
<script type="text/javascript" src="../_static/sidebar.js"></script>
|
|||
|
|
|||
|
<link rel="search" type="application/opensearchdescription+xml"
|
|||
|
title="Search within Python 3.7.4 documentation"
|
|||
|
href="../_static/opensearch.xml"/>
|
|||
|
<link rel="author" title="About these documents" href="../about.html" />
|
|||
|
<link rel="index" title="Index" href="../genindex.html" />
|
|||
|
<link rel="search" title="Search" href="../search.html" />
|
|||
|
<link rel="copyright" title="Copyright" href="../copyright.html" />
|
|||
|
<link rel="next" title="Instrumenting CPython with DTrace and SystemTap" href="instrumentation.html" />
|
|||
|
<link rel="prev" title="An introduction to the ipaddress module" href="ipaddress.html" />
|
|||
|
<link rel="shortcut icon" type="image/png" href="../_static/py.png" />
|
|||
|
<link rel="canonical" href="https://docs.python.org/3/howto/clinic.html" />
|
|||
|
|
|||
|
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/switchers.js"></script>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<style>
|
|||
|
@media only screen {
|
|||
|
table.full-width-table {
|
|||
|
width: 100%;
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|
|||
|
|
|||
|
|
|||
|
</head><body>
|
|||
|
|
|||
|
<div class="related" role="navigation" aria-label="related navigation">
|
|||
|
<h3>Navigation</h3>
|
|||
|
<ul>
|
|||
|
<li class="right" style="margin-right: 10px">
|
|||
|
<a href="../genindex.html" title="General Index"
|
|||
|
accesskey="I">index</a></li>
|
|||
|
<li class="right" >
|
|||
|
<a href="../py-modindex.html" title="Python Module Index"
|
|||
|
>modules</a> |</li>
|
|||
|
<li class="right" >
|
|||
|
<a href="instrumentation.html" title="Instrumenting CPython with DTrace and SystemTap"
|
|||
|
accesskey="N">next</a> |</li>
|
|||
|
<li class="right" >
|
|||
|
<a href="ipaddress.html" title="An introduction to the ipaddress module"
|
|||
|
accesskey="P">previous</a> |</li>
|
|||
|
<li><img src="../_static/py.png" alt=""
|
|||
|
style="vertical-align: middle; margin-top: -1px"/></li>
|
|||
|
<li><a href="https://www.python.org/">Python</a> »</li>
|
|||
|
<li>
|
|||
|
<span class="language_switcher_placeholder">en</span>
|
|||
|
<span class="version_switcher_placeholder">3.7.4</span>
|
|||
|
<a href="../index.html">Documentation </a> »
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
|||
|
<li class="right">
|
|||
|
|
|||
|
|
|||
|
<div class="inline-search" style="display: none" role="search">
|
|||
|
<form class="inline-search" action="../search.html" method="get">
|
|||
|
<input placeholder="Quick search" type="text" name="q" />
|
|||
|
<input type="submit" value="Go" />
|
|||
|
<input type="hidden" name="check_keywords" value="yes" />
|
|||
|
<input type="hidden" name="area" value="default" />
|
|||
|
</form>
|
|||
|
</div>
|
|||
|
<script type="text/javascript">$('.inline-search').show(0);</script>
|
|||
|
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="document">
|
|||
|
<div class="documentwrapper">
|
|||
|
<div class="bodywrapper">
|
|||
|
<div class="body" role="main">
|
|||
|
|
|||
|
<div class="section" id="argument-clinic-how-to">
|
|||
|
<h1>Argument Clinic How-To<a class="headerlink" href="#argument-clinic-how-to" title="Permalink to this headline">¶</a></h1>
|
|||
|
<dl class="field-list simple">
|
|||
|
<dt class="field-odd">author</dt>
|
|||
|
<dd class="field-odd"><p>Larry Hastings</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
<div class="topic">
|
|||
|
<p class="topic-title first">Abstract</p>
|
|||
|
<p>Argument Clinic is a preprocessor for CPython C files.
|
|||
|
Its purpose is to automate all the boilerplate involved
|
|||
|
with writing argument parsing code for “builtins”.
|
|||
|
This document shows you how to convert your first C
|
|||
|
function to work with Argument Clinic, and then introduces
|
|||
|
some advanced topics on Argument Clinic usage.</p>
|
|||
|
<p>Currently Argument Clinic is considered internal-only
|
|||
|
for CPython. Its use is not supported for files outside
|
|||
|
CPython, and no guarantees are made regarding backwards
|
|||
|
compatibility for future versions. In other words: if you
|
|||
|
maintain an external C extension for CPython, you’re welcome
|
|||
|
to experiment with Argument Clinic in your own code. But the
|
|||
|
version of Argument Clinic that ships with the next version
|
|||
|
of CPython <em>could</em> be totally incompatible and break all your code.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="the-goals-of-argument-clinic">
|
|||
|
<h2>The Goals Of Argument Clinic<a class="headerlink" href="#the-goals-of-argument-clinic" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>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 <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*args</span></code> (and maybe <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*kwargs</span></code>)
|
|||
|
magically converted into the C variables and types you need.</p>
|
|||
|
<p>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.</p>
|
|||
|
<p>Obviously, no one would want to use Argument Clinic unless
|
|||
|
it’s solving their problem—and without creating new problems of
|
|||
|
its own.
|
|||
|
So it’s paramount that Argument Clinic generate correct code.
|
|||
|
It’d be nice if the code was faster, too, but at the very least
|
|||
|
it should not introduce a major speed regression. (Eventually Argument
|
|||
|
Clinic <em>should</em> make a major speedup possible—we could
|
|||
|
rewrite its code generator to produce tailor-made argument
|
|||
|
parsing code, rather than calling the general-purpose CPython
|
|||
|
argument parsing library. That would make for the fastest
|
|||
|
argument parsing possible!)</p>
|
|||
|
<p>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.</p>
|
|||
|
<p>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!</p>
|
|||
|
<p>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.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="basic-concepts-and-usage">
|
|||
|
<h2>Basic Concepts And Usage<a class="headerlink" href="#basic-concepts-and-usage" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Argument Clinic ships with CPython; you’ll find it in <code class="docutils literal notranslate"><span class="pre">Tools/clinic/clinic.py</span></code>.
|
|||
|
If you run that script, specifying a C file as an argument:</p>
|
|||
|
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$</span> python3 Tools/clinic/clinic.py foo.c
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Argument Clinic will scan over the file looking for lines that
|
|||
|
look exactly like this:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>/*[clinic input]
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>When it finds one, it reads everything up to a line that looks
|
|||
|
exactly like this:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>[clinic start generated code]*/
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Everything in between these two lines is input for Argument Clinic.
|
|||
|
All of these lines, including the beginning and ending comment
|
|||
|
lines, are collectively called an Argument Clinic “block”.</p>
|
|||
|
<p>When Argument Clinic parses one of these blocks, it
|
|||
|
generates output. This output is rewritten into the C file
|
|||
|
immediately after the block, followed by a comment containing a checksum.
|
|||
|
The Argument Clinic block now looks like this:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>/*[clinic input]
|
|||
|
... clinic input goes here ...
|
|||
|
[clinic start generated code]*/
|
|||
|
... clinic output goes here ...
|
|||
|
/*[clinic end generated code: checksum=...]*/
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>If you run Argument Clinic on the same file a second time, Argument Clinic
|
|||
|
will discard the old output and write out the new output with a fresh checksum
|
|||
|
line. However, if the input hasn’t changed, the output won’t change either.</p>
|
|||
|
<p>You should never modify the output portion of an Argument Clinic block. Instead,
|
|||
|
change the input until it produces the output you want. (That’s the purpose of the
|
|||
|
checksum—to detect if someone changed the output, as these edits would be lost
|
|||
|
the next time Argument Clinic writes out fresh output.)</p>
|
|||
|
<p>For the sake of clarity, here’s the terminology we’ll use with Argument Clinic:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li><p>The first line of the comment (<code class="docutils literal notranslate"><span class="pre">/*[clinic</span> <span class="pre">input]</span></code>) is the <em>start line</em>.</p></li>
|
|||
|
<li><p>The last line of the initial comment (<code class="docutils literal notranslate"><span class="pre">[clinic</span> <span class="pre">start</span> <span class="pre">generated</span> <span class="pre">code]*/</span></code>) is the <em>end line</em>.</p></li>
|
|||
|
<li><p>The last line (<code class="docutils literal notranslate"><span class="pre">/*[clinic</span> <span class="pre">end</span> <span class="pre">generated</span> <span class="pre">code:</span> <span class="pre">checksum=...]*/</span></code>) is the <em>checksum line</em>.</p></li>
|
|||
|
<li><p>In between the start line and the end line is the <em>input</em>.</p></li>
|
|||
|
<li><p>In between the end line and the checksum line is the <em>output</em>.</p></li>
|
|||
|
<li><p>All the text collectively, from the start line to the checksum line inclusively,
|
|||
|
is the <em>block</em>. (A block that hasn’t been successfully processed by Argument
|
|||
|
Clinic yet doesn’t have output or a checksum line, but it’s still considered
|
|||
|
a block.)</p></li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<div class="section" id="converting-your-first-function">
|
|||
|
<h2>Converting Your First Function<a class="headerlink" href="#converting-your-first-function" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>The best way to get a sense of how Argument Clinic works is to
|
|||
|
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.</p>
|
|||
|
<p>Let’s dive in!</p>
|
|||
|
<ol class="arabic" start="0">
|
|||
|
<li><p>Make sure you’re working with a freshly updated checkout
|
|||
|
of the CPython trunk.</p></li>
|
|||
|
<li><p>Find a Python builtin that calls either <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a>
|
|||
|
or <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTupleAndKeywords" title="PyArg_ParseTupleAndKeywords"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code></a>, and hasn’t been converted
|
|||
|
to work with Argument Clinic yet.
|
|||
|
For my example I’m using <code class="docutils literal notranslate"><span class="pre">_pickle.Pickler.dump()</span></code>.</p></li>
|
|||
|
<li><p>If the call to the <code class="docutils literal notranslate"><span class="pre">PyArg_Parse</span></code> function uses any of the
|
|||
|
following format units:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>O&
|
|||
|
O!
|
|||
|
es
|
|||
|
es#
|
|||
|
et
|
|||
|
et#
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>or if it has multiple calls to <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a>,
|
|||
|
you should choose a different function. Argument Clinic <em>does</em>
|
|||
|
support all of these scenarios. But these are advanced
|
|||
|
topics—let’s do something simpler for your first function.</p>
|
|||
|
<p>Also, if the function has multiple calls to <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a>
|
|||
|
or <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTupleAndKeywords" title="PyArg_ParseTupleAndKeywords"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code></a> where it supports different
|
|||
|
types for the same argument, or if the function uses something besides
|
|||
|
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.</p>
|
|||
|
</li>
|
|||
|
<li><p>Add the following boilerplate above the function, creating our block:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><p>Cut the docstring and paste it in between the <code class="docutils literal notranslate"><span class="pre">[clinic]</span></code> 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.)</p>
|
|||
|
<p>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 <code class="docutils literal notranslate"><span class="pre">help()</span></code> on your builtin in the future,
|
|||
|
the first line will be built automatically based on the function’s
|
|||
|
signature.)</p>
|
|||
|
<p>Sample:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">Write a pickled representation of obj to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><p>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.</p>
|
|||
|
<p>(Our example docstring consists solely of a summary line, so the sample
|
|||
|
code doesn’t have to change for this step.)</p>
|
|||
|
</li>
|
|||
|
<li><p>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.</p>
|
|||
|
<p>Sample:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">_pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm">Write a pickled representation of obj to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><p>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.)</p>
|
|||
|
<p>The name of the class and module should be the same as the one
|
|||
|
seen by Python. Check the name defined in the <a class="reference internal" href="../c-api/module.html#c.PyModuleDef" title="PyModuleDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyModuleDef</span></code></a>
|
|||
|
or <a class="reference internal" href="../c-api/type.html#c.PyTypeObject" title="PyTypeObject"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyTypeObject</span></code></a> as appropriate.</p>
|
|||
|
<p>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 <a class="reference internal" href="../c-api/type.html#c.PyTypeObject" title="PyTypeObject"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyTypeObject</span></code></a> for this class.</p>
|
|||
|
<p>Sample:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">module _pickle</span>
|
|||
|
<span class="cm">class _pickle.Pickler "PicklerObject *" "&Pickler_Type"</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
|
|||
|
<span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">_pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm">Write a pickled representation of obj to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><p>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.</p>
|
|||
|
<p>The general form of these parameter lines is as follows:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>name_of_parameter: converter
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>If the parameter has a default value, add that after the
|
|||
|
converter:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>name_of_parameter: converter = default_value
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Argument Clinic’s support for “default values” is quite sophisticated;
|
|||
|
please see <a class="reference internal" href="#default-values"><span class="std std-ref">the section below on default values</span></a>
|
|||
|
for more information.</p>
|
|||
|
<p>Add a blank line below the parameters.</p>
|
|||
|
<p>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.</p>
|
|||
|
<p>For each parameter, copy the “format unit” for that
|
|||
|
parameter from the <code class="docutils literal notranslate"><span class="pre">PyArg_Parse()</span></code> format argument and
|
|||
|
specify <em>that</em> as its converter, as a quoted
|
|||
|
string. (“format unit” is the formal name for the one-to-three
|
|||
|
character substring of the <code class="docutils literal notranslate"><span class="pre">format</span></code> 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 <a class="reference internal" href="../c-api/arg.html#arg-parsing"><span class="std std-ref">Parsing arguments and building values</span></a>.)</p>
|
|||
|
<p>For multicharacter format units like <code class="docutils literal notranslate"><span class="pre">z#</span></code>, use the
|
|||
|
entire two-or-three character string.</p>
|
|||
|
<p>Sample:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span> <span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm"> module _pickle</span>
|
|||
|
<span class="cm"> class _pickle.Pickler "PicklerObject *" "&Pickler_Type"</span>
|
|||
|
<span class="cm"> [clinic start generated code]*/</span>
|
|||
|
|
|||
|
<span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm"> _pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm"> obj: 'O'</span>
|
|||
|
|
|||
|
<span class="cm">Write a pickled representation of obj to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><p>If your function has <code class="docutils literal notranslate"><span class="pre">|</span></code> 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.</p>
|
|||
|
<p>If your function has <code class="docutils literal notranslate"><span class="pre">$</span></code> in the format string, meaning it
|
|||
|
takes keyword-only arguments, specify <code class="docutils literal notranslate"><span class="pre">*</span></code> on a line by
|
|||
|
itself before the first keyword-only argument, indented the
|
|||
|
same as the parameter lines.</p>
|
|||
|
<p>(<code class="docutils literal notranslate"><span class="pre">_pickle.Pickler.dump</span></code> has neither, so our sample is unchanged.)</p>
|
|||
|
</li>
|
|||
|
<li><p>If the existing C function calls <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a>
|
|||
|
(as opposed to <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTupleAndKeywords" title="PyArg_ParseTupleAndKeywords"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code></a>), then all its
|
|||
|
arguments are positional-only.</p>
|
|||
|
<p>To mark all parameters as positional-only in Argument Clinic,
|
|||
|
add a <code class="docutils literal notranslate"><span class="pre">/</span></code> on a line by itself after the last parameter,
|
|||
|
indented the same as the parameter lines.</p>
|
|||
|
<p>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.)</p>
|
|||
|
<p>Sample:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">module _pickle</span>
|
|||
|
<span class="cm">class _pickle.Pickler "PicklerObject *" "&Pickler_Type"</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
|
|||
|
<span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">_pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm"> obj: 'O'</span>
|
|||
|
<span class="cm"> /</span>
|
|||
|
|
|||
|
<span class="cm">Write a pickled representation of obj to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><p>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.</p>
|
|||
|
<p>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.</p>
|
|||
|
<p>Sample:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">module _pickle</span>
|
|||
|
<span class="cm">class _pickle.Pickler "PicklerObject *" "&Pickler_Type"</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
|
|||
|
<span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">_pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm"> obj: 'O'</span>
|
|||
|
<span class="cm"> The object to be pickled.</span>
|
|||
|
<span class="cm"> /</span>
|
|||
|
|
|||
|
<span class="cm">Write a pickled representation of obj to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><p>Save and close the file, then run <code class="docutils literal notranslate"><span class="pre">Tools/clinic/clinic.py</span></code> on
|
|||
|
it. With luck everything worked—your block now has output, and
|
|||
|
a <code class="docutils literal notranslate"><span class="pre">.c.h</span></code> file has been generated! Reopen the file in your
|
|||
|
text editor to see:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">_pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm"> obj: 'O'</span>
|
|||
|
<span class="cm"> The object to be pickled.</span>
|
|||
|
<span class="cm"> /</span>
|
|||
|
|
|||
|
<span class="cm">Write a pickled representation of obj to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
|
|||
|
<span class="k">static</span> <span class="n">PyObject</span> <span class="o">*</span>
|
|||
|
<span class="n">_pickle_Pickler_dump</span><span class="p">(</span><span class="n">PicklerObject</span> <span class="o">*</span><span class="n">self</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">obj</span><span class="p">)</span>
|
|||
|
<span class="cm">/*[clinic end generated code: output=87ecad1261e02ac7 input=552eb1c0f52260d9]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>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.</p>
|
|||
|
<p>For readability, most of the glue code has been generated to a <code class="docutils literal notranslate"><span class="pre">.c.h</span></code>
|
|||
|
file. You’ll need to include that in your original <code class="docutils literal notranslate"><span class="pre">.c</span></code> file,
|
|||
|
typically right after the clinic module block:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">"clinic/_pickle.c.h"</span><span class="cp"></span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><p>Double-check that the argument-parsing code Argument Clinic generated
|
|||
|
looks basically the same as the existing code.</p>
|
|||
|
<p>First, ensure both places use the same argument-parsing function.
|
|||
|
The existing code must call either
|
|||
|
<a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a> or <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTupleAndKeywords" title="PyArg_ParseTupleAndKeywords"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code></a>;
|
|||
|
ensure that the code generated by Argument Clinic calls the
|
|||
|
<em>exact</em> same function.</p>
|
|||
|
<p>Second, the format string passed in to <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a> or
|
|||
|
<a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTupleAndKeywords" title="PyArg_ParseTupleAndKeywords"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code></a> should be <em>exactly</em> the same
|
|||
|
as the hand-written one in the existing function, up to the colon
|
|||
|
or semi-colon.</p>
|
|||
|
<p>(Argument Clinic always generates its format strings
|
|||
|
with a <code class="docutils literal notranslate"><span class="pre">:</span></code> followed by the name of the function. If the
|
|||
|
existing code’s format string ends with <code class="docutils literal notranslate"><span class="pre">;</span></code>, to provide
|
|||
|
usage help, this change is harmless—don’t worry about it.)</p>
|
|||
|
<p>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
|
|||
|
<em>exactly</em> the same between the two invocations.</p>
|
|||
|
<p>Fourth, inside the output portion of the block you’ll find a preprocessor
|
|||
|
macro defining the appropriate static <a class="reference internal" href="../c-api/structures.html#c.PyMethodDef" title="PyMethodDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code></a> structure for
|
|||
|
this builtin:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#define __PICKLE_PICKLER_DUMP_METHODDEF \</span>
|
|||
|
<span class="cp">{"dump", (PyCFunction)__pickle_Pickler_dump, METH_O, __pickle_Pickler_dump__doc__},</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This static structure should be <em>exactly</em> the same as the existing static
|
|||
|
<a class="reference internal" href="../c-api/structures.html#c.PyMethodDef" title="PyMethodDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code></a> structure for this builtin.</p>
|
|||
|
<p>If any of these items differ in <em>any way</em>,
|
|||
|
adjust your Argument Clinic function specification and rerun
|
|||
|
<code class="docutils literal notranslate"><span class="pre">Tools/clinic/clinic.py</span></code> until they <em>are</em> the same.</p>
|
|||
|
</li>
|
|||
|
<li><p>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.</p>
|
|||
|
<p>Let’s reiterate, just because it’s kind of weird. Your code should now
|
|||
|
look like this:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span> <span class="n">return_type</span>
|
|||
|
<span class="nf">your_function_impl</span><span class="p">(...)</span>
|
|||
|
<span class="cm">/*[clinic end generated code: checksum=...]*/</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="p">...</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>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.</p>
|
|||
|
<p>Sample:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">module _pickle</span>
|
|||
|
<span class="cm">class _pickle.Pickler "PicklerObject *" "&Pickler_Type"</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
<span class="cm">/*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/</span>
|
|||
|
|
|||
|
<span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">_pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm"> obj: 'O'</span>
|
|||
|
<span class="cm"> The object to be pickled.</span>
|
|||
|
<span class="cm"> /</span>
|
|||
|
|
|||
|
<span class="cm">Write a pickled representation of obj to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
|
|||
|
<span class="n">PyDoc_STRVAR</span><span class="p">(</span><span class="n">__pickle_Pickler_dump__doc__</span><span class="p">,</span>
|
|||
|
<span class="s">"Write a pickled representation of obj to the open file.</span><span class="se">\n</span><span class="s">"</span>
|
|||
|
<span class="s">"</span><span class="se">\n</span><span class="s">"</span>
|
|||
|
<span class="p">...</span>
|
|||
|
<span class="k">static</span> <span class="n">PyObject</span> <span class="o">*</span>
|
|||
|
<span class="n">_pickle_Pickler_dump_impl</span><span class="p">(</span><span class="n">PicklerObject</span> <span class="o">*</span><span class="n">self</span><span class="p">,</span> <span class="n">PyObject</span> <span class="o">*</span><span class="n">obj</span><span class="p">)</span>
|
|||
|
<span class="cm">/*[clinic end generated code: checksum=3bd30745bf206a48f8b576a1da3d90f55a0a4187]*/</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="cm">/* Check whether the Pickler was initialized correctly (issue3664).</span>
|
|||
|
<span class="cm"> Developers often forget to call __init__() in their subclasses, which</span>
|
|||
|
<span class="cm"> would trigger a segfault without this check. */</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="n">self</span><span class="o">-></span><span class="n">write</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
<span class="n">PyErr_Format</span><span class="p">(</span><span class="n">PicklingError</span><span class="p">,</span>
|
|||
|
<span class="s">"Pickler.__init__() was not called by %s.__init__()"</span><span class="p">,</span>
|
|||
|
<span class="n">Py_TYPE</span><span class="p">(</span><span class="n">self</span><span class="p">)</span><span class="o">-></span><span class="n">tp_name</span><span class="p">);</span>
|
|||
|
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="n">_Pickler_ClearBuffer</span><span class="p">(</span><span class="n">self</span><span class="p">)</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span>
|
|||
|
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="p">...</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><p>Remember the macro with the <a class="reference internal" href="../c-api/structures.html#c.PyMethodDef" title="PyMethodDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code></a> structure for this
|
|||
|
function? Find the existing <a class="reference internal" href="../c-api/structures.html#c.PyMethodDef" title="PyMethodDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code></a> 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.)</p>
|
|||
|
<p>Note that the body of the macro contains a trailing comma. So when you
|
|||
|
replace the existing static <a class="reference internal" href="../c-api/structures.html#c.PyMethodDef" title="PyMethodDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code></a> structure with the macro,
|
|||
|
<em>don’t</em> add a comma to the end.</p>
|
|||
|
<p>Sample:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span> <span class="k">struct</span> <span class="n">PyMethodDef</span> <span class="n">Pickler_methods</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
|
|||
|
<span class="n">__PICKLE_PICKLER_DUMP_METHODDEF</span>
|
|||
|
<span class="n">__PICKLE_PICKLER_CLEAR_MEMO_METHODDEF</span>
|
|||
|
<span class="p">{</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">}</span> <span class="cm">/* sentinel */</span>
|
|||
|
<span class="p">};</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><p>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.</p>
|
|||
|
<p>Well, except for one difference: <code class="docutils literal notranslate"><span class="pre">inspect.signature()</span></code> run on your function
|
|||
|
should now provide a valid signature!</p>
|
|||
|
<p>Congratulations, you’ve ported your first function to work with Argument Clinic!</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</div>
|
|||
|
<div class="section" id="advanced-topics">
|
|||
|
<h2>Advanced Topics<a class="headerlink" href="#advanced-topics" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Now that you’ve had some experience working with Argument Clinic, it’s time
|
|||
|
for some advanced topics.</p>
|
|||
|
<div class="section" id="symbolic-default-values">
|
|||
|
<h3>Symbolic default values<a class="headerlink" href="#symbolic-default-values" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>The default value you provide for a parameter can’t be any arbitrary
|
|||
|
expression. Currently the following are explicitly supported:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li><p>Numeric constants (integer and float)</p></li>
|
|||
|
<li><p>String constants</p></li>
|
|||
|
<li><p><code class="docutils literal notranslate"><span class="pre">True</span></code>, <code class="docutils literal notranslate"><span class="pre">False</span></code>, and <code class="docutils literal notranslate"><span class="pre">None</span></code></p></li>
|
|||
|
<li><p>Simple symbolic constants like <code class="docutils literal notranslate"><span class="pre">sys.maxsize</span></code>, which must
|
|||
|
start with the name of the module</p></li>
|
|||
|
</ul>
|
|||
|
<p>In case you’re curious, this is implemented in <code class="docutils literal notranslate"><span class="pre">from_builtin()</span></code>
|
|||
|
in <code class="docutils literal notranslate"><span class="pre">Lib/inspect.py</span></code>.</p>
|
|||
|
<p>(In the future, this may need to get even more elaborate,
|
|||
|
to allow full expressions like <code class="docutils literal notranslate"><span class="pre">CONSTANT</span> <span class="pre">-</span> <span class="pre">1</span></code>.)</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="renaming-the-c-functions-and-variables-generated-by-argument-clinic">
|
|||
|
<h3>Renaming the C functions and variables generated by Argument Clinic<a class="headerlink" href="#renaming-the-c-functions-and-variables-generated-by-argument-clinic" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Argument Clinic automatically names the functions it generates for you.
|
|||
|
Occasionally this may cause a problem, if the generated name collides with
|
|||
|
the name of an existing C function. There’s an easy solution: override the names
|
|||
|
used for the C functions. Just add the keyword <code class="docutils literal notranslate"><span class="pre">"as"</span></code>
|
|||
|
to your function declaration line, followed by the function name you wish to use.
|
|||
|
Argument Clinic will use that function name for the base (generated) function,
|
|||
|
then add <code class="docutils literal notranslate"><span class="pre">"_impl"</span></code> to the end and use that for the name of the impl function.</p>
|
|||
|
<p>For example, if we wanted to rename the C function names generated for
|
|||
|
<code class="docutils literal notranslate"><span class="pre">pickle.Pickler.dump</span></code>, it’d look like this:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">pickle.Pickler.dump as pickler_dumper</span>
|
|||
|
|
|||
|
<span class="cm">...</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The base function would now be named <code class="docutils literal notranslate"><span class="pre">pickler_dumper()</span></code>,
|
|||
|
and the impl function would now be named <code class="docutils literal notranslate"><span class="pre">pickler_dumper_impl()</span></code>.</p>
|
|||
|
<p>Similarly, you may have a problem where you want to give a parameter
|
|||
|
a specific Python name, but that name may be inconvenient in C. Argument
|
|||
|
Clinic allows you to give a parameter different names in Python and in C,
|
|||
|
using the same <code class="docutils literal notranslate"><span class="pre">"as"</span></code> syntax:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm"> obj: object</span>
|
|||
|
<span class="cm"> file as file_obj: object</span>
|
|||
|
<span class="cm"> protocol: object = NULL</span>
|
|||
|
<span class="cm"> *</span>
|
|||
|
<span class="cm"> fix_imports: bool = True</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Here, the name used in Python (in the signature and the <code class="docutils literal notranslate"><span class="pre">keywords</span></code>
|
|||
|
array) would be <code class="docutils literal notranslate"><span class="pre">file</span></code>, but the C variable would be named <code class="docutils literal notranslate"><span class="pre">file_obj</span></code>.</p>
|
|||
|
<p>You can use this to rename the <code class="docutils literal notranslate"><span class="pre">self</span></code> parameter too!</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="converting-functions-using-pyarg-unpacktuple">
|
|||
|
<h3>Converting functions using PyArg_UnpackTuple<a class="headerlink" href="#converting-functions-using-pyarg-unpacktuple" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>To convert a function parsing its arguments with <a class="reference internal" href="../c-api/arg.html#c.PyArg_UnpackTuple" title="PyArg_UnpackTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_UnpackTuple()</span></code></a>,
|
|||
|
simply write out all the arguments, specifying each as an <code class="docutils literal notranslate"><span class="pre">object</span></code>. You
|
|||
|
may specify the <code class="docutils literal notranslate"><span class="pre">type</span></code> argument to cast the type as appropriate. All
|
|||
|
arguments should be marked positional-only (add a <code class="docutils literal notranslate"><span class="pre">/</span></code> on a line by itself
|
|||
|
after the last argument).</p>
|
|||
|
<p>Currently the generated code will use <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a>, but this
|
|||
|
will change soon.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="optional-groups">
|
|||
|
<h3>Optional Groups<a class="headerlink" href="#optional-groups" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Some legacy functions have a tricky approach to parsing their arguments:
|
|||
|
they count the number of positional arguments, then use a <code class="docutils literal notranslate"><span class="pre">switch</span></code> statement
|
|||
|
to call one of several different <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a> calls depending on
|
|||
|
how many positional arguments there are. (These functions cannot accept
|
|||
|
keyword-only arguments.) This approach was used to simulate optional
|
|||
|
arguments back before <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTupleAndKeywords" title="PyArg_ParseTupleAndKeywords"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code></a> was created.</p>
|
|||
|
<p>While functions using this approach can often be converted to
|
|||
|
use <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTupleAndKeywords" title="PyArg_ParseTupleAndKeywords"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code></a>, optional arguments, and default values,
|
|||
|
it’s not always possible. Some of these legacy functions have
|
|||
|
behaviors <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTupleAndKeywords" title="PyArg_ParseTupleAndKeywords"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code></a> doesn’t directly support.
|
|||
|
The most obvious example is the builtin function <code class="docutils literal notranslate"><span class="pre">range()</span></code>, which has
|
|||
|
an optional argument on the <em>left</em> side of its required argument!
|
|||
|
Another example is <code class="docutils literal notranslate"><span class="pre">curses.window.addch()</span></code>, which has a group of two
|
|||
|
arguments that must always be specified together. (The arguments are
|
|||
|
called <code class="docutils literal notranslate"><span class="pre">x</span></code> and <code class="docutils literal notranslate"><span class="pre">y</span></code>; if you call the function passing in <code class="docutils literal notranslate"><span class="pre">x</span></code>,
|
|||
|
you must also pass in <code class="docutils literal notranslate"><span class="pre">y</span></code>—and if you don’t pass in <code class="docutils literal notranslate"><span class="pre">x</span></code> you may not
|
|||
|
pass in <code class="docutils literal notranslate"><span class="pre">y</span></code> either.)</p>
|
|||
|
<p>In any case, the goal of Argument Clinic is to support argument parsing
|
|||
|
for all existing CPython builtins without changing their semantics.
|
|||
|
Therefore Argument Clinic supports
|
|||
|
this alternate approach to parsing, using what are called <em>optional groups</em>.
|
|||
|
Optional groups are groups of arguments that must all be passed in together.
|
|||
|
They can be to the left or the right of the required arguments. They
|
|||
|
can <em>only</em> be used with positional-only parameters.</p>
|
|||
|
<div class="admonition note">
|
|||
|
<p class="admonition-title">Note</p>
|
|||
|
<p>Optional groups are <em>only</em> intended for use when converting
|
|||
|
functions that make multiple calls to <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a>!
|
|||
|
Functions that use <em>any</em> other approach for parsing arguments
|
|||
|
should <em>almost never</em> be converted to Argument Clinic using
|
|||
|
optional groups. Functions using optional groups currently
|
|||
|
cannot have accurate signatures in Python, because Python just
|
|||
|
doesn’t understand the concept. Please avoid using optional
|
|||
|
groups wherever possible.</p>
|
|||
|
</div>
|
|||
|
<p>To specify an optional group, add a <code class="docutils literal notranslate"><span class="pre">[</span></code> on a line by itself before
|
|||
|
the parameters you wish to group together, and a <code class="docutils literal notranslate"><span class="pre">]</span></code> on a line by itself
|
|||
|
after these parameters. As an example, here’s how <code class="docutils literal notranslate"><span class="pre">curses.window.addch</span></code>
|
|||
|
uses optional groups to make the first two parameters and the last
|
|||
|
parameter optional:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
|
|||
|
<span class="cm">curses.window.addch</span>
|
|||
|
|
|||
|
<span class="cm"> [</span>
|
|||
|
<span class="cm"> x: int</span>
|
|||
|
<span class="cm"> X-coordinate.</span>
|
|||
|
<span class="cm"> y: int</span>
|
|||
|
<span class="cm"> Y-coordinate.</span>
|
|||
|
<span class="cm"> ]</span>
|
|||
|
|
|||
|
<span class="cm"> ch: object</span>
|
|||
|
<span class="cm"> Character to add.</span>
|
|||
|
|
|||
|
<span class="cm"> [</span>
|
|||
|
<span class="cm"> attr: long</span>
|
|||
|
<span class="cm"> Attributes for the character.</span>
|
|||
|
<span class="cm"> ]</span>
|
|||
|
<span class="cm"> /</span>
|
|||
|
|
|||
|
<span class="cm">...</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Notes:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li><p>For every optional group, one additional parameter will be passed into the
|
|||
|
impl function representing the group. The parameter will be an int named
|
|||
|
<code class="docutils literal notranslate"><span class="pre">group_{direction}_{number}</span></code>,
|
|||
|
where <code class="docutils literal notranslate"><span class="pre">{direction}</span></code> is either <code class="docutils literal notranslate"><span class="pre">right</span></code> or <code class="docutils literal notranslate"><span class="pre">left</span></code> depending on whether the group
|
|||
|
is before or after the required parameters, and <code class="docutils literal notranslate"><span class="pre">{number}</span></code> is a monotonically
|
|||
|
increasing number (starting at 1) indicating how far away the group is from
|
|||
|
the required parameters. When the impl is called, this parameter will be set
|
|||
|
to zero if this group was unused, and set to non-zero if this group was used.
|
|||
|
(By used or unused, I mean whether or not the parameters received arguments
|
|||
|
in this invocation.)</p></li>
|
|||
|
<li><p>If there are no required arguments, the optional groups will behave
|
|||
|
as if they’re to the right of the required arguments.</p></li>
|
|||
|
<li><p>In the case of ambiguity, the argument parsing code
|
|||
|
favors parameters on the left (before the required parameters).</p></li>
|
|||
|
<li><p>Optional groups can only contain positional-only parameters.</p></li>
|
|||
|
<li><p>Optional groups are <em>only</em> intended for legacy code. Please do not
|
|||
|
use optional groups for new code.</p></li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<div class="section" id="using-real-argument-clinic-converters-instead-of-legacy-converters">
|
|||
|
<h3>Using real Argument Clinic converters, instead of “legacy converters”<a class="headerlink" href="#using-real-argument-clinic-converters-instead-of-legacy-converters" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>To save time, and to minimize how much you need to learn
|
|||
|
to achieve your first port to Argument Clinic, the walkthrough above tells
|
|||
|
you to use “legacy converters”. “Legacy converters” are a convenience,
|
|||
|
designed explicitly to make porting existing code to Argument Clinic
|
|||
|
easier. And to be clear, their use is acceptable when porting code for
|
|||
|
Python 3.4.</p>
|
|||
|
<p>However, in the long term we probably want all our blocks to
|
|||
|
use Argument Clinic’s real syntax for converters. Why? A couple
|
|||
|
reasons:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li><p>The proper converters are far easier to read and clearer in their intent.</p></li>
|
|||
|
<li><p>There are some format units that are unsupported as “legacy converters”,
|
|||
|
because they require arguments, and the legacy converter syntax doesn’t
|
|||
|
support specifying arguments.</p></li>
|
|||
|
<li><p>In the future we may have a new argument parsing library that isn’t
|
|||
|
restricted to what <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a> supports; this flexibility
|
|||
|
won’t be available to parameters using legacy converters.</p></li>
|
|||
|
</ul>
|
|||
|
<p>Therefore, if you don’t mind a little extra effort, please use the normal
|
|||
|
converters instead of legacy converters.</p>
|
|||
|
<p>In a nutshell, the syntax for Argument Clinic (non-legacy) converters
|
|||
|
looks like a Python function call. However, if there are no explicit
|
|||
|
arguments to the function (all functions take their default values),
|
|||
|
you may omit the parentheses. Thus <code class="docutils literal notranslate"><span class="pre">bool</span></code> and <code class="docutils literal notranslate"><span class="pre">bool()</span></code> are exactly
|
|||
|
the same converters.</p>
|
|||
|
<p>All arguments to Argument Clinic converters are keyword-only.
|
|||
|
All Argument Clinic converters accept the following arguments:</p>
|
|||
|
<blockquote>
|
|||
|
<div><dl class="simple">
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">c_default</span></code></dt><dd><p>The default value for this parameter when defined in C.
|
|||
|
Specifically, this will be the initializer for the variable declared
|
|||
|
in the “parse function”. See <a class="reference internal" href="#default-values"><span class="std std-ref">the section on default values</span></a>
|
|||
|
for how to use this.
|
|||
|
Specified as a string.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">annotation</span></code></dt><dd><p>The annotation value for this parameter. Not currently supported,
|
|||
|
because PEP 8 mandates that the Python library may not use
|
|||
|
annotations.</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
</div></blockquote>
|
|||
|
<p>In addition, some converters accept additional arguments. Here is a list
|
|||
|
of these arguments, along with their meanings:</p>
|
|||
|
<blockquote>
|
|||
|
<div><dl>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">accept</span></code></dt><dd><p>A set of Python types (and possibly pseudo-types);
|
|||
|
this restricts the allowable Python argument to values of these types.
|
|||
|
(This is not a general-purpose facility; as a rule it only supports
|
|||
|
specific lists of types as shown in the legacy converter table.)</p>
|
|||
|
<p>To accept <code class="docutils literal notranslate"><span class="pre">None</span></code>, add <code class="docutils literal notranslate"><span class="pre">NoneType</span></code> to this set.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">bitwise</span></code></dt><dd><p>Only supported for unsigned integers. The native integer value of this
|
|||
|
Python argument will be written to the parameter without any range checking,
|
|||
|
even for negative values.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">converter</span></code></dt><dd><p>Only supported by the <code class="docutils literal notranslate"><span class="pre">object</span></code> converter. Specifies the name of a
|
|||
|
<a class="reference internal" href="../c-api/arg.html#o-ampersand"><span class="std std-ref">C “converter function”</span></a>
|
|||
|
to use to convert this object to a native type.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">encoding</span></code></dt><dd><p>Only supported for strings. Specifies the encoding to use when converting
|
|||
|
this string from a Python str (Unicode) value into a C <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*</span></code> value.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">subclass_of</span></code></dt><dd><p>Only supported for the <code class="docutils literal notranslate"><span class="pre">object</span></code> converter. Requires that the Python
|
|||
|
value be a subclass of a Python type, as expressed in C.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">type</span></code></dt><dd><p>Only supported for the <code class="docutils literal notranslate"><span class="pre">object</span></code> and <code class="docutils literal notranslate"><span class="pre">self</span></code> converters. Specifies
|
|||
|
the C type that will be used to declare the variable. Default value is
|
|||
|
<code class="docutils literal notranslate"><span class="pre">"PyObject</span> <span class="pre">*"</span></code>.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">zeroes</span></code></dt><dd><p>Only supported for strings. If true, embedded NUL bytes (<code class="docutils literal notranslate"><span class="pre">'\\0'</span></code>) are
|
|||
|
permitted inside the value. The length of the string will be passed in
|
|||
|
to the impl function, just after the string parameter, as a parameter named
|
|||
|
<code class="docutils literal notranslate"><span class="pre"><parameter_name>_length</span></code>.</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
</div></blockquote>
|
|||
|
<p>Please note, not every possible combination of arguments will work.
|
|||
|
Usually these arguments are implemented by specific <code class="docutils literal notranslate"><span class="pre">PyArg_ParseTuple</span></code>
|
|||
|
<em>format units</em>, with specific behavior. For example, currently you cannot
|
|||
|
call <code class="docutils literal notranslate"><span class="pre">unsigned_short</span></code> without also specifying <code class="docutils literal notranslate"><span class="pre">bitwise=True</span></code>.
|
|||
|
Although it’s perfectly reasonable to think this would work, these semantics don’t
|
|||
|
map to any existing format unit. So Argument Clinic doesn’t support it. (Or, at
|
|||
|
least, not yet.)</p>
|
|||
|
<p>Below is a table showing the mapping of legacy converters into real
|
|||
|
Argument Clinic converters. On the left is the legacy converter,
|
|||
|
on the right is the text you’d replace it with.</p>
|
|||
|
<table class="docutils align-center">
|
|||
|
<colgroup>
|
|||
|
<col style="width: 10%" />
|
|||
|
<col style="width: 90%" />
|
|||
|
</colgroup>
|
|||
|
<tbody>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'B'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">unsigned_char(bitwise=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'b'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">unsigned_char</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'c'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">char</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'C'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">int(accept={str})</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'d'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">double</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'D'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">Py_complex</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'es'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">str(encoding='name_of_encoding')</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'es#'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">str(encoding='name_of_encoding',</span> <span class="pre">zeroes=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'et'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">str(encoding='name_of_encoding',</span> <span class="pre">accept={bytes,</span> <span class="pre">bytearray,</span> <span class="pre">str})</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'et#'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">str(encoding='name_of_encoding',</span> <span class="pre">accept={bytes,</span> <span class="pre">bytearray,</span> <span class="pre">str},</span> <span class="pre">zeroes=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'f'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">float</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'h'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">short</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'H'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">unsigned_short(bitwise=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'i'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">int</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'I'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">unsigned_int(bitwise=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'k'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">unsigned_long(bitwise=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'K'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">unsigned_long_long(bitwise=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'l'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">long</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'L'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">long</span> <span class="pre">long</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'n'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">Py_ssize_t</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'O'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">object</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'O!'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">object(subclass_of='&PySomething_Type')</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'O&'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">object(converter='name_of_c_function')</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'p'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">bool</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'S'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">PyBytesObject</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'s'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">str</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'s#'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">str(zeroes=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'s*'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">Py_buffer(accept={buffer,</span> <span class="pre">str})</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'U'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">unicode</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'u'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">Py_UNICODE</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'u#'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">Py_UNICODE(zeroes=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'w*'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">Py_buffer(accept={rwbuffer})</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'Y'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">PyByteArrayObject</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'y'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">str(accept={bytes})</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'y#'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">str(accept={robuffer},</span> <span class="pre">zeroes=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'y*'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">Py_buffer</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'Z'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">Py_UNICODE(accept={str,</span> <span class="pre">NoneType})</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'Z#'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">Py_UNICODE(accept={str,</span> <span class="pre">NoneType},</span> <span class="pre">zeroes=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'z'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">str(accept={str,</span> <span class="pre">NoneType})</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">'z#'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">str(accept={str,</span> <span class="pre">NoneType},</span> <span class="pre">zeroes=True)</span></code></p></td>
|
|||
|
</tr>
|
|||
|
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">'z*'</span></code></p></td>
|
|||
|
<td><p><code class="docutils literal notranslate"><span class="pre">Py_buffer(accept={buffer,</span> <span class="pre">str,</span> <span class="pre">NoneType})</span></code></p></td>
|
|||
|
</tr>
|
|||
|
</tbody>
|
|||
|
</table>
|
|||
|
<p>As an example, here’s our sample <code class="docutils literal notranslate"><span class="pre">pickle.Pickler.dump</span></code> using the proper
|
|||
|
converter:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm"> obj: object</span>
|
|||
|
<span class="cm"> The object to be pickled.</span>
|
|||
|
<span class="cm"> /</span>
|
|||
|
|
|||
|
<span class="cm">Write a pickled representation of obj to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Argument Clinic will show you all the converters it has
|
|||
|
available. For each converter it’ll show you all the parameters
|
|||
|
it accepts, along with the default value for each parameter.
|
|||
|
Just run <code class="docutils literal notranslate"><span class="pre">Tools/clinic/clinic.py</span> <span class="pre">--converters</span></code> to see the full list.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="py-buffer">
|
|||
|
<h3>Py_buffer<a class="headerlink" href="#py-buffer" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>When using the <code class="docutils literal notranslate"><span class="pre">Py_buffer</span></code> converter
|
|||
|
(or the <code class="docutils literal notranslate"><span class="pre">'s*'</span></code>, <code class="docutils literal notranslate"><span class="pre">'w*'</span></code>, <code class="docutils literal notranslate"><span class="pre">'*y'</span></code>, or <code class="docutils literal notranslate"><span class="pre">'z*'</span></code> legacy converters),
|
|||
|
you <em>must</em> not call <a class="reference internal" href="../c-api/buffer.html#c.PyBuffer_Release" title="PyBuffer_Release"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyBuffer_Release()</span></code></a> on the provided buffer.
|
|||
|
Argument Clinic generates code that does it for you (in the parsing function).</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="advanced-converters">
|
|||
|
<h3>Advanced converters<a class="headerlink" href="#advanced-converters" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Remember those format units you skipped for your first
|
|||
|
time because they were advanced? Here’s how to handle those too.</p>
|
|||
|
<p>The trick is, all those format units take arguments—either
|
|||
|
conversion functions, or types, or strings specifying an encoding.
|
|||
|
(But “legacy converters” don’t support arguments. That’s why we
|
|||
|
skipped them for your first function.) The argument you specified
|
|||
|
to the format unit is now an argument to the converter; this
|
|||
|
argument is either <code class="docutils literal notranslate"><span class="pre">converter</span></code> (for <code class="docutils literal notranslate"><span class="pre">O&</span></code>), <code class="docutils literal notranslate"><span class="pre">subclass_of</span></code> (for <code class="docutils literal notranslate"><span class="pre">O!</span></code>),
|
|||
|
or <code class="docutils literal notranslate"><span class="pre">encoding</span></code> (for all the format units that start with <code class="docutils literal notranslate"><span class="pre">e</span></code>).</p>
|
|||
|
<p>When using <code class="docutils literal notranslate"><span class="pre">subclass_of</span></code>, you may also want to use the other
|
|||
|
custom argument for <code class="docutils literal notranslate"><span class="pre">object()</span></code>: <code class="docutils literal notranslate"><span class="pre">type</span></code>, which lets you set the type
|
|||
|
actually used for the parameter. For example, if you want to ensure
|
|||
|
that the object is a subclass of <code class="docutils literal notranslate"><span class="pre">PyUnicode_Type</span></code>, you probably want
|
|||
|
to use the converter <code class="docutils literal notranslate"><span class="pre">object(type='PyUnicodeObject</span> <span class="pre">*',</span> <span class="pre">subclass_of='&PyUnicode_Type')</span></code>.</p>
|
|||
|
<p>One possible problem with using Argument Clinic: it takes away some possible
|
|||
|
flexibility for the format units starting with <code class="docutils literal notranslate"><span class="pre">e</span></code>. When writing a
|
|||
|
<code class="docutils literal notranslate"><span class="pre">PyArg_Parse</span></code> call by hand, you could theoretically decide at runtime what
|
|||
|
encoding string to pass in to <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a>. But now this string must
|
|||
|
be hard-coded at Argument-Clinic-preprocessing-time. This limitation is deliberate;
|
|||
|
it made supporting this format unit much easier, and may allow for future optimizations.
|
|||
|
This restriction doesn’t seem unreasonable; CPython itself always passes in static
|
|||
|
hard-coded encoding strings for parameters whose format units start with <code class="docutils literal notranslate"><span class="pre">e</span></code>.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="parameter-default-values">
|
|||
|
<span id="default-values"></span><h3>Parameter default values<a class="headerlink" href="#parameter-default-values" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Default values for parameters can be any of a number of values.
|
|||
|
At their simplest, they can be string, int, or float literals:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>foo: str = "abc"
|
|||
|
bar: int = 123
|
|||
|
bat: float = 45.6
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>They can also use any of Python’s built-in constants:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>yep: bool = True
|
|||
|
nope: bool = False
|
|||
|
nada: object = None
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>There’s also special support for a default value of <code class="docutils literal notranslate"><span class="pre">NULL</span></code>, and
|
|||
|
for simple expressions, documented in the following sections.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="the-null-default-value">
|
|||
|
<h3>The <code class="docutils literal notranslate"><span class="pre">NULL</span></code> default value<a class="headerlink" href="#the-null-default-value" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>For string and object parameters, you can set them to <code class="docutils literal notranslate"><span class="pre">None</span></code> to indicate
|
|||
|
that there’s no default. However, that means the C variable will be
|
|||
|
initialized to <code class="docutils literal notranslate"><span class="pre">Py_None</span></code>. For convenience’s sakes, there’s a special
|
|||
|
value called <code class="docutils literal notranslate"><span class="pre">NULL</span></code> for just this reason: from Python’s perspective it
|
|||
|
behaves like a default value of <code class="docutils literal notranslate"><span class="pre">None</span></code>, but the C variable is initialized
|
|||
|
with <code class="docutils literal notranslate"><span class="pre">NULL</span></code>.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="expressions-specified-as-default-values">
|
|||
|
<h3>Expressions specified as default values<a class="headerlink" href="#expressions-specified-as-default-values" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>The default value for a parameter can be more than just a literal value.
|
|||
|
It can be an entire expression, using math operators and looking up attributes
|
|||
|
on objects. However, this support isn’t exactly simple, because of some
|
|||
|
non-obvious semantics.</p>
|
|||
|
<p>Consider the following example:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>foo: Py_ssize_t = sys.maxsize - 1
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">sys.maxsize</span></code> can have different values on different platforms. Therefore
|
|||
|
Argument Clinic can’t simply evaluate that expression locally and hard-code it
|
|||
|
in C. So it stores the default in such a way that it will get evaluated at
|
|||
|
runtime, when the user asks for the function’s signature.</p>
|
|||
|
<p>What namespace is available when the expression is evaluated? It’s evaluated
|
|||
|
in the context of the module the builtin came from. So, if your module has an
|
|||
|
attribute called “<code class="docutils literal notranslate"><span class="pre">max_widgets</span></code>”, you may simply use it:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>foo: Py_ssize_t = max_widgets
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>If the symbol isn’t found in the current module, it fails over to looking in
|
|||
|
<code class="docutils literal notranslate"><span class="pre">sys.modules</span></code>. That’s how it can find <code class="docutils literal notranslate"><span class="pre">sys.maxsize</span></code> for example. (Since you
|
|||
|
don’t know in advance what modules the user will load into their interpreter,
|
|||
|
it’s best to restrict yourself to modules that are preloaded by Python itself.)</p>
|
|||
|
<p>Evaluating default values only at runtime means Argument Clinic can’t compute
|
|||
|
the correct equivalent C default value. So you need to tell it explicitly.
|
|||
|
When you use an expression, you must also specify the equivalent expression
|
|||
|
in C, using the <code class="docutils literal notranslate"><span class="pre">c_default</span></code> parameter to the converter:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>foo: Py_ssize_t(c_default="PY_SSIZE_T_MAX - 1") = sys.maxsize - 1
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Another complication: Argument Clinic can’t know in advance whether or not the
|
|||
|
expression you supply is valid. It parses it to make sure it looks legal, but
|
|||
|
it can’t <em>actually</em> know. You must be very careful when using expressions to
|
|||
|
specify values that are guaranteed to be valid at runtime!</p>
|
|||
|
<p>Finally, because expressions must be representable as static C values, there
|
|||
|
are many restrictions on legal expressions. Here’s a list of Python features
|
|||
|
you’re not permitted to use:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li><p>Function calls.</p></li>
|
|||
|
<li><p>Inline if statements (<code class="docutils literal notranslate"><span class="pre">3</span> <span class="pre">if</span> <span class="pre">foo</span> <span class="pre">else</span> <span class="pre">5</span></code>).</p></li>
|
|||
|
<li><p>Automatic sequence unpacking (<code class="docutils literal notranslate"><span class="pre">*[1,</span> <span class="pre">2,</span> <span class="pre">3]</span></code>).</p></li>
|
|||
|
<li><p>List/set/dict comprehensions and generator expressions.</p></li>
|
|||
|
<li><p>Tuple/list/set/dict literals.</p></li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<div class="section" id="using-a-return-converter">
|
|||
|
<h3>Using a return converter<a class="headerlink" href="#using-a-return-converter" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>By default the impl function Argument Clinic generates for you returns <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code>.
|
|||
|
But your C function often computes some C type, then converts it into the <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code>
|
|||
|
at the last moment. Argument Clinic handles converting your inputs from Python types
|
|||
|
into native C types—why not have it convert your return value from a native C type
|
|||
|
into a Python type too?</p>
|
|||
|
<p>That’s what a “return converter” does. It changes your impl function to return
|
|||
|
some C type, then adds code to the generated (non-impl) function to handle converting
|
|||
|
that value into the appropriate <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code>.</p>
|
|||
|
<p>The syntax for return converters is similar to that of parameter converters.
|
|||
|
You specify the return converter like it was a return annotation on the
|
|||
|
function itself. Return converters behave much the same as parameter converters;
|
|||
|
they take arguments, the arguments are all keyword-only, and if you’re not changing
|
|||
|
any of the default arguments you can omit the parentheses.</p>
|
|||
|
<p>(If you use both <code class="docutils literal notranslate"><span class="pre">"as"</span></code> <em>and</em> a return converter for your function,
|
|||
|
the <code class="docutils literal notranslate"><span class="pre">"as"</span></code> should come before the return converter.)</p>
|
|||
|
<p>There’s one additional complication when using return converters: how do you
|
|||
|
indicate an error has occurred? Normally, a function returns a valid (non-<code class="docutils literal notranslate"><span class="pre">NULL</span></code>)
|
|||
|
pointer for success, and <code class="docutils literal notranslate"><span class="pre">NULL</span></code> for failure. But if you use an integer return converter,
|
|||
|
all integers are valid. How can Argument Clinic detect an error? Its solution: each return
|
|||
|
converter implicitly looks for a special value that indicates an error. If you return
|
|||
|
that value, and an error has been set (<code class="docutils literal notranslate"><span class="pre">PyErr_Occurred()</span></code> returns a true
|
|||
|
value), then the generated code will propagate the error. Otherwise it will
|
|||
|
encode the value you return like normal.</p>
|
|||
|
<p>Currently Argument Clinic supports only a few return converters:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>bool
|
|||
|
int
|
|||
|
unsigned int
|
|||
|
long
|
|||
|
unsigned int
|
|||
|
size_t
|
|||
|
Py_ssize_t
|
|||
|
float
|
|||
|
double
|
|||
|
DecodeFSDefault
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>None of these take parameters. For the first three, return -1 to indicate
|
|||
|
error. For <code class="docutils literal notranslate"><span class="pre">DecodeFSDefault</span></code>, the return type is <code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">char</span> <span class="pre">*</span></code>; return a NULL
|
|||
|
pointer to indicate an error.</p>
|
|||
|
<p>(There’s also an experimental <code class="docutils literal notranslate"><span class="pre">NoneType</span></code> converter, which lets you
|
|||
|
return <code class="docutils literal notranslate"><span class="pre">Py_None</span></code> on success or <code class="docutils literal notranslate"><span class="pre">NULL</span></code> on failure, without having
|
|||
|
to increment the reference count on <code class="docutils literal notranslate"><span class="pre">Py_None</span></code>. I’m not sure it adds
|
|||
|
enough clarity to be worth using.)</p>
|
|||
|
<p>To see all the return converters Argument Clinic supports, along with
|
|||
|
their parameters (if any),
|
|||
|
just run <code class="docutils literal notranslate"><span class="pre">Tools/clinic/clinic.py</span> <span class="pre">--converters</span></code> for the full list.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="cloning-existing-functions">
|
|||
|
<h3>Cloning existing functions<a class="headerlink" href="#cloning-existing-functions" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>If you have a number of functions that look similar, you may be able to
|
|||
|
use Clinic’s “clone” feature. When you clone an existing function,
|
|||
|
you reuse:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li><p>its parameters, including</p>
|
|||
|
<ul>
|
|||
|
<li><p>their names,</p></li>
|
|||
|
<li><p>their converters, with all parameters,</p></li>
|
|||
|
<li><p>their default values,</p></li>
|
|||
|
<li><p>their per-parameter docstrings,</p></li>
|
|||
|
<li><p>their <em>kind</em> (whether they’re positional only,
|
|||
|
positional or keyword, or keyword only), and</p></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><p>its return converter.</p></li>
|
|||
|
</ul>
|
|||
|
<p>The only thing not copied from the original function is its docstring;
|
|||
|
the syntax allows you to specify a new docstring.</p>
|
|||
|
<p>Here’s the syntax for cloning a function:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">module.class.new_function [as c_basename] = module.class.existing_function</span>
|
|||
|
|
|||
|
<span class="cm">Docstring for new_function goes here.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>(The functions can be in different modules or classes. I wrote
|
|||
|
<code class="docutils literal notranslate"><span class="pre">module.class</span></code> in the sample just to illustrate that you must
|
|||
|
use the full path to <em>both</em> functions.)</p>
|
|||
|
<p>Sorry, there’s no syntax for partially-cloning a function, or cloning a function
|
|||
|
then modifying it. Cloning is an all-or nothing proposition.</p>
|
|||
|
<p>Also, the function you are cloning from must have been previously defined
|
|||
|
in the current file.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="calling-python-code">
|
|||
|
<h3>Calling Python code<a class="headerlink" href="#calling-python-code" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>The rest of the advanced topics require you to write Python code
|
|||
|
which lives inside your C file and modifies Argument Clinic’s
|
|||
|
runtime state. This is simple: you simply define a Python block.</p>
|
|||
|
<p>A Python block uses different delimiter lines than an Argument
|
|||
|
Clinic function block. It looks like this:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[python input]</span>
|
|||
|
<span class="cm"># python code goes here</span>
|
|||
|
<span class="cm">[python start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>All the code inside the Python block is executed at the
|
|||
|
time it’s parsed. All text written to stdout inside the block
|
|||
|
is redirected into the “output” after the block.</p>
|
|||
|
<p>As an example, here’s a Python block that adds a static integer
|
|||
|
variable to the C code:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[python input]</span>
|
|||
|
<span class="cm">print('static int __ignored_unused_variable__ = 0;')</span>
|
|||
|
<span class="cm">[python start generated code]*/</span>
|
|||
|
<span class="k">static</span> <span class="kt">int</span> <span class="n">__ignored_unused_variable__</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
|||
|
<span class="cm">/*[python checksum:...]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="using-a-self-converter">
|
|||
|
<h3>Using a “self converter”<a class="headerlink" href="#using-a-self-converter" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Argument Clinic automatically adds a “self” parameter for you
|
|||
|
using a default converter. It automatically sets the <code class="docutils literal notranslate"><span class="pre">type</span></code>
|
|||
|
of this parameter to the “pointer to an instance” you specified
|
|||
|
when you declared the type. However, you can override
|
|||
|
Argument Clinic’s converter and specify one yourself.
|
|||
|
Just add your own <code class="docutils literal notranslate"><span class="pre">self</span></code> parameter as the first parameter in a
|
|||
|
block, and ensure that its converter is an instance of
|
|||
|
<code class="docutils literal notranslate"><span class="pre">self_converter</span></code> or a subclass thereof.</p>
|
|||
|
<p>What’s the point? This lets you override the type of <code class="docutils literal notranslate"><span class="pre">self</span></code>,
|
|||
|
or give it a different default name.</p>
|
|||
|
<p>How do you specify the custom type you want to cast <code class="docutils literal notranslate"><span class="pre">self</span></code> to?
|
|||
|
If you only have one or two functions with the same type for <code class="docutils literal notranslate"><span class="pre">self</span></code>,
|
|||
|
you can directly use Argument Clinic’s existing <code class="docutils literal notranslate"><span class="pre">self</span></code> converter,
|
|||
|
passing in the type you want to use as the <code class="docutils literal notranslate"><span class="pre">type</span></code> parameter:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
|
|||
|
<span class="cm">_pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm"> self: self(type="PicklerObject *")</span>
|
|||
|
<span class="cm"> obj: object</span>
|
|||
|
<span class="cm"> /</span>
|
|||
|
|
|||
|
<span class="cm">Write a pickled representation of the given object to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>On the other hand, if you have a lot of functions that will use the same
|
|||
|
type for <code class="docutils literal notranslate"><span class="pre">self</span></code>, it’s best to create your own converter, subclassing
|
|||
|
<code class="docutils literal notranslate"><span class="pre">self_converter</span></code> but overwriting the <code class="docutils literal notranslate"><span class="pre">type</span></code> member:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[python input]</span>
|
|||
|
<span class="cm">class PicklerObject_converter(self_converter):</span>
|
|||
|
<span class="cm"> type = "PicklerObject *"</span>
|
|||
|
<span class="cm">[python start generated code]*/</span>
|
|||
|
|
|||
|
<span class="cm">/*[clinic input]</span>
|
|||
|
|
|||
|
<span class="cm">_pickle.Pickler.dump</span>
|
|||
|
|
|||
|
<span class="cm"> self: PicklerObject</span>
|
|||
|
<span class="cm"> obj: object</span>
|
|||
|
<span class="cm"> /</span>
|
|||
|
|
|||
|
<span class="cm">Write a pickled representation of the given object to the open file.</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="writing-a-custom-converter">
|
|||
|
<h3>Writing a custom converter<a class="headerlink" href="#writing-a-custom-converter" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>As we hinted at in the previous section… you can write your own converters!
|
|||
|
A converter is simply a Python class that inherits from <code class="docutils literal notranslate"><span class="pre">CConverter</span></code>.
|
|||
|
The main purpose of a custom converter is if you have a parameter using
|
|||
|
the <code class="docutils literal notranslate"><span class="pre">O&</span></code> format unit—parsing this parameter means calling
|
|||
|
a <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a> “converter function”.</p>
|
|||
|
<p>Your converter class should be named <code class="docutils literal notranslate"><span class="pre">*something*_converter</span></code>.
|
|||
|
If the name follows this convention, then your converter class
|
|||
|
will be automatically registered with Argument Clinic; its name
|
|||
|
will be the name of your class with the <code class="docutils literal notranslate"><span class="pre">_converter</span></code> suffix
|
|||
|
stripped off. (This is accomplished with a metaclass.)</p>
|
|||
|
<p>You shouldn’t subclass <code class="docutils literal notranslate"><span class="pre">CConverter.__init__</span></code>. Instead, you should
|
|||
|
write a <code class="docutils literal notranslate"><span class="pre">converter_init()</span></code> function. <code class="docutils literal notranslate"><span class="pre">converter_init()</span></code>
|
|||
|
always accepts a <code class="docutils literal notranslate"><span class="pre">self</span></code> parameter; after that, all additional
|
|||
|
parameters <em>must</em> be keyword-only. Any arguments passed in to
|
|||
|
the converter in Argument Clinic will be passed along to your
|
|||
|
<code class="docutils literal notranslate"><span class="pre">converter_init()</span></code>.</p>
|
|||
|
<p>There are some additional members of <code class="docutils literal notranslate"><span class="pre">CConverter</span></code> you may wish
|
|||
|
to specify in your subclass. Here’s the current list:</p>
|
|||
|
<dl class="simple">
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">type</span></code></dt><dd><p>The C type to use for this variable.
|
|||
|
<code class="docutils literal notranslate"><span class="pre">type</span></code> should be a Python string specifying the type, e.g. <code class="docutils literal notranslate"><span class="pre">int</span></code>.
|
|||
|
If this is a pointer type, the type string should end with <code class="docutils literal notranslate"><span class="pre">'</span> <span class="pre">*'</span></code>.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">default</span></code></dt><dd><p>The Python default value for this parameter, as a Python value.
|
|||
|
Or the magic value <code class="docutils literal notranslate"><span class="pre">unspecified</span></code> if there is no default.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">py_default</span></code></dt><dd><p><code class="docutils literal notranslate"><span class="pre">default</span></code> as it should appear in Python code,
|
|||
|
as a string.
|
|||
|
Or <code class="docutils literal notranslate"><span class="pre">None</span></code> if there is no default.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">c_default</span></code></dt><dd><p><code class="docutils literal notranslate"><span class="pre">default</span></code> as it should appear in C code,
|
|||
|
as a string.
|
|||
|
Or <code class="docutils literal notranslate"><span class="pre">None</span></code> if there is no default.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">c_ignored_default</span></code></dt><dd><p>The default value used to initialize the C variable when
|
|||
|
there is no default, but not specifying a default may
|
|||
|
result in an “uninitialized variable” warning. This can
|
|||
|
easily happen when using option groups—although
|
|||
|
properly-written code will never actually use this value,
|
|||
|
the variable does get passed in to the impl, and the
|
|||
|
C compiler will complain about the “use” of the
|
|||
|
uninitialized value. This value should always be a
|
|||
|
non-empty string.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">converter</span></code></dt><dd><p>The name of the C converter function, as a string.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">impl_by_reference</span></code></dt><dd><p>A boolean value. If true,
|
|||
|
Argument Clinic will add a <code class="docutils literal notranslate"><span class="pre">&</span></code> in front of the name of
|
|||
|
the variable when passing it into the impl function.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">parse_by_reference</span></code></dt><dd><p>A boolean value. If true,
|
|||
|
Argument Clinic will add a <code class="docutils literal notranslate"><span class="pre">&</span></code> in front of the name of
|
|||
|
the variable when passing it into <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a>.</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
<p>Here’s the simplest example of a custom converter, from <code class="docutils literal notranslate"><span class="pre">Modules/zlibmodule.c</span></code>:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[python input]</span>
|
|||
|
|
|||
|
<span class="cm">class ssize_t_converter(CConverter):</span>
|
|||
|
<span class="cm"> type = 'Py_ssize_t'</span>
|
|||
|
<span class="cm"> converter = 'ssize_t_converter'</span>
|
|||
|
|
|||
|
<span class="cm">[python start generated code]*/</span>
|
|||
|
<span class="cm">/*[python end generated code: output=da39a3ee5e6b4b0d input=35521e4e733823c7]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This block adds a converter to Argument Clinic named <code class="docutils literal notranslate"><span class="pre">ssize_t</span></code>. Parameters
|
|||
|
declared as <code class="docutils literal notranslate"><span class="pre">ssize_t</span></code> will be declared as type <code class="docutils literal notranslate"><span class="pre">Py_ssize_t</span></code>, and will
|
|||
|
be parsed by the <code class="docutils literal notranslate"><span class="pre">'O&'</span></code> format unit, which will call the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">ssize_t_converter</span></code> converter function. <code class="docutils literal notranslate"><span class="pre">ssize_t</span></code> variables
|
|||
|
automatically support default values.</p>
|
|||
|
<p>More sophisticated custom converters can insert custom C code to
|
|||
|
handle initialization and cleanup.
|
|||
|
You can see more examples of custom converters in the CPython
|
|||
|
source tree; grep the C files for the string <code class="docutils literal notranslate"><span class="pre">CConverter</span></code>.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="writing-a-custom-return-converter">
|
|||
|
<h3>Writing a custom return converter<a class="headerlink" href="#writing-a-custom-return-converter" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Writing a custom return converter is much like writing
|
|||
|
a custom converter. Except it’s somewhat simpler, because return
|
|||
|
converters are themselves much simpler.</p>
|
|||
|
<p>Return converters must subclass <code class="docutils literal notranslate"><span class="pre">CReturnConverter</span></code>.
|
|||
|
There are no examples yet of custom return converters,
|
|||
|
because they are not widely used yet. If you wish to
|
|||
|
write your own return converter, please read <code class="docutils literal notranslate"><span class="pre">Tools/clinic/clinic.py</span></code>,
|
|||
|
specifically the implementation of <code class="docutils literal notranslate"><span class="pre">CReturnConverter</span></code> and
|
|||
|
all its subclasses.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="meth-o-and-meth-noargs">
|
|||
|
<h3>METH_O and METH_NOARGS<a class="headerlink" href="#meth-o-and-meth-noargs" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>To convert a function using <code class="docutils literal notranslate"><span class="pre">METH_O</span></code>, make sure the function’s
|
|||
|
single argument is using the <code class="docutils literal notranslate"><span class="pre">object</span></code> converter, and mark the
|
|||
|
arguments as positional-only:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">meth_o_sample</span>
|
|||
|
|
|||
|
<span class="cm"> argument: object</span>
|
|||
|
<span class="cm"> /</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>To convert a function using <code class="docutils literal notranslate"><span class="pre">METH_NOARGS</span></code>, just don’t specify
|
|||
|
any arguments.</p>
|
|||
|
<p>You can still use a self converter, a return converter, and specify
|
|||
|
a <code class="docutils literal notranslate"><span class="pre">type</span></code> argument to the object converter for <code class="docutils literal notranslate"><span class="pre">METH_O</span></code>.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="tp-new-and-tp-init-functions">
|
|||
|
<h3>tp_new and tp_init functions<a class="headerlink" href="#tp-new-and-tp-init-functions" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>You can convert <code class="docutils literal notranslate"><span class="pre">tp_new</span></code> and <code class="docutils literal notranslate"><span class="pre">tp_init</span></code> functions. Just name
|
|||
|
them <code class="docutils literal notranslate"><span class="pre">__new__</span></code> or <code class="docutils literal notranslate"><span class="pre">__init__</span></code> as appropriate. Notes:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li><p>The function name generated for <code class="docutils literal notranslate"><span class="pre">__new__</span></code> doesn’t end in <code class="docutils literal notranslate"><span class="pre">__new__</span></code>
|
|||
|
like it would by default. It’s just the name of the class, converted
|
|||
|
into a valid C identifier.</p></li>
|
|||
|
<li><p>No <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> <code class="docutils literal notranslate"><span class="pre">#define</span></code> is generated for these functions.</p></li>
|
|||
|
<li><p><code class="docutils literal notranslate"><span class="pre">__init__</span></code> functions return <code class="docutils literal notranslate"><span class="pre">int</span></code>, not <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code>.</p></li>
|
|||
|
<li><p>Use the docstring as the class docstring.</p></li>
|
|||
|
<li><p>Although <code class="docutils literal notranslate"><span class="pre">__new__</span></code> and <code class="docutils literal notranslate"><span class="pre">__init__</span></code> functions must always
|
|||
|
accept both the <code class="docutils literal notranslate"><span class="pre">args</span></code> and <code class="docutils literal notranslate"><span class="pre">kwargs</span></code> objects, when converting
|
|||
|
you may specify any signature for these functions that you like.
|
|||
|
(If your function doesn’t support keywords, the parsing function
|
|||
|
generated will throw an exception if it receives any.)</p></li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<div class="section" id="changing-and-redirecting-clinic-s-output">
|
|||
|
<h3>Changing and redirecting Clinic’s output<a class="headerlink" href="#changing-and-redirecting-clinic-s-output" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>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.</p>
|
|||
|
<p>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 before 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.)</p>
|
|||
|
<p>Let’s start with defining some terminology:</p>
|
|||
|
<dl>
|
|||
|
<dt><em>field</em></dt><dd><p>A field, in this context, is a subsection of Clinic’s output.
|
|||
|
For example, the <code class="docutils literal notranslate"><span class="pre">#define</span></code> for the <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> structure
|
|||
|
is a field, called <code class="docutils literal notranslate"><span class="pre">methoddef_define</span></code>. Clinic has seven
|
|||
|
different fields it can output per function definition:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>docstring_prototype
|
|||
|
docstring_definition
|
|||
|
methoddef_define
|
|||
|
impl_prototype
|
|||
|
parser_prototype
|
|||
|
parser_definition
|
|||
|
impl_definition
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>All the names are of the form <code class="docutils literal notranslate"><span class="pre">"<a>_<b>"</span></code>,
|
|||
|
where <code class="docutils literal notranslate"><span class="pre">"<a>"</span></code> is the semantic object represented (the parsing function,
|
|||
|
the impl function, the docstring, or the methoddef structure) and <code class="docutils literal notranslate"><span class="pre">"<b>"</span></code>
|
|||
|
represents what kind of statement the field is. Field names that end in
|
|||
|
<code class="docutils literal notranslate"><span class="pre">"_prototype"</span></code>
|
|||
|
represent forward declarations of that thing, without the actual body/data
|
|||
|
of the thing; field names that end in <code class="docutils literal notranslate"><span class="pre">"_definition"</span></code> represent the actual
|
|||
|
definition of the thing, with the body/data of the thing. (<code class="docutils literal notranslate"><span class="pre">"methoddef"</span></code>
|
|||
|
is special, it’s the only one that ends with <code class="docutils literal notranslate"><span class="pre">"_define"</span></code>, representing that
|
|||
|
it’s a preprocessor #define.)</p>
|
|||
|
</dd>
|
|||
|
<dt><em>destination</em></dt><dd><p>A destination is a place Clinic can write output to. There are
|
|||
|
five built-in destinations:</p>
|
|||
|
<dl>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">block</span></code></dt><dd><p>The default destination: printed in the output section of
|
|||
|
the current Clinic block.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">buffer</span></code></dt><dd><p>A text buffer where you can save text for later. Text sent
|
|||
|
here is appended to the end of any existing text. It’s an
|
|||
|
error to have any text left in the buffer when Clinic finishes
|
|||
|
processing a file.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">file</span></code></dt><dd><p>A separate “clinic file” that will be created automatically by Clinic.
|
|||
|
The filename chosen for the file is <code class="docutils literal notranslate"><span class="pre">{basename}.clinic{extension}</span></code>,
|
|||
|
where <code class="docutils literal notranslate"><span class="pre">basename</span></code> and <code class="docutils literal notranslate"><span class="pre">extension</span></code> were assigned the output
|
|||
|
from <code class="docutils literal notranslate"><span class="pre">os.path.splitext()</span></code> run on the current file. (Example:
|
|||
|
the <code class="docutils literal notranslate"><span class="pre">file</span></code> destination for <code class="docutils literal notranslate"><span class="pre">_pickle.c</span></code> would be written to
|
|||
|
<code class="docutils literal notranslate"><span class="pre">_pickle.clinic.c</span></code>.)</p>
|
|||
|
<p><strong>Important: When using a</strong> <code class="docutils literal notranslate"><span class="pre">file</span></code> <strong>destination, you</strong>
|
|||
|
<em>must check in</em> <strong>the generated file!</strong></p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">two-pass</span></code></dt><dd><p>A buffer like <code class="docutils literal notranslate"><span class="pre">buffer</span></code>. However, a two-pass buffer can only
|
|||
|
be dumped once, and it prints out all text sent to it during
|
|||
|
all processing, even from Clinic blocks <em>after</em> the dumping point.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">suppress</span></code></dt><dd><p>The text is suppressed—thrown away.</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
<p>Clinic defines five new directives that let you reconfigure its output.</p>
|
|||
|
<p>The first new directive is <code class="docutils literal notranslate"><span class="pre">dump</span></code>:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>dump <destination>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This dumps the current contents of the named destination into the output of
|
|||
|
the current block, and empties it. This only works with <code class="docutils literal notranslate"><span class="pre">buffer</span></code> and
|
|||
|
<code class="docutils literal notranslate"><span class="pre">two-pass</span></code> destinations.</p>
|
|||
|
<p>The second new directive is <code class="docutils literal notranslate"><span class="pre">output</span></code>. The most basic form of <code class="docutils literal notranslate"><span class="pre">output</span></code>
|
|||
|
is like this:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>output <field> <destination>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This tells Clinic to output <em>field</em> to <em>destination</em>. <code class="docutils literal notranslate"><span class="pre">output</span></code> also
|
|||
|
supports a special meta-destination, called <code class="docutils literal notranslate"><span class="pre">everything</span></code>, which tells
|
|||
|
Clinic to output <em>all</em> fields to that <em>destination</em>.</p>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">output</span></code> has a number of other functions:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>output push
|
|||
|
output pop
|
|||
|
output preset <preset>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">output</span> <span class="pre">push</span></code> and <code class="docutils literal notranslate"><span class="pre">output</span> <span class="pre">pop</span></code> 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.</p>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">output</span> <span class="pre">preset</span></code> sets Clinic’s output to one of several built-in
|
|||
|
preset configurations, as follows:</p>
|
|||
|
<blockquote>
|
|||
|
<div><dl>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">block</span></code></dt><dd><p>Clinic’s original starting configuration. Writes everything
|
|||
|
immediately after the input block.</p>
|
|||
|
<p>Suppress the <code class="docutils literal notranslate"><span class="pre">parser_prototype</span></code>
|
|||
|
and <code class="docutils literal notranslate"><span class="pre">docstring_prototype</span></code>, write everything else to <code class="docutils literal notranslate"><span class="pre">block</span></code>.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">file</span></code></dt><dd><p>Designed to write everything to the “clinic file” that it can.
|
|||
|
You then <code class="docutils literal notranslate"><span class="pre">#include</span></code> 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
|
|||
|
<code class="docutils literal notranslate"><span class="pre">typedef</span></code> and <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span></code> definitions.</p>
|
|||
|
<p>Suppress the <code class="docutils literal notranslate"><span class="pre">parser_prototype</span></code>
|
|||
|
and <code class="docutils literal notranslate"><span class="pre">docstring_prototype</span></code>, write the <code class="docutils literal notranslate"><span class="pre">impl_definition</span></code> to
|
|||
|
<code class="docutils literal notranslate"><span class="pre">block</span></code>, and write everything else to <code class="docutils literal notranslate"><span class="pre">file</span></code>.</p>
|
|||
|
<p>The default filename is <code class="docutils literal notranslate"><span class="pre">"{dirname}/clinic/{basename}.h"</span></code>.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">buffer</span></code></dt><dd><p>Save up 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
|
|||
|
<code class="docutils literal notranslate"><span class="pre">buffer</span></code> may require even more editing than <code class="docutils literal notranslate"><span class="pre">file</span></code>, if
|
|||
|
your file has static <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> arrays defined in the
|
|||
|
middle of the file.</p>
|
|||
|
<p>Suppress the <code class="docutils literal notranslate"><span class="pre">parser_prototype</span></code>, <code class="docutils literal notranslate"><span class="pre">impl_prototype</span></code>,
|
|||
|
and <code class="docutils literal notranslate"><span class="pre">docstring_prototype</span></code>, write the <code class="docutils literal notranslate"><span class="pre">impl_definition</span></code> to
|
|||
|
<code class="docutils literal notranslate"><span class="pre">block</span></code>, and write everything else to <code class="docutils literal notranslate"><span class="pre">file</span></code>.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">two-pass</span></code></dt><dd><p>Similar to the <code class="docutils literal notranslate"><span class="pre">buffer</span></code> preset, but writes forward declarations to
|
|||
|
the <code class="docutils literal notranslate"><span class="pre">two-pass</span></code> buffer, and definitions to the <code class="docutils literal notranslate"><span class="pre">buffer</span></code>.
|
|||
|
This is similar to the <code class="docutils literal notranslate"><span class="pre">buffer</span></code> preset, but may require
|
|||
|
less editing than <code class="docutils literal notranslate"><span class="pre">buffer</span></code>. Dump the <code class="docutils literal notranslate"><span class="pre">two-pass</span></code> buffer
|
|||
|
near the top of your file, and dump the <code class="docutils literal notranslate"><span class="pre">buffer</span></code> near
|
|||
|
the end just like you would when using the <code class="docutils literal notranslate"><span class="pre">buffer</span></code> preset.</p>
|
|||
|
<p>Suppresses the <code class="docutils literal notranslate"><span class="pre">impl_prototype</span></code>, write the <code class="docutils literal notranslate"><span class="pre">impl_definition</span></code>
|
|||
|
to <code class="docutils literal notranslate"><span class="pre">block</span></code>, write <code class="docutils literal notranslate"><span class="pre">docstring_prototype</span></code>, <code class="docutils literal notranslate"><span class="pre">methoddef_define</span></code>,
|
|||
|
and <code class="docutils literal notranslate"><span class="pre">parser_prototype</span></code> to <code class="docutils literal notranslate"><span class="pre">two-pass</span></code>, write everything else
|
|||
|
to <code class="docutils literal notranslate"><span class="pre">buffer</span></code>.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">partial-buffer</span></code></dt><dd><p>Similar to the <code class="docutils literal notranslate"><span class="pre">buffer</span></code> preset, but writes more things to <code class="docutils literal notranslate"><span class="pre">block</span></code>,
|
|||
|
only writing the really big chunks of generated code to <code class="docutils literal notranslate"><span class="pre">buffer</span></code>.
|
|||
|
This avoids the definition-before-use problem of <code class="docutils literal notranslate"><span class="pre">buffer</span></code> completely,
|
|||
|
at the small cost of having slightly more stuff in the block’s output.
|
|||
|
Dump the <code class="docutils literal notranslate"><span class="pre">buffer</span></code> near the end, just like you would when using
|
|||
|
the <code class="docutils literal notranslate"><span class="pre">buffer</span></code> preset.</p>
|
|||
|
<p>Suppresses the <code class="docutils literal notranslate"><span class="pre">impl_prototype</span></code>, write the <code class="docutils literal notranslate"><span class="pre">docstring_definition</span></code>
|
|||
|
and <code class="docutils literal notranslate"><span class="pre">parser_definition</span></code> to <code class="docutils literal notranslate"><span class="pre">buffer</span></code>, write everything else to <code class="docutils literal notranslate"><span class="pre">block</span></code>.</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
</div></blockquote>
|
|||
|
<p>The third new directive is <code class="docutils literal notranslate"><span class="pre">destination</span></code>:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>destination <name> <command> [...]
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This performs an operation on the destination named <code class="docutils literal notranslate"><span class="pre">name</span></code>.</p>
|
|||
|
<p>There are two defined subcommands: <code class="docutils literal notranslate"><span class="pre">new</span></code> and <code class="docutils literal notranslate"><span class="pre">clear</span></code>.</p>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">new</span></code> subcommand works like this:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>destination <name> new <type>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This creates a new destination with name <code class="docutils literal notranslate"><span class="pre"><name></span></code> and type <code class="docutils literal notranslate"><span class="pre"><type></span></code>.</p>
|
|||
|
<p>There are five destination types:</p>
|
|||
|
<blockquote>
|
|||
|
<div><dl>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">suppress</span></code></dt><dd><p>Throws the text away.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">block</span></code></dt><dd><p>Writes the text to the current block. This is what Clinic
|
|||
|
originally did.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">buffer</span></code></dt><dd><p>A simple text buffer, like the “buffer” builtin destination above.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">file</span></code></dt><dd><p>A text file. The file destination takes an extra argument,
|
|||
|
a template to use for building the filename, like so:</p>
|
|||
|
<blockquote>
|
|||
|
<div><p>destination <name> new <type> <file_template></p>
|
|||
|
</div></blockquote>
|
|||
|
<p>The template can use three strings internally that will be replaced
|
|||
|
by bits of the filename:</p>
|
|||
|
<blockquote>
|
|||
|
<div><dl class="simple">
|
|||
|
<dt>{path}</dt><dd><p>The full path to the file, including directory and full filename.</p>
|
|||
|
</dd>
|
|||
|
<dt>{dirname}</dt><dd><p>The name of the directory the file is in.</p>
|
|||
|
</dd>
|
|||
|
<dt>{basename}</dt><dd><p>Just the name of the file, not including the directory.</p>
|
|||
|
</dd>
|
|||
|
<dt>{basename_root}</dt><dd><p>Basename with the extension clipped off
|
|||
|
(everything up to but not including the last ‘.’).</p>
|
|||
|
</dd>
|
|||
|
<dt>{basename_extension}</dt><dd><p>The last ‘.’ and everything after it. If the basename
|
|||
|
does not contain a period, this will be the empty string.</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
</div></blockquote>
|
|||
|
<p>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}”.”</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">two-pass</span></code></dt><dd><p>A two-pass buffer, like the “two-pass” builtin destination above.</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
</div></blockquote>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">clear</span></code> subcommand works like this:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>destination <name> clear
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>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.)</p>
|
|||
|
<p>The fourth new directive is <code class="docutils literal notranslate"><span class="pre">set</span></code>:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>set line_prefix "string"
|
|||
|
set line_suffix "string"
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">set</span></code> lets you set two internal variables in Clinic.
|
|||
|
<code class="docutils literal notranslate"><span class="pre">line_prefix</span></code> is a string that will be prepended to every line of Clinic’s output;
|
|||
|
<code class="docutils literal notranslate"><span class="pre">line_suffix</span></code> is a string that will be appended to every line of Clinic’s output.</p>
|
|||
|
<p>Both of these support two format strings:</p>
|
|||
|
<blockquote>
|
|||
|
<div><dl class="simple">
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">{block</span> <span class="pre">comment</span> <span class="pre">start}</span></code></dt><dd><p>Turns into the string <code class="docutils literal notranslate"><span class="pre">/*</span></code>, the start-comment text sequence for C files.</p>
|
|||
|
</dd>
|
|||
|
<dt><code class="docutils literal notranslate"><span class="pre">{block</span> <span class="pre">comment</span> <span class="pre">end}</span></code></dt><dd><p>Turns into the string <code class="docutils literal notranslate"><span class="pre">*/</span></code>, the end-comment text sequence for C files.</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
</div></blockquote>
|
|||
|
<p>The final new directive is one you shouldn’t need to use directly,
|
|||
|
called <code class="docutils literal notranslate"><span class="pre">preserve</span></code>:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>preserve
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This tells Clinic that the current contents of the output should be kept, unmodified.
|
|||
|
This is used internally by Clinic when dumping output into <code class="docutils literal notranslate"><span class="pre">file</span></code> 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.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="the-ifdef-trick">
|
|||
|
<h3>The #ifdef trick<a class="headerlink" href="#the-ifdef-trick" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>If you’re converting a function that isn’t available on all platforms,
|
|||
|
there’s a trick you can use to make life a little easier. The existing
|
|||
|
code probably looks like this:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#ifdef HAVE_FUNCTIONNAME</span>
|
|||
|
<span class="k">static</span> <span class="nf">module_functionname</span><span class="p">(...)</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="p">...</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="cp">#endif </span><span class="cm">/* HAVE_FUNCTIONNAME */</span><span class="cp"></span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>And then in the <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> structure at the bottom the existing code
|
|||
|
will have:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>#ifdef HAVE_FUNCTIONNAME
|
|||
|
{'functionname', ... },
|
|||
|
#endif /* HAVE_FUNCTIONNAME */
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>In this scenario, you should enclose the body of your impl function inside the <code class="docutils literal notranslate"><span class="pre">#ifdef</span></code>,
|
|||
|
like so:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#ifdef HAVE_FUNCTIONNAME</span>
|
|||
|
<span class="cm">/*[clinic input]</span>
|
|||
|
<span class="cm">module.functionname</span>
|
|||
|
<span class="cm">...</span>
|
|||
|
<span class="cm">[clinic start generated code]*/</span>
|
|||
|
<span class="k">static</span> <span class="nf">module_functionname</span><span class="p">(...)</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="p">...</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="cp">#endif </span><span class="cm">/* HAVE_FUNCTIONNAME */</span><span class="cp"></span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Then, remove those three lines from the <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> structure,
|
|||
|
replacing them with the macro Argument Clinic generated:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>MODULE_FUNCTIONNAME_METHODDEF
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>(You can find the real name for this macro inside the generated code.
|
|||
|
Or you can calculate it yourself: it’s the name of your function as defined
|
|||
|
on the first line of your block, but with periods changed to underscores,
|
|||
|
uppercased, and <code class="docutils literal notranslate"><span class="pre">"_METHODDEF"</span></code> added to the end.)</p>
|
|||
|
<p>Perhaps you’re wondering: what if <code class="docutils literal notranslate"><span class="pre">HAVE_FUNCTIONNAME</span></code> isn’t defined?
|
|||
|
The <code class="docutils literal notranslate"><span class="pre">MODULE_FUNCTIONNAME_METHODDEF</span></code> macro won’t be defined either!</p>
|
|||
|
<p>Here’s where Argument Clinic gets very clever. It actually detects that the
|
|||
|
Argument Clinic block might be deactivated by the <code class="docutils literal notranslate"><span class="pre">#ifdef</span></code>. When that
|
|||
|
happens, it generates a little extra code that looks like this:</p>
|
|||
|
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#ifndef MODULE_FUNCTIONNAME_METHODDEF</span>
|
|||
|
<span class="cp">#define MODULE_FUNCTIONNAME_METHODDEF</span>
|
|||
|
<span class="cp">#endif </span><span class="cm">/* !defined(MODULE_FUNCTIONNAME_METHODDEF) */</span><span class="cp"></span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>That means the macro always works. If the function is defined, this turns
|
|||
|
into the correct structure, including the trailing comma. If the function is
|
|||
|
undefined, this turns into nothing.</p>
|
|||
|
<p>However, this causes one ticklish problem: where should Argument Clinic put this
|
|||
|
extra code when using the “block” output preset? It can’t go in the output block,
|
|||
|
because that could be deactivated by the <code class="docutils literal notranslate"><span class="pre">#ifdef</span></code>. (That’s the whole point!)</p>
|
|||
|
<p>In this situation, Argument Clinic writes the extra code to the “buffer” destination.
|
|||
|
This may mean that you get a complaint from Argument Clinic:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>Warning in file "Modules/posixmodule.c" on line 12357:
|
|||
|
Destination buffer 'buffer' not empty at end of file, emptying.
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>When this happens, just open your file, find the <code class="docutils literal notranslate"><span class="pre">dump</span> <span class="pre">buffer</span></code> block that
|
|||
|
Argument Clinic added to your file (it’ll be at the very bottom), then
|
|||
|
move it above the <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> structure where that macro is used.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="using-argument-clinic-in-python-files">
|
|||
|
<h3>Using Argument Clinic in Python files<a class="headerlink" href="#using-argument-clinic-in-python-files" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>It’s actually possible to use Argument Clinic to preprocess Python files.
|
|||
|
There’s no point to using Argument Clinic blocks, of course, as the output
|
|||
|
wouldn’t make any sense to the Python interpreter. But using Argument Clinic
|
|||
|
to run Python blocks lets you use Python as a Python preprocessor!</p>
|
|||
|
<p>Since Python comments are different from C comments, Argument Clinic
|
|||
|
blocks embedded in Python files look slightly different. They look like this:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1">#/*[python input]</span>
|
|||
|
<span class="c1">#print("def foo(): pass")</span>
|
|||
|
<span class="c1">#[python start generated code]*/</span>
|
|||
|
<span class="k">def</span> <span class="nf">foo</span><span class="p">():</span> <span class="k">pass</span>
|
|||
|
<span class="c1">#/*[python checksum:...]*/</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
|||
|
<div class="sphinxsidebarwrapper">
|
|||
|
<h3><a href="../contents.html">Table of Contents</a></h3>
|
|||
|
<ul>
|
|||
|
<li><a class="reference internal" href="#">Argument Clinic How-To</a><ul>
|
|||
|
<li><a class="reference internal" href="#the-goals-of-argument-clinic">The Goals Of Argument Clinic</a></li>
|
|||
|
<li><a class="reference internal" href="#basic-concepts-and-usage">Basic Concepts And Usage</a></li>
|
|||
|
<li><a class="reference internal" href="#converting-your-first-function">Converting Your First Function</a></li>
|
|||
|
<li><a class="reference internal" href="#advanced-topics">Advanced Topics</a><ul>
|
|||
|
<li><a class="reference internal" href="#symbolic-default-values">Symbolic default values</a></li>
|
|||
|
<li><a class="reference internal" href="#renaming-the-c-functions-and-variables-generated-by-argument-clinic">Renaming the C functions and variables generated by Argument Clinic</a></li>
|
|||
|
<li><a class="reference internal" href="#converting-functions-using-pyarg-unpacktuple">Converting functions using PyArg_UnpackTuple</a></li>
|
|||
|
<li><a class="reference internal" href="#optional-groups">Optional Groups</a></li>
|
|||
|
<li><a class="reference internal" href="#using-real-argument-clinic-converters-instead-of-legacy-converters">Using real Argument Clinic converters, instead of “legacy converters”</a></li>
|
|||
|
<li><a class="reference internal" href="#py-buffer">Py_buffer</a></li>
|
|||
|
<li><a class="reference internal" href="#advanced-converters">Advanced converters</a></li>
|
|||
|
<li><a class="reference internal" href="#parameter-default-values">Parameter default values</a></li>
|
|||
|
<li><a class="reference internal" href="#the-null-default-value">The <code class="docutils literal notranslate"><span class="pre">NULL</span></code> default value</a></li>
|
|||
|
<li><a class="reference internal" href="#expressions-specified-as-default-values">Expressions specified as default values</a></li>
|
|||
|
<li><a class="reference internal" href="#using-a-return-converter">Using a return converter</a></li>
|
|||
|
<li><a class="reference internal" href="#cloning-existing-functions">Cloning existing functions</a></li>
|
|||
|
<li><a class="reference internal" href="#calling-python-code">Calling Python code</a></li>
|
|||
|
<li><a class="reference internal" href="#using-a-self-converter">Using a “self converter”</a></li>
|
|||
|
<li><a class="reference internal" href="#writing-a-custom-converter">Writing a custom converter</a></li>
|
|||
|
<li><a class="reference internal" href="#writing-a-custom-return-converter">Writing a custom return converter</a></li>
|
|||
|
<li><a class="reference internal" href="#meth-o-and-meth-noargs">METH_O and METH_NOARGS</a></li>
|
|||
|
<li><a class="reference internal" href="#tp-new-and-tp-init-functions">tp_new and tp_init functions</a></li>
|
|||
|
<li><a class="reference internal" href="#changing-and-redirecting-clinic-s-output">Changing and redirecting Clinic’s output</a></li>
|
|||
|
<li><a class="reference internal" href="#the-ifdef-trick">The #ifdef trick</a></li>
|
|||
|
<li><a class="reference internal" href="#using-argument-clinic-in-python-files">Using Argument Clinic in Python files</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h4>Previous topic</h4>
|
|||
|
<p class="topless"><a href="ipaddress.html"
|
|||
|
title="previous chapter">An introduction to the ipaddress module</a></p>
|
|||
|
<h4>Next topic</h4>
|
|||
|
<p class="topless"><a href="instrumentation.html"
|
|||
|
title="next chapter">Instrumenting CPython with DTrace and SystemTap</a></p>
|
|||
|
<div role="note" aria-label="source link">
|
|||
|
<h3>This Page</h3>
|
|||
|
<ul class="this-page-menu">
|
|||
|
<li><a href="../bugs.html">Report a Bug</a></li>
|
|||
|
<li>
|
|||
|
<a href="https://github.com/python/cpython/blob/3.7/Doc/howto/clinic.rst"
|
|||
|
rel="nofollow">Show Source
|
|||
|
</a>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="clearer"></div>
|
|||
|
</div>
|
|||
|
<div class="related" role="navigation" aria-label="related navigation">
|
|||
|
<h3>Navigation</h3>
|
|||
|
<ul>
|
|||
|
<li class="right" style="margin-right: 10px">
|
|||
|
<a href="../genindex.html" title="General Index"
|
|||
|
>index</a></li>
|
|||
|
<li class="right" >
|
|||
|
<a href="../py-modindex.html" title="Python Module Index"
|
|||
|
>modules</a> |</li>
|
|||
|
<li class="right" >
|
|||
|
<a href="instrumentation.html" title="Instrumenting CPython with DTrace and SystemTap"
|
|||
|
>next</a> |</li>
|
|||
|
<li class="right" >
|
|||
|
<a href="ipaddress.html" title="An introduction to the ipaddress module"
|
|||
|
>previous</a> |</li>
|
|||
|
<li><img src="../_static/py.png" alt=""
|
|||
|
style="vertical-align: middle; margin-top: -1px"/></li>
|
|||
|
<li><a href="https://www.python.org/">Python</a> »</li>
|
|||
|
<li>
|
|||
|
<span class="language_switcher_placeholder">en</span>
|
|||
|
<span class="version_switcher_placeholder">3.7.4</span>
|
|||
|
<a href="../index.html">Documentation </a> »
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
|||
|
<li class="right">
|
|||
|
|
|||
|
|
|||
|
<div class="inline-search" style="display: none" role="search">
|
|||
|
<form class="inline-search" action="../search.html" method="get">
|
|||
|
<input placeholder="Quick search" type="text" name="q" />
|
|||
|
<input type="submit" value="Go" />
|
|||
|
<input type="hidden" name="check_keywords" value="yes" />
|
|||
|
<input type="hidden" name="area" value="default" />
|
|||
|
</form>
|
|||
|
</div>
|
|||
|
<script type="text/javascript">$('.inline-search').show(0);</script>
|
|||
|
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<div class="footer">
|
|||
|
© <a href="../copyright.html">Copyright</a> 2001-2019, Python Software Foundation.
|
|||
|
<br />
|
|||
|
The Python Software Foundation is a non-profit corporation.
|
|||
|
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
|||
|
<br />
|
|||
|
Last updated on Jul 13, 2019.
|
|||
|
<a href="../bugs.html">Found a bug</a>?
|
|||
|
<br />
|
|||
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 2.0.1.
|
|||
|
</div>
|
|||
|
|
|||
|
</body>
|
|||
|
</html>
|