2134 lines
163 KiB
HTML
2134 lines
163 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
<meta property="og:title" content="Argument Clinic How-To" />
|
||
<meta property="og:type" content="website" />
|
||
<meta property="og:url" content="https://docs.python.org/3/howto/clinic.html" />
|
||
<meta property="og:site_name" content="Python documentation" />
|
||
<meta property="og:description" content="author, Larry Hastings,. Source code: Tools/clinic/clinic.py. Abstract: Argument Clinic is a preprocessor for CPython C files. It was introduced in Python 3.4 with PEP 436, in order to provide intr..." />
|
||
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
|
||
<meta property="og:image:alt" content="Python documentation" />
|
||
<meta name="description" content="author, Larry Hastings,. Source code: Tools/clinic/clinic.py. Abstract: Argument Clinic is a preprocessor for CPython C files. It was introduced in Python 3.4 with PEP 436, in order to provide intr..." />
|
||
<meta property="og:image:width" content="200" />
|
||
<meta property="og:image:height" content="200" />
|
||
<meta name="theme-color" content="#3776ab" />
|
||
|
||
<title>Argument Clinic How-To — Python 3.12.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
|
||
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
|
||
|
||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
|
||
<script src="../_static/sidebar.js"></script>
|
||
|
||
<link rel="search" type="application/opensearchdescription+xml"
|
||
title="Search within Python 3.12.0 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="canonical" href="https://docs.python.org/3/howto/clinic.html" />
|
||
|
||
|
||
|
||
|
||
|
||
<style>
|
||
@media only screen {
|
||
table.full-width-table {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
<link rel="stylesheet" href="../_static/pydoctheme_dark.css" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
|
||
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
|
||
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
||
<script type="text/javascript" src="../_static/menu.js"></script>
|
||
<script type="text/javascript" src="../_static/themetoggle.js"></script>
|
||
|
||
</head>
|
||
<body>
|
||
<div class="mobile-nav">
|
||
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
|
||
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
|
||
<nav class="nav-content" role="navigation">
|
||
<label for="menuToggler" class="toggler__label">
|
||
<span></span>
|
||
</label>
|
||
<span class="nav-items-wrapper">
|
||
<a href="https://www.python.org/" class="nav-logo">
|
||
<img src="../_static/py.svg" alt="Logo"/>
|
||
</a>
|
||
<span class="version_switcher_placeholder"></span>
|
||
<form role="search" class="search" action="../search.html" method="get">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
|
||
<path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
|
||
</svg>
|
||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||
<input type="submit" value="Go"/>
|
||
</form>
|
||
</span>
|
||
</nav>
|
||
<div class="menu-wrapper">
|
||
<nav class="menu" role="navigation" aria-label="main navigation">
|
||
<div class="language_switcher_placeholder"></div>
|
||
|
||
<label class="theme-selector-label">
|
||
Theme
|
||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||
<option value="auto" selected>Auto</option>
|
||
<option value="light">Light</option>
|
||
<option value="dark">Dark</option>
|
||
</select>
|
||
</label>
|
||
<div>
|
||
<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="#background">Background</a><ul>
|
||
<li><a class="reference internal" href="#basic-concepts">Basic concepts</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#reference">Reference</a><ul>
|
||
<li><a class="reference internal" href="#terminology">Terminology</a></li>
|
||
<li><a class="reference internal" href="#command-line-interface">Command-line interface</a></li>
|
||
<li><a class="reference internal" href="#module-clinic">Classes for extending Argument Clinic</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#tutorial">Tutorial</a></li>
|
||
<li><a class="reference internal" href="#how-to-guides">How-to guides</a><ul>
|
||
<li><a class="reference internal" href="#how-to-rename-c-functions-and-variables-generated-by-argument-clinic">How to rename C functions and variables generated by Argument Clinic</a></li>
|
||
<li><a class="reference internal" href="#how-to-convert-functions-using-pyarg-unpacktuple">How to convert functions using <code class="docutils literal notranslate"><span class="pre">PyArg_UnpackTuple</span></code></a></li>
|
||
<li><a class="reference internal" href="#how-to-use-optional-groups">How to use optional groups</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-real-argument-clinic-converters-instead-of-legacy-converters">How to use real Argument Clinic converters, instead of “legacy converters”</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-the-py-buffer-converter">How to use the <code class="docutils literal notranslate"><span class="pre">Py_buffer</span></code> converter</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-advanced-converters">How to use advanced converters</a></li>
|
||
<li><a class="reference internal" href="#how-to-assign-default-values-to-parameter">How to assign default values to parameter</a><ul>
|
||
<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="#symbolic-default-values">Symbolic default values</a></li>
|
||
<li><a class="reference internal" href="#expressions-as-default-values">Expressions as default values</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#how-to-use-return-converters">How to use return converters</a></li>
|
||
<li><a class="reference internal" href="#how-to-clone-existing-functions">How to clone existing functions</a></li>
|
||
<li><a class="reference internal" href="#how-to-call-python-code">How to call Python code</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-the-self-converter">How to use the “self converter”</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-the-defining-class-converter">How to use the “defining class” converter</a></li>
|
||
<li><a class="reference internal" href="#how-to-write-a-custom-converter">How to write a custom converter</a></li>
|
||
<li><a class="reference internal" href="#how-to-write-a-custom-return-converter">How to write a custom return converter</a></li>
|
||
<li><a class="reference internal" href="#how-to-convert-meth-o-and-meth-noargs-functions">How to convert <code class="docutils literal notranslate"><span class="pre">METH_O</span></code> and <code class="docutils literal notranslate"><span class="pre">METH_NOARGS</span></code> functions</a></li>
|
||
<li><a class="reference internal" href="#how-to-convert-tp-new-and-tp-init-functions">How to 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</a></li>
|
||
<li><a class="reference internal" href="#how-to-change-and-redirect-clinic-s-output">How to change and redirect Clinic’s output</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-the-ifdef-trick">How to use the <code class="docutils literal notranslate"><span class="pre">#ifdef</span></code> trick</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-argument-clinic-in-python-files">How to use Argument Clinic in Python files</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
</div>
|
||
<div>
|
||
<h4>Previous topic</h4>
|
||
<p class="topless"><a href="ipaddress.html"
|
||
title="previous chapter">An introduction to the ipaddress module</a></p>
|
||
</div>
|
||
<div>
|
||
<h4>Next topic</h4>
|
||
<p class="topless"><a href="instrumentation.html"
|
||
title="next chapter">Instrumenting CPython with DTrace and SystemTap</a></p>
|
||
</div>
|
||
<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/main/Doc/howto/clinic.rst"
|
||
rel="nofollow">Show Source
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</nav>
|
||
</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"
|
||
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.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.12.0 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">Argument Clinic How-To</a></li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||
<input type="submit" value="Go" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
<li class="right">
|
||
<label class="theme-selector-label">
|
||
Theme
|
||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||
<option value="auto" selected>Auto</option>
|
||
<option value="light">Light</option>
|
||
<option value="dark">Dark</option>
|
||
</select>
|
||
</label> |</li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section id="argument-clinic-how-to">
|
||
<span id="howto-clinic"></span><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>
|
||
<p><strong>Source code:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/3.12/Tools/clinic/clinic.py">Tools/clinic/clinic.py</a>.</p>
|
||
<div class="topic">
|
||
<p class="topic-title">Abstract</p>
|
||
<p>Argument Clinic is a preprocessor for CPython C files.
|
||
It was introduced in Python 3.4 with <span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-0436/"><strong>PEP 436</strong></a>,
|
||
in order to provide introspection signatures,
|
||
and to generate performant and tailor-made boilerplate code
|
||
for argument parsing in CPython builtins,
|
||
module level functions, and class methods.
|
||
This document is divided in four major sections:</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="#clinic-background"><span class="std std-ref">Background</span></a> talks about the basic concepts and goals of
|
||
Argument Clinic.</p></li>
|
||
<li><p><a class="reference internal" href="#clinic-reference"><span class="std std-ref">Reference</span></a> describes the command-line interface and Argument
|
||
Clinic terminology.</p></li>
|
||
<li><p><a class="reference internal" href="#clinic-tutorial"><span class="std std-ref">Tutorial</span></a> guides you through all the steps required to
|
||
adapt an existing C function to Argument Clinic.</p></li>
|
||
<li><p><a class="reference internal" href="#clinic-howtos"><span class="std std-ref">How-to guides</span></a> details how to handle specific tasks.</p></li>
|
||
</ul>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>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>
|
||
<section id="background">
|
||
<span id="clinic-background"></span><h2>Background<a class="headerlink" href="#background" title="Permalink to this headline">¶</a></h2>
|
||
<section id="basic-concepts">
|
||
<h3>Basic concepts<a class="headerlink" href="#basic-concepts" title="Permalink to this headline">¶</a></h3>
|
||
<p>When Argument Clinic is run on a file, either via the <a class="reference internal" href="#clinic-cli"><span class="std std-ref">Command-line interface</span></a>
|
||
or via <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">clinic</span></code>, it will scan over the input files looking for
|
||
<a class="reference internal" href="#term-start-line"><span class="xref std std-term">start lines</span></a>:</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 the <a class="reference internal" href="#term-end-line"><span class="xref std std-term">end line</span></a>:</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 Argument Clinic <a class="reference internal" href="#term-input"><span class="xref std std-term">input</span></a>.
|
||
When Argument Clinic parses input, it generates <a class="reference internal" href="#term-output"><span class="xref std std-term">output</span></a>.
|
||
The output is rewritten into the C file immediately after the input,
|
||
followed by a <a class="reference internal" href="#term-checksum-line"><span class="xref std std-term">checksum line</span></a>.
|
||
All of these lines, including the <a class="reference internal" href="#term-start-line"><span class="xref std std-term">start line</span></a> and <a class="reference internal" href="#term-checksum-line"><span class="xref std std-term">checksum line</span></a>,
|
||
are collectively called an Argument Clinic <a class="reference internal" href="#term-block"><span class="xref std std-term">block</span></a>:</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: ...]*/
|
||
</pre></div>
|
||
</div>
|
||
<p>If you run Argument Clinic on the same file a second time, Argument Clinic
|
||
will discard the old <a class="reference internal" href="#term-output"><span class="xref std std-term">output</span></a> and write out the new output with a fresh
|
||
<a class="reference internal" href="#term-checksum-line"><span class="xref std std-term">checksum line</span></a>.
|
||
If the <a class="reference internal" href="#term-input"><span class="xref std std-term">input</span></a> hasn’t changed, the output won’t change either.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>You should never modify the output of an Argument Clinic block,
|
||
as any change will be lost in future Argument Clinic runs;
|
||
Argument Clinic will detect an output checksum mismatch and regenerate the
|
||
correct output.
|
||
If you are not happy with the generated output,
|
||
you should instead change the input until it produces the output you want.</p>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="reference">
|
||
<span id="clinic-reference"></span><h2>Reference<a class="headerlink" href="#reference" title="Permalink to this headline">¶</a></h2>
|
||
<section id="terminology">
|
||
<span id="clinic-terminology"></span><h3>Terminology<a class="headerlink" href="#terminology" title="Permalink to this headline">¶</a></h3>
|
||
<dl class="glossary simple">
|
||
<dt id="term-start-line">start line<a class="headerlink" href="#term-start-line" title="Permalink to this term">¶</a></dt><dd><p>The line <code class="docutils literal notranslate"><span class="pre">/*[clinic</span> <span class="pre">input]</span></code>.
|
||
This line marks the beginning of Argument Clinic input.
|
||
Note that the <em>start line</em> opens a C block comment.</p>
|
||
</dd>
|
||
<dt id="term-end-line">end line<a class="headerlink" href="#term-end-line" title="Permalink to this term">¶</a></dt><dd><p>The line <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>.
|
||
The <em>end line</em> marks the _end_ of Argument Clinic <a class="reference internal" href="#term-input"><span class="xref std std-term">input</span></a>,
|
||
but at the same time marks the _start_ of Argument Clinic <a class="reference internal" href="#term-output"><span class="xref std std-term">output</span></a>,
|
||
thus the text <em>“clinic start start generated code”</em>
|
||
Note that the <em>end line</em> closes the C block comment opened
|
||
by the <em>start line</em>.</p>
|
||
</dd>
|
||
<dt id="term-checksum">checksum<a class="headerlink" href="#term-checksum" title="Permalink to this term">¶</a></dt><dd><p>A hash to distinguish unique <a class="reference internal" href="#term-input"><span class="xref std std-term">inputs</span></a>
|
||
and <a class="reference internal" href="#term-output"><span class="xref std std-term">outputs</span></a>.</p>
|
||
</dd>
|
||
<dt id="term-checksum-line">checksum line<a class="headerlink" href="#term-checksum-line" title="Permalink to this term">¶</a></dt><dd><p>A line that looks like <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">...]*/</span></code>.
|
||
The three dots will be replaced by a <a class="reference internal" href="#term-checksum"><span class="xref std std-term">checksum</span></a> generated from the
|
||
<a class="reference internal" href="#term-input"><span class="xref std std-term">input</span></a>, and a <a class="reference internal" href="#term-checksum"><span class="xref std std-term">checksum</span></a> generated from the <a class="reference internal" href="#term-output"><span class="xref std std-term">output</span></a>.
|
||
The checksum line marks the end of Argument Clinic generated code,
|
||
and is used by Argument Clinic to determine if it needs to regenerate
|
||
output.</p>
|
||
</dd>
|
||
<dt id="term-input">input<a class="headerlink" href="#term-input" title="Permalink to this term">¶</a></dt><dd><p>The text between the <a class="reference internal" href="#term-start-line"><span class="xref std std-term">start line</span></a> and the <a class="reference internal" href="#term-end-line"><span class="xref std std-term">end line</span></a>.
|
||
Note that the start and end lines open and close a C block comment;
|
||
the <em>input</em> is thus a part of that same C block comment.</p>
|
||
</dd>
|
||
<dt id="term-output">output<a class="headerlink" href="#term-output" title="Permalink to this term">¶</a></dt><dd><p>The text between the <a class="reference internal" href="#term-end-line"><span class="xref std std-term">end line</span></a> and the <a class="reference internal" href="#term-checksum-line"><span class="xref std std-term">checksum line</span></a>.</p>
|
||
</dd>
|
||
<dt id="term-block">block<a class="headerlink" href="#term-block" title="Permalink to this term">¶</a></dt><dd><p>All text from the <a class="reference internal" href="#term-start-line"><span class="xref std std-term">start line</span></a> to the <a class="reference internal" href="#term-checksum-line"><span class="xref std std-term">checksum line</span></a> inclusively.</p>
|
||
</dd>
|
||
</dl>
|
||
</section>
|
||
<section id="command-line-interface">
|
||
<span id="clinic-cli"></span><h3>Command-line interface<a class="headerlink" href="#command-line-interface" title="Permalink to this headline">¶</a></h3>
|
||
<p>The Argument Clinic <abbr title="Command-Line Interface">CLI</abbr> is typically used to
|
||
process a single source file, like this:</p>
|
||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python3<span class="w"> </span>./Tools/clinic/clinic.py<span class="w"> </span>foo.c
|
||
</pre></div>
|
||
</div>
|
||
<p>The CLI supports the following options:</p>
|
||
<dl class="std option">
|
||
<dt class="sig sig-object std" id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-h">
|
||
<span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-h"></span><span id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-help"></span><span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-help"></span><span class="sig-name descname"><span class="pre">-h</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--help</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-h" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>Print CLI usage.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="std option">
|
||
<dt class="sig sig-object std" id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-f">
|
||
<span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-f"></span><span id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-force"></span><span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-force"></span><span class="sig-name descname"><span class="pre">-f</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--force</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-f" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>Force output regeneration.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="std option">
|
||
<dt class="sig sig-object std" id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-o">
|
||
<span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-o"></span><span id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-output"></span><span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-output"></span><span class="sig-name descname"><span class="pre">-o</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--output</span></span><span class="sig-prename descclassname"> <span class="pre">OUTPUT</span></span><a class="headerlink" href="#cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-o" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>Redirect file output to OUTPUT</p>
|
||
</dd></dl>
|
||
|
||
<dl class="std option">
|
||
<dt class="sig sig-object std" id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-v">
|
||
<span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-v"></span><span id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-verbose"></span><span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-verbose"></span><span class="sig-name descname"><span class="pre">-v</span></span><span class="sig-prename descclassname"></span><span class="sig-prename descclassname"><span class="pre">,</span> </span><span class="sig-name descname"><span class="pre">--verbose</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-v" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>Enable verbose mode.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="std option">
|
||
<dt class="sig sig-object std" id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-converters">
|
||
<span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-converters"></span><span class="sig-name descname"><span class="pre">--converters</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-converters" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>Print a list of all supported converters and return converters.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="std option">
|
||
<dt class="sig sig-object std" id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-make">
|
||
<span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-make"></span><span class="sig-name descname"><span class="pre">--make</span></span><span class="sig-prename descclassname"></span><a class="headerlink" href="#cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-make" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>Walk <a class="reference internal" href="#cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-srcdir"><code class="xref std std-option docutils literal notranslate"><span class="pre">--srcdir</span></code></a> to run over all relevant files.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="std option">
|
||
<dt class="sig sig-object std" id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-srcdir">
|
||
<span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-srcdir"></span><span class="sig-name descname"><span class="pre">--srcdir</span></span><span class="sig-prename descclassname"> <span class="pre">SRCDIR</span></span><a class="headerlink" href="#cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-srcdir" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>The directory tree to walk in <a class="reference internal" href="#cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-make"><code class="xref std std-option docutils literal notranslate"><span class="pre">--make</span></code></a> mode.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="std option">
|
||
<dt class="sig sig-object std" id="cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-arg-FILE">
|
||
<span id="cmdoption-tools-clinic-clinic-py-h-f-o-output-v-converters-make-srcdir-srcdir-file-arg-file"></span><span class="sig-name descname"><span class="pre">FILE</span></span><span class="sig-prename descclassname"> <span class="pre">...</span></span><a class="headerlink" href="#cmdoption-.-Tools-clinic-clinic.py-h-f-o-OUTPUT-v-converters-make-srcdir-SRCDIR-FILE-...-arg-FILE" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>The list of files to process.</p>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="module-clinic">
|
||
<span id="classes-for-extending-argument-clinic"></span><span id="clinic-classes"></span><h3>Classes for extending Argument Clinic<a class="headerlink" href="#module-clinic" title="Permalink to this headline">¶</a></h3>
|
||
<dl class="py class">
|
||
<dt class="sig sig-object py" id="clinic.CConverter">
|
||
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">clinic.</span></span><span class="sig-name descname"><span class="pre">CConverter</span></span><a class="headerlink" href="#clinic.CConverter" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>The base class for all converters.
|
||
See <a class="reference internal" href="#clinic-howto-custom-converter"><span class="std std-ref">How to write a custom converter</span></a> for how to subclass this class.</p>
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="clinic.CConverter.type">
|
||
<span class="sig-name descname"><span class="pre">type</span></span><a class="headerlink" href="#clinic.CConverter.type" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>The C type to use for this variable.
|
||
<code class="xref py py-attr 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></dl>
|
||
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="clinic.CConverter.default">
|
||
<span class="sig-name descname"><span class="pre">default</span></span><a class="headerlink" href="#clinic.CConverter.default" title="Permalink to this definition">¶</a></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></dl>
|
||
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="clinic.CConverter.py_default">
|
||
<span class="sig-name descname"><span class="pre">py_default</span></span><a class="headerlink" href="#clinic.CConverter.py_default" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p><code class="xref py py-attr 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></dl>
|
||
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="clinic.CConverter.c_default">
|
||
<span class="sig-name descname"><span class="pre">c_default</span></span><a class="headerlink" href="#clinic.CConverter.c_default" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p><code class="xref py py-attr 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></dl>
|
||
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="clinic.CConverter.c_ignored_default">
|
||
<span class="sig-name descname"><span class="pre">c_ignored_default</span></span><a class="headerlink" href="#clinic.CConverter.c_ignored_default" title="Permalink to this definition">¶</a></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></dl>
|
||
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="clinic.CConverter.converter">
|
||
<span class="sig-name descname"><span class="pre">converter</span></span><a class="headerlink" href="#clinic.CConverter.converter" title="Permalink to this definition">¶</a></dt>
|
||
<dd><p>The name of the C converter function, as a string.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="clinic.CConverter.impl_by_reference">
|
||
<span class="sig-name descname"><span class="pre">impl_by_reference</span></span><a class="headerlink" href="#clinic.CConverter.impl_by_reference" title="Permalink to this definition">¶</a></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></dl>
|
||
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="clinic.CConverter.parse_by_reference">
|
||
<span class="sig-name descname"><span class="pre">parse_by_reference</span></span><a class="headerlink" href="#clinic.CConverter.parse_by_reference" title="Permalink to this definition">¶</a></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>
|
||
|
||
</dd></dl>
|
||
|
||
</section>
|
||
</section>
|
||
<section id="tutorial">
|
||
<span id="clinic-tutorial"></span><h2>Tutorial<a class="headerlink" href="#tutorial" 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 <a class="reference internal" href="#clinic-howtos"><span class="std std-ref">advanced concepts</span></a>
|
||
you’ll see later on in the document,
|
||
like <a class="reference internal" href="#clinic-howto-return-converters"><span class="std std-ref">How to use return converters</span></a>
|
||
and <a class="reference internal" href="#clinic-howto-self-converter"><span class="std std-ref">How to use the “self converter”</span></a>.
|
||
But we’ll keep it simple for this walkthrough so you can learn.</p>
|
||
<p>First, make sure you’re working with a freshly updated checkout
|
||
of the CPython trunk.</p>
|
||
<p>Next, 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 this tutorial, we’ll be using
|
||
<a class="reference internal" href="../library/pickle.html#pickle.Pickler.dump" title="pickle.Pickler.dump"><code class="xref py py-meth docutils literal notranslate"><span class="pre">_pickle.Pickler.dump</span></code></a>.</p>
|
||
<p>If the call to the <code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_Parse*()</span></code> function uses any of the
|
||
following format units…:</p>
|
||
<blockquote>
|
||
<div><div class="highlight-none notranslate"><div class="highlight"><pre><span></span>O&
|
||
O!
|
||
es
|
||
es#
|
||
et
|
||
et#
|
||
</pre></div>
|
||
</div>
|
||
</div></blockquote>
|
||
<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.
|
||
(See <a class="reference internal" href="#clinic-howto-advanced-converters"><span class="std std-ref">How to use advanced converters</span></a> for those scenarios.)</p>
|
||
<p>Also, if the function has multiple calls to <code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code>
|
||
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
|
||
<code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_Parse*()</span></code> 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>
|
||
<p>Next, add the following boilerplate above the function,
|
||
creating our input 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>
|
||
<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 <a class="reference internal" href="../library/functions.html#help" title="help"><code class="xref py py-func docutils literal notranslate"><span class="pre">help()</span></code></a> on your builtin in the future,
|
||
the first line will be built automatically based on the function’s signature.</p>
|
||
<p>Example docstring summary line:</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>
|
||
<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.
|
||
(See <span class="target" id="index-1"></span><a class="pep reference external" href="https://peps.python.org/pep-0257/"><strong>PEP 257</strong></a> regarding docstring conventions.)</p>
|
||
<p>Our example docstring consists solely of a summary line, so the sample
|
||
code doesn’t have to change for this step.</p>
|
||
<p>Now, above the docstring, enter the name of the function, followed
|
||
by a blank line. This should be the Python name of the function,
|
||
and should be the full dotted path to the function —
|
||
it should start with the name of the module,
|
||
include any sub-modules, and if the function is a method on
|
||
a class it should include the class name too.</p>
|
||
<p>In our example, <code class="xref py py-mod docutils literal notranslate"><span class="pre">_pickle</span></code> is the module, <code class="xref py py-class docutils literal notranslate"><span class="pre">Pickler</span></code> is the class,
|
||
and <code class="xref py py-meth docutils literal notranslate"><span class="pre">dump()</span></code> is the method, so the name becomes
|
||
<code class="xref py py-meth docutils literal notranslate"><span class="pre">_pickle.Pickler.dump()</span></code>:</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>
|
||
<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 <code class="xref c c-type docutils literal notranslate"><span class="pre">PyTypeObject</span></code> for this class:</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>
|
||
<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.
|
||
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;
|
||
see <a class="reference internal" href="#clinic-howto-default-values"><span class="std std-ref">How to assign default values to parameter</span></a> for more information.</p>
|
||
<p>Next, 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 <a class="reference internal" href="../c-api/arg.html#c.PyArg_Parse" title="PyArg_Parse"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_Parse()</span></code></a> format argument and
|
||
specify <em>that</em> as its converter, as a quoted string.
|
||
The “format unit” is the formal name for the one-to-three
|
||
character substring of the <em>format</em> 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>
|
||
<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="xref py py-meth docutils literal notranslate"><span class="pre">_pickle.Pickler.dump()</span></code> has neither, so our sample is unchanged.</p>
|
||
<p>Next, 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 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 positional-only parameter,
|
||
indented the same as the parameter lines.</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>
|
||
<p>It can be helpful to write a per-parameter docstring for each parameter.
|
||
Since per-parameter docstrings are optional,
|
||
you can skip this step if you prefer.</p>
|
||
<p>Nevertheless, here’s how to add a per-parameter docstring.
|
||
The first line of the per-parameter docstring
|
||
must be indented further than the parameter definition.
|
||
The left margin of this first line establishes
|
||
the left margin for the whole per-parameter docstring;
|
||
all the text you write will be outdented by this amount.
|
||
You can write as much text as you like, across multiple lines if you wish.</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>
|
||
<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="file docutils literal notranslate"><span class="pre">.c.h</span></code> file has been generated!
|
||
Reload the file in your text editor to see the generated code:</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="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
|
||
<span class="n">_pickle_Pickler_dump</span><span class="p">(</span><span class="n">PicklerObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </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="file docutils literal notranslate"><span class="pre">.c.h</span></code>
|
||
file. You’ll need to include that in your original <code class="file 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="w"> </span><span class="cpf">"clinic/_pickle.c.h"</span>
|
||
</pre></div>
|
||
</div>
|
||
<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 <code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code> or
|
||
<code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code> 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, 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
|
||
<code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code> 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>
|
||
<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="w"> </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: input=..., output=...]*/</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="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
|
||
<span class="n">_pickle_Pickler_dump_impl</span><span class="p">(</span><span class="n">PicklerObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </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="w"> </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="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">self</span><span class="o">-></span><span class="n">write</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="n">PyErr_Format</span><span class="p">(</span><span class="n">PicklingError</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s">"Pickler.__init__() was not called by %s.__init__()"</span><span class="p">,</span>
|
||
<span class="w"> </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="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
|
||
<span class="w"> </span><span class="k">if</span><span class="w"> </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="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
|
||
<span class="w"> </span><span class="p">...</span>
|
||
</pre></div>
|
||
</div>
|
||
<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 <code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code> 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; when you
|
||
replace the existing static <code class="xref c c-type docutils literal notranslate"><span class="pre">PyMethodDef</span></code> 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="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">PyMethodDef</span><span class="w"> </span><span class="n">Pickler_methods</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="n">__PICKLE_PICKLER_DUMP_METHODDEF</span>
|
||
<span class="w"> </span><span class="n">__PICKLE_PICKLER_CLEAR_MEMO_METHODDEF</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">}</span><span class="w"> </span><span class="cm">/* sentinel */</span>
|
||
<span class="p">};</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Argument Clinic may generate new instances of <code class="docutils literal notranslate"><span class="pre">_Py_ID</span></code>. For example:</p>
|
||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="o">&</span><span class="n">_Py_ID</span><span class="p">(</span><span class="n">new_unique_py_id</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If it does, you’ll have to run <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">regen-global-objects</span></code>
|
||
to regenerate the list of precompiled identifiers at this point.</p>
|
||
<p>Finally, compile, then run the relevant portions of the regression-test suite.
|
||
This change should not introduce any new compile-time warnings or errors,
|
||
and there should be no externally visible change to Python’s behavior,
|
||
except for one difference: <a class="reference internal" href="../library/inspect.html#inspect.signature" title="inspect.signature"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.signature()</span></code></a> 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>
|
||
</section>
|
||
<section id="how-to-guides">
|
||
<span id="clinic-howtos"></span><h2>How-to guides<a class="headerlink" href="#how-to-guides" title="Permalink to this headline">¶</a></h2>
|
||
<section id="how-to-rename-c-functions-and-variables-generated-by-argument-clinic">
|
||
<h3>How to rename C functions and variables generated by Argument Clinic<a class="headerlink" href="#how-to-rename-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
|
||
<a class="reference internal" href="../library/pickle.html#pickle.Pickler.dump" title="pickle.Pickler.dump"><code class="xref py py-meth docutils literal notranslate"><span class="pre">pickle.Pickler.dump()</span></code></a>, 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="xref c c-func docutils literal notranslate"><span class="pre">pickler_dumper()</span></code>,
|
||
and the impl function would now be named <code class="xref c c-func 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 <em>file</em>, 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 <em>self</em> parameter too!</p>
|
||
</section>
|
||
<section id="how-to-convert-functions-using-pyarg-unpacktuple">
|
||
<h3>How to convert functions using <code class="docutils literal notranslate"><span class="pre">PyArg_UnpackTuple</span></code><a class="headerlink" href="#how-to-convert-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 <em>type</em> 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>
|
||
</section>
|
||
<section id="how-to-use-optional-groups">
|
||
<h3>How to use optional groups<a class="headerlink" href="#how-to-use-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 <code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code>, optional arguments, and default values,
|
||
it’s not always possible. Some of these legacy functions have
|
||
behaviors <code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTupleAndKeywords()</span></code> doesn’t directly support.
|
||
The most obvious example is the builtin function <a class="reference internal" href="../library/stdtypes.html#range" title="range"><code class="xref py py-func docutils literal notranslate"><span class="pre">range()</span></code></a>, which has
|
||
an optional argument on the <em>left</em> side of its required argument!
|
||
Another example is <a class="reference internal" href="../library/curses.html#curses.window.addch" title="curses.window.addch"><code class="xref py py-meth docutils literal notranslate"><span class="pre">curses.window.addch()</span></code></a>, which has a group of two
|
||
arguments that must always be specified together. (The arguments are
|
||
called <em>x</em> and <em>y</em>; if you call the function passing in <em>x</em>,
|
||
you must also pass in <em>y</em> — and if you don’t pass in <em>x</em> you may not
|
||
pass in <em>y</em> 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 <a class="reference internal" href="../library/curses.html#curses.window.addch" title="curses.window.addch"><code class="xref py py-meth docutils literal notranslate"><span class="pre">curses.window.addch()</span></code></a>
|
||
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>
|
||
</section>
|
||
<section id="how-to-use-real-argument-clinic-converters-instead-of-legacy-converters">
|
||
<h3>How to use real Argument Clinic converters, instead of “legacy converters”<a class="headerlink" href="#how-to-use-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><em>c_default</em></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><em>annotation</em></dt><dd><p>The annotation value for this parameter. Not currently supported,
|
||
because <span class="target" id="index-2"></span><a class="pep reference external" href="https://peps.python.org/pep-0008/"><strong>PEP 8</strong></a> mandates that the Python library may not use
|
||
annotations.</p>
|
||
</dd>
|
||
<dt><em>unused</em></dt><dd><p>Wrap the argument with <a class="reference internal" href="../c-api/intro.html#c.Py_UNUSED" title="Py_UNUSED"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_UNUSED</span></code></a> in the impl function signature.</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><em>accept</em></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><em>bitwise</em></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><em>converter</em></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><em>encoding</em></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><em>subclass_of</em></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><em>type</em></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><em>zeroes</em></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 <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>
|
||
<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-default">
|
||
<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">wchar_t</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">wchar_t(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">wchar_t(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">wchar_t(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>One advantage of real converters is that they’re more flexible than legacy
|
||
converters. For example, the <code class="docutils literal notranslate"><span class="pre">unsigned_int</span></code> converter (and all the
|
||
<code class="docutils literal notranslate"><span class="pre">unsigned_</span></code> converters) can be specified without <code class="docutils literal notranslate"><span class="pre">bitwise=True</span></code>. Their
|
||
default behavior performs range checking on the value, and they won’t accept
|
||
negative numbers. You just can’t do that with a legacy converter!</p>
|
||
<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>
|
||
</section>
|
||
<section id="how-to-use-the-py-buffer-converter">
|
||
<h3>How to use the <code class="docutils literal notranslate"><span class="pre">Py_buffer</span></code> converter<a class="headerlink" href="#how-to-use-the-py-buffer-converter" 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>
|
||
</section>
|
||
<section id="how-to-use-advanced-converters">
|
||
<span id="clinic-howto-advanced-converters"></span><h3>How to use advanced converters<a class="headerlink" href="#how-to-use-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 <em>converter</em> (for <code class="docutils literal notranslate"><span class="pre">O&</span></code>), <em>subclass_of</em> (for <code class="docutils literal notranslate"><span class="pre">O!</span></code>),
|
||
or <em>encoding</em> (for all the format units that start with <code class="docutils literal notranslate"><span class="pre">e</span></code>).</p>
|
||
<p>When using <em>subclass_of</em>, you may also want to use the other
|
||
custom argument for <code class="docutils literal notranslate"><span class="pre">object()</span></code>: <em>type</em>, 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 <a class="reference internal" href="../c-api/unicode.html#c.PyUnicode_Type" title="PyUnicode_Type"><code class="xref c c-var docutils literal notranslate"><span class="pre">PyUnicode_Type</span></code></a>, 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="xref c c-func docutils literal notranslate"><span class="pre">PyArg_Parse*()</span></code> call by hand, you could theoretically decide at runtime what
|
||
encoding string to pass to that call. 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>
|
||
</section>
|
||
<section id="how-to-assign-default-values-to-parameter">
|
||
<span id="default-values"></span><span id="clinic-howto-default-values"></span><h3>How to assign default values to parameter<a class="headerlink" href="#how-to-assign-default-values-to-parameter" 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>
|
||
<section id="the-null-default-value">
|
||
<h4>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></h4>
|
||
<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>
|
||
</section>
|
||
<section id="symbolic-default-values">
|
||
<h4>Symbolic default values<a class="headerlink" href="#symbolic-default-values" title="Permalink to this headline">¶</a></h4>
|
||
<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 <a class="reference internal" href="../library/sys.html#sys.maxsize" title="sys.maxsize"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.maxsize</span></code></a>, which must
|
||
start with the name of the module</p></li>
|
||
</ul>
|
||
<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>
|
||
</section>
|
||
<section id="expressions-as-default-values">
|
||
<h4>Expressions as default values<a class="headerlink" href="#expressions-as-default-values" title="Permalink to this headline">¶</a></h4>
|
||
<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><a class="reference internal" href="../library/sys.html#sys.maxsize" title="sys.maxsize"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.maxsize</span></code></a> 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="xref py py-attr 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
|
||
<a class="reference internal" href="../library/sys.html#sys.modules" title="sys.modules"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.modules</span></code></a>. That’s how it can find <a class="reference internal" href="../library/sys.html#sys.maxsize" title="sys.maxsize"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.maxsize</span></code></a> 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 <em>c_default</em> 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>
|
||
</section>
|
||
</section>
|
||
<section id="how-to-use-return-converters">
|
||
<span id="clinic-howto-return-converters"></span><h3>How to use return converters<a class="headerlink" href="#how-to-use-return-converters" title="Permalink to this headline">¶</a></h3>
|
||
<p>By default, the impl function Argument Clinic generates for you returns
|
||
<a class="reference internal" href="../c-api/structures.html#c.PyObject" title="PyObject"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code></a>.
|
||
But your C function often computes some C type,
|
||
then converts it into the <code class="xref c c-type 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="xref c c-type 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, using <code class="docutils literal notranslate"><span class="pre">-></span></code> notation.</p>
|
||
<p>For example:</p>
|
||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
||
<span class="cm">add -> int</span>
|
||
|
||
<span class="cm"> a: int</span>
|
||
<span class="cm"> b: int</span>
|
||
<span class="cm"> /</span>
|
||
|
||
<span class="cm">[clinic start generated code]*/</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>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 (c:func:<cite>PyErr_Occurred</cite> 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
|
||
double
|
||
float
|
||
int
|
||
long
|
||
Py_ssize_t
|
||
size_t
|
||
unsigned int
|
||
unsigned long
|
||
</pre></div>
|
||
</div>
|
||
<p>None of these take parameters.
|
||
For all of these, return <code class="docutils literal notranslate"><span class="pre">-1</span></code> to indicate error.</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>
|
||
</section>
|
||
<section id="how-to-clone-existing-functions">
|
||
<h3>How to clone existing functions<a class="headerlink" href="#how-to-clone-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>
|
||
</section>
|
||
<section id="how-to-call-python-code">
|
||
<h3>How to call Python code<a class="headerlink" href="#how-to-call-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="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">__ignored_unused_variable__</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
|
||
<span class="cm">/*[python checksum:...]*/</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="how-to-use-the-self-converter">
|
||
<span id="clinic-howto-self-converter"></span><h3>How to use the “self converter”<a class="headerlink" href="#how-to-use-the-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 <em>self</em> parameter as the first parameter in a
|
||
block, and ensure that its converter is an instance of
|
||
<code class="xref py py-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 <em>type</em> 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="xref py py-class docutils literal notranslate"><span class="pre">self_converter</span></code> but overwriting the <code class="xref py py-attr 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>
|
||
</section>
|
||
<section id="how-to-use-the-defining-class-converter">
|
||
<h3>How to use the “defining class” converter<a class="headerlink" href="#how-to-use-the-defining-class-converter" title="Permalink to this headline">¶</a></h3>
|
||
<p>Argument Clinic facilitates gaining access to the defining class of a method.
|
||
This is useful for <a class="reference internal" href="../c-api/typeobj.html#heap-types"><span class="std std-ref">heap type</span></a> methods that need to fetch
|
||
module level state. Use <a class="reference internal" href="../c-api/type.html#c.PyType_FromModuleAndSpec" title="PyType_FromModuleAndSpec"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_FromModuleAndSpec()</span></code></a> to associate a new
|
||
heap type with a module. You can now use <a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleState" title="PyType_GetModuleState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleState()</span></code></a> on
|
||
the defining class to fetch the module state, for example from a module method.</p>
|
||
<p>Example from <a class="reference external" href="https://github.com/python/cpython/tree/3.12/Modules/zlibmodule.c">Modules/zlibmodule.c</a>.
|
||
First, <code class="docutils literal notranslate"><span class="pre">defining_class</span></code> is added to the clinic input:</p>
|
||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic input]</span>
|
||
<span class="cm">zlib.Compress.compress</span>
|
||
|
||
<span class="cm"> cls: defining_class</span>
|
||
<span class="cm"> data: Py_buffer</span>
|
||
<span class="cm"> Binary data to be compressed.</span>
|
||
<span class="cm"> /</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>After running the Argument Clinic tool, the following function signature is
|
||
generated:</p>
|
||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/*[clinic start generated code]*/</span>
|
||
<span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
|
||
<span class="n">zlib_Compress_compress_impl</span><span class="p">(</span><span class="n">compobject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">cls</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="n">Py_buffer</span><span class="w"> </span><span class="o">*</span><span class="n">data</span><span class="p">)</span>
|
||
<span class="cm">/*[clinic end generated code: output=6731b3f0ff357ca6 input=04d00f65ab01d260]*/</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The following code can now use <code class="docutils literal notranslate"><span class="pre">PyType_GetModuleState(cls)</span></code> to fetch the
|
||
module state:</p>
|
||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">zlibstate</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyType_GetModuleState</span><span class="p">(</span><span class="n">cls</span><span class="p">);</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Each method may only have one argument using this converter, and it must appear
|
||
after <code class="docutils literal notranslate"><span class="pre">self</span></code>, or, if <code class="docutils literal notranslate"><span class="pre">self</span></code> is not used, as the first argument. The argument
|
||
will be of type <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span> <span class="pre">*</span></code>. The argument will not appear in the
|
||
<code class="xref py py-attr docutils literal notranslate"><span class="pre">__text_signature__</span></code>.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">defining_class</span></code> converter is not compatible with <code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code>
|
||
and <code class="xref py py-meth docutils literal notranslate"><span class="pre">__new__()</span></code> methods, which cannot use the <a class="reference internal" href="../c-api/structures.html#c.METH_METHOD" title="METH_METHOD"><code class="xref c c-macro docutils literal notranslate"><span class="pre">METH_METHOD</span></code></a>
|
||
convention.</p>
|
||
<p>It is not possible to use <code class="docutils literal notranslate"><span class="pre">defining_class</span></code> with slot methods. In order to
|
||
fetch the module state from such methods, use <a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleByDef" title="PyType_GetModuleByDef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleByDef()</span></code></a>
|
||
to look up the module and then <a class="reference internal" href="../c-api/module.html#c.PyModule_GetState" title="PyModule_GetState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyModule_GetState()</span></code></a> to fetch the module
|
||
state. Example from the <code class="docutils literal notranslate"><span class="pre">setattro</span></code> slot method in
|
||
<a class="reference external" href="https://github.com/python/cpython/tree/3.12/Modules/_threadmodule.c">Modules/_threadmodule.c</a>:</p>
|
||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="kt">int</span>
|
||
<span class="nf">local_setattro</span><span class="p">(</span><span class="n">localobject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">v</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">module</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyType_GetModuleByDef</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="w"> </span><span class="o">&</span><span class="n">thread_module</span><span class="p">);</span>
|
||
<span class="w"> </span><span class="n">thread_module_state</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_thread_state</span><span class="p">(</span><span class="n">module</span><span class="p">);</span>
|
||
<span class="w"> </span><span class="p">...</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>See also <span class="target" id="index-3"></span><a class="pep reference external" href="https://peps.python.org/pep-0573/"><strong>PEP 573</strong></a>.</p>
|
||
</section>
|
||
<section id="how-to-write-a-custom-converter">
|
||
<span id="clinic-howto-custom-converter"></span><h3>How to write a custom converter<a class="headerlink" href="#how-to-write-a-custom-converter" title="Permalink to this headline">¶</a></h3>
|
||
<p>A converter is a Python class that inherits from <a class="reference internal" href="#clinic.CConverter" title="clinic.CConverter"><code class="xref py py-class docutils literal notranslate"><span class="pre">CConverter</span></code></a>.
|
||
The main purpose of a custom converter, is for parameters parsed with
|
||
the <code class="docutils literal notranslate"><span class="pre">O&</span></code> format unit — parsing such a 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="samp docutils literal notranslate"><em><span class="pre">ConverterName</span></em><span class="pre">_converter</span></code>.
|
||
By following this convention, your converter class will be automatically
|
||
registered with Argument Clinic, with its <em>converter name</em> being the name of
|
||
your converter class with the <code class="docutils literal notranslate"><span class="pre">_converter</span></code> suffix stripped off.</p>
|
||
<p>Instead of subclassing <code class="xref py py-meth docutils literal notranslate"><span class="pre">CConverter.__init__()</span></code>,
|
||
write a <code class="xref py py-meth docutils literal notranslate"><span class="pre">converter_init()</span></code> method.
|
||
<code class="xref py py-meth docutils literal notranslate"><span class="pre">converter_init()</span></code> always accepts a <em>self</em> parameter.
|
||
After <em>self</em>, all additional parameters <strong>must</strong> be keyword-only.
|
||
Any arguments passed to the converter in Argument Clinic
|
||
will be passed along to your <code class="xref py py-meth docutils literal notranslate"><span class="pre">converter_init()</span></code> method.
|
||
See <a class="reference internal" href="#clinic.CConverter" title="clinic.CConverter"><code class="xref py py-class docutils literal notranslate"><span class="pre">CConverter</span></code></a> for a list of members you may wish to specify in
|
||
your subclass.</p>
|
||
<p>Here’s the simplest example of a custom converter, from <a class="reference external" href="https://github.com/python/cpython/tree/3.12/Modules/zlibmodule.c">Modules/zlibmodule.c</a>:</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 named <code class="docutils literal notranslate"><span class="pre">ssize_t</span></code> to Argument Clinic.
|
||
Parameters declared as <code class="docutils literal notranslate"><span class="pre">ssize_t</span></code> will be declared with type <a class="reference internal" href="../c-api/intro.html#c.Py_ssize_t" title="Py_ssize_t"><code class="xref c c-type docutils literal notranslate"><span class="pre">Py_ssize_t</span></code></a>,
|
||
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="xref c c-func docutils literal notranslate"><span class="pre">ssize_t_converter()</span></code> converter C 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>
|
||
</section>
|
||
<section id="how-to-write-a-custom-return-converter">
|
||
<h3>How to write a custom return converter<a class="headerlink" href="#how-to-write-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="xref py py-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 <a class="reference external" href="https://github.com/python/cpython/tree/3.12/Tools/clinic/clinic.py">Tools/clinic/clinic.py</a>,
|
||
specifically the implementation of <code class="xref py py-class docutils literal notranslate"><span class="pre">CReturnConverter</span></code> and
|
||
all its subclasses.</p>
|
||
</section>
|
||
<section id="how-to-convert-meth-o-and-meth-noargs-functions">
|
||
<h3>How to convert <code class="docutils literal notranslate"><span class="pre">METH_O</span></code> and <code class="docutils literal notranslate"><span class="pre">METH_NOARGS</span></code> functions<a class="headerlink" href="#how-to-convert-meth-o-and-meth-noargs-functions" title="Permalink to this headline">¶</a></h3>
|
||
<p>To convert a function using <a class="reference internal" href="../c-api/structures.html#c.METH_O" title="METH_O"><code class="xref c c-macro docutils literal notranslate"><span class="pre">METH_O</span></code></a>, 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 <a class="reference internal" href="../c-api/structures.html#c.METH_NOARGS" title="METH_NOARGS"><code class="xref c c-macro docutils literal notranslate"><span class="pre">METH_NOARGS</span></code></a>, just don’t specify
|
||
any arguments.</p>
|
||
<p>You can still use a self converter, a return converter, and specify
|
||
a <em>type</em> argument to the object converter for <a class="reference internal" href="../c-api/structures.html#c.METH_O" title="METH_O"><code class="xref c c-macro docutils literal notranslate"><span class="pre">METH_O</span></code></a>.</p>
|
||
</section>
|
||
<section id="how-to-convert-tp-new-and-tp-init-functions">
|
||
<h3>How to 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<a class="headerlink" href="#how-to-convert-tp-new-and-tp-init-functions" title="Permalink to this headline">¶</a></h3>
|
||
<p>You can convert <a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_new" title="PyTypeObject.tp_new"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_new</span></code></a> and
|
||
<a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_init" title="PyTypeObject.tp_init"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_init</span></code></a> 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 <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> <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>
|
||
</section>
|
||
<section id="how-to-change-and-redirect-clinic-s-output">
|
||
<h3>How to change and redirect Clinic’s output<a class="headerlink" href="#how-to-change-and-redirect-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 <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
|
||
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="file docutils literal notranslate"><span class="pre">_pickle.c</span></code> would be written to
|
||
<code class="file 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>
|
||
</section>
|
||
<section id="how-to-use-the-ifdef-trick">
|
||
<h3>How to use the <code class="docutils literal notranslate"><span class="pre">#ifdef</span></code> trick<a class="headerlink" href="#how-to-use-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="w"> </span><span class="n">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>
|
||
</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="w"> </span><span class="n">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>
|
||
</pre></div>
|
||
</div>
|
||
<p>Then, remove those three lines from 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,
|
||
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="w"> </span><span class="cp">#define MODULE_FUNCTIONNAME_METHODDEF</span>
|
||
<span class="cp">#endif </span><span class="cm">/* !defined(MODULE_FUNCTIONNAME_METHODDEF) */</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 <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 where that macro is used.</p>
|
||
</section>
|
||
<section id="how-to-use-argument-clinic-in-python-files">
|
||
<h3>How to use Argument Clinic in Python files<a class="headerlink" href="#how-to-use-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>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
<div class="clearer"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<div>
|
||
<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="#background">Background</a><ul>
|
||
<li><a class="reference internal" href="#basic-concepts">Basic concepts</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#reference">Reference</a><ul>
|
||
<li><a class="reference internal" href="#terminology">Terminology</a></li>
|
||
<li><a class="reference internal" href="#command-line-interface">Command-line interface</a></li>
|
||
<li><a class="reference internal" href="#module-clinic">Classes for extending Argument Clinic</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#tutorial">Tutorial</a></li>
|
||
<li><a class="reference internal" href="#how-to-guides">How-to guides</a><ul>
|
||
<li><a class="reference internal" href="#how-to-rename-c-functions-and-variables-generated-by-argument-clinic">How to rename C functions and variables generated by Argument Clinic</a></li>
|
||
<li><a class="reference internal" href="#how-to-convert-functions-using-pyarg-unpacktuple">How to convert functions using <code class="docutils literal notranslate"><span class="pre">PyArg_UnpackTuple</span></code></a></li>
|
||
<li><a class="reference internal" href="#how-to-use-optional-groups">How to use optional groups</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-real-argument-clinic-converters-instead-of-legacy-converters">How to use real Argument Clinic converters, instead of “legacy converters”</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-the-py-buffer-converter">How to use the <code class="docutils literal notranslate"><span class="pre">Py_buffer</span></code> converter</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-advanced-converters">How to use advanced converters</a></li>
|
||
<li><a class="reference internal" href="#how-to-assign-default-values-to-parameter">How to assign default values to parameter</a><ul>
|
||
<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="#symbolic-default-values">Symbolic default values</a></li>
|
||
<li><a class="reference internal" href="#expressions-as-default-values">Expressions as default values</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#how-to-use-return-converters">How to use return converters</a></li>
|
||
<li><a class="reference internal" href="#how-to-clone-existing-functions">How to clone existing functions</a></li>
|
||
<li><a class="reference internal" href="#how-to-call-python-code">How to call Python code</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-the-self-converter">How to use the “self converter”</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-the-defining-class-converter">How to use the “defining class” converter</a></li>
|
||
<li><a class="reference internal" href="#how-to-write-a-custom-converter">How to write a custom converter</a></li>
|
||
<li><a class="reference internal" href="#how-to-write-a-custom-return-converter">How to write a custom return converter</a></li>
|
||
<li><a class="reference internal" href="#how-to-convert-meth-o-and-meth-noargs-functions">How to convert <code class="docutils literal notranslate"><span class="pre">METH_O</span></code> and <code class="docutils literal notranslate"><span class="pre">METH_NOARGS</span></code> functions</a></li>
|
||
<li><a class="reference internal" href="#how-to-convert-tp-new-and-tp-init-functions">How to 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</a></li>
|
||
<li><a class="reference internal" href="#how-to-change-and-redirect-clinic-s-output">How to change and redirect Clinic’s output</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-the-ifdef-trick">How to use the <code class="docutils literal notranslate"><span class="pre">#ifdef</span></code> trick</a></li>
|
||
<li><a class="reference internal" href="#how-to-use-argument-clinic-in-python-files">How to use Argument Clinic in Python files</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
</div>
|
||
<div>
|
||
<h4>Previous topic</h4>
|
||
<p class="topless"><a href="ipaddress.html"
|
||
title="previous chapter">An introduction to the ipaddress module</a></p>
|
||
</div>
|
||
<div>
|
||
<h4>Next topic</h4>
|
||
<p class="topless"><a href="instrumentation.html"
|
||
title="next chapter">Instrumenting CPython with DTrace and SystemTap</a></p>
|
||
</div>
|
||
<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/main/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.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.12.0 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">Argument Clinic How-To</a></li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||
<input type="submit" value="Go" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
<li class="right">
|
||
<label class="theme-selector-label">
|
||
Theme
|
||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||
<option value="auto" selected>Auto</option>
|
||
<option value="light">Light</option>
|
||
<option value="dark">Dark</option>
|
||
</select>
|
||
</label> |</li>
|
||
|
||
</ul>
|
||
</div>
|
||
<div class="footer">
|
||
© <a href="../copyright.html">Copyright</a> 2001-2023, Python Software Foundation.
|
||
<br />
|
||
This page is licensed under the Python Software Foundation License Version 2.
|
||
<br />
|
||
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
|
||
<br />
|
||
See <a href="/license.html">History and License</a> for more information.<br />
|
||
<br />
|
||
|
||
The Python Software Foundation is a non-profit corporation.
|
||
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
||
<br />
|
||
<br />
|
||
|
||
Last updated on Oct 02, 2023.
|
||
<a href="/bugs.html">Found a bug</a>?
|
||
<br />
|
||
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.5.0.
|
||
</div>
|
||
|
||
</body>
|
||
</html> |