CINXE.COM

PEP 727 – Documentation in Annotated Metadata | peps.python.org

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 727 – Documentation in Annotated Metadata | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0727/"> <link rel="stylesheet" href="../_static/style.css" type="text/css"> <link rel="stylesheet" href="../_static/mq.css" type="text/css"> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light"> <link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark"> <link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss"> <meta property="og:title" content='PEP 727 – Documentation in Annotated Metadata | peps.python.org'> <meta property="og:description" content="This PEP proposes a standardized way to provide documentation strings for Python symbols defined with Annotated using a new class typing.Doc."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0727/"> <meta property="og:site_name" content="Python Enhancement Proposals (PEPs)"> <meta property="og:image" content="https://peps.python.org/_static/og-image.png"> <meta property="og:image:alt" content="Python PEPs"> <meta property="og:image:width" content="200"> <meta property="og:image:height" content="200"> <meta name="description" content="This PEP proposes a standardized way to provide documentation strings for Python symbols defined with Annotated using a new class typing.Doc."> <meta name="theme-color" content="#3776ab"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all"> <title>Following system colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="9"></circle> <path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path> </svg> </symbol> <symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all"> <title>Selected dark colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path> </svg> </symbol> <symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all"> <title>Selected light colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </symbol> </svg> <script> document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto" </script> <section id="pep-page-section"> <header> <h1>Python Enhancement Proposals</h1> <ul class="breadcrumbs"> <li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li> <li><a href="../pep-0000/">PEP Index</a> &raquo; </li> <li>PEP 727</li> </ul> <button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())"> <svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg> <span class="visually-hidden">Toggle light / dark / auto colour theme</span> </button> </header> <article> <section id="pep-content"> <h1 class="page-title">PEP 727 – Documentation in Annotated Metadata</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Sebastián Ramírez &lt;tiangolo&#32;&#97;t&#32;gmail.com&gt;</dd> <dt class="field-even">Sponsor<span class="colon">:</span></dt> <dd class="field-even">Jelle Zijlstra &lt;jelle.zijlstra&#32;&#97;t&#32;gmail.com&gt;</dd> <dt class="field-odd">Discussions-To<span class="colon">:</span></dt> <dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/32566">Discourse thread</a></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Proposal under active discussion and revision">Draft</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Topic<span class="colon">:</span></dt> <dd class="field-even"><a class="reference external" href="../topic/typing/">Typing</a></dd> <dt class="field-odd">Created<span class="colon">:</span></dt> <dd class="field-odd">28-Aug-2023</dd> <dt class="field-even">Python-Version<span class="colon">:</span></dt> <dd class="field-even">3.13</dd> <dt class="field-odd">Post-History<span class="colon">:</span></dt> <dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/32566" title="Discourse thread">30-Aug-2023</a></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#motivation">Motivation</a></li> <li><a class="reference internal" href="#rationale">Rationale</a><ul> <li><a class="reference internal" href="#summary">Summary</a></li> </ul> </li> <li><a class="reference internal" href="#specification">Specification</a><ul> <li><a class="reference internal" href="#examples">Examples</a></li> </ul> </li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#security-implications">Security Implications</a></li> <li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li> <li><a class="reference internal" href="#survey-of-other-languages">Survey of Other languages</a><ul> <li><a class="reference internal" href="#java">Java</a></li> <li><a class="reference internal" href="#javascript">JavaScript</a></li> <li><a class="reference internal" href="#typescript">TypeScript</a></li> <li><a class="reference internal" href="#rust">Rust</a></li> <li><a class="reference internal" href="#go-lang">Go Lang</a></li> </ul> </li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul> <li><a class="reference internal" href="#standardize-current-docstrings">Standardize Current Docstrings</a></li> <li><a class="reference internal" href="#extra-metadata-and-decorator">Extra Metadata and Decorator</a></li> <li><a class="reference internal" href="#string-under-definition">String Under Definition</a></li> <li><a class="reference internal" href="#plain-string-in-annotated">Plain String in Annotated</a></li> <li><a class="reference internal" href="#another-annotated-like-type">Another Annotated-Like Type</a></li> <li><a class="reference internal" href="#transferring-documentation-from-type-aliases">Transferring Documentation from Type aliases</a></li> <li><a class="reference internal" href="#shorthand-with-slices">Shorthand with Slices</a></li> </ul> </li> <li><a class="reference internal" href="#open-issues">Open Issues</a><ul> <li><a class="reference internal" href="#verbosity">Verbosity</a></li> <li><a class="reference internal" href="#documentation-is-not-typing">Documentation is not Typing</a></li> <li><a class="reference internal" href="#multiple-standards">Multiple Standards</a></li> <li><a class="reference internal" href="#adoption">Adoption</a></li> </ul> </li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>This PEP proposes a standardized way to provide documentation strings for Python symbols defined with <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> using a new class <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code>.</p> </section> <section id="motivation"> <h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2> <p>There’s already a well-defined way to provide documentation for classes, functions, class methods, and modules: using docstrings.</p> <p>Currently there is no formalized standard to provide documentation strings for other types of symbols: parameters, return values, class-scoped variables (class variables and instance variables), local variables, and type aliases.</p> <p>Nevertheless, to allow documenting most of these additional symbols, several conventions have been created as microsyntaxes inside of docstrings, and are currently commonly used: Sphinx, numpydoc, Google, Keras, etc.</p> <p>There are two scenarios in which these conventions would be supported by tools: for authors, while <strong>editing</strong> the contents of the documentation strings and for users, while <strong>rendering</strong> that content in some way (in documentation sites, tooltips in editors, etc).</p> <p>Because each of these conventions uses a microsyntax inside a string, when <strong>editing</strong> those docstrings, editors can’t easily provide support for autocompletion, inline errors for broken syntax, etc. Any type of <strong>editing</strong> support for these conventions would be on top of the support for editing standard Python syntax.</p> <p>When documenting parameters with current conventions, because the docstring is in a different place in the code than the actual parameters and it requires duplication of information (the parameter name) the information about a parameter is easily in a place in the code quite far away from the declaration of the actual parameter and it is disconnected from it. This means it’s easy to refactor a function, remove a parameter, and forget to remove its docs. The same happens when adding a new parameter: it’s easy to forget to add the docstring for it.</p> <p>And because of this same duplication of information (the parameter name) editors and other tools need complex custom logic to check or ensure the consistency of the parameters in the signature and in their docstring, or they simply don’t fully support that.</p> <p>As these existing conventions are different types of microsyntaxes inside of strings, robustly parsing them for <strong>rendering</strong> requires complex logic that needs to be implemented by the tools supporting them. Additionally, libraries and tools don’t have a straightforward way to obtain the documentation for each individual parameter or variable at runtime, without depending on a specific docstring convention parser. Accessing the parameter documentation strings at runtime would be useful, for example, for testing the contents of each parameter’s documentation, to ensure consistency across several similar functions, or to extract and expose that same parameter documentation in some other way (e.g. an API with FastAPI, a CLI with Typer, etc).</p> <p>Some of these previous formats tried to account for the lack of type annotations in older Python versions by including typing information in the docstrings (e.g. <a class="reference external" href="https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#info-field-lists">Sphinx</a>, <a class="reference external" href="https://numpydoc.readthedocs.io/en/latest/format.html#parameters">numpydoc</a>) but now that information doesn’t need to be in docstrings as there is now an official <a class="pep reference internal" href="../pep-0484/" title="PEP 484 – Type Hints">syntax for type annotations</a>.</p> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>This proposal intends to address these shortcomings by extending and complementing the information in docstrings, keeping backwards compatibility with existing docstrings (it doesn’t deprecate them), and doing it in a way that leverages the Python language and structure, via type annotations with <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code>, and a new class <code class="docutils literal notranslate"><span class="pre">Doc</span></code> in <code class="docutils literal notranslate"><span class="pre">typing</span></code>.</p> <p>The reason why this would belong in the standard Python library instead of an external package is because although the implementation would be quite trivial, the actual power and benefit from it would come from being a standard, to facilitate its usage from library authors and to provide a default way to document Python symbols using <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code>. Some tool providers (at least VS Code and PyCharm) have shown they would consider implementing support for this only if it was a standard.</p> <p>This doesn’t deprecate current usage of docstrings, docstrings should be considered the preferred documentation method when available (not available in type aliases, parameters, etc). And docstrings would be complemented by this proposal for documentation specific to the symbols that can be declared with <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> (currently only covered by the several available microsyntax conventions).</p> <p>This should be relatively transparent to common developers (library users) unless they manually open the source files from libraries adopting it.</p> <p>It should be considered opt-in for library authors who would like to adopt it and they should be free to decide to use it or not.</p> <p>It would be only useful for libraries that are willing to use optional type hints.</p> <section id="summary"> <h3><a class="toc-backref" href="#summary" role="doc-backlink">Summary</a></h3> <p>Here’s a short summary of the features of this proposal in contrast to current conventions:</p> <ul class="simple"> <li><strong>Editing</strong> would be already fully supported by default by any editor (current or future) supporting Python syntax, including syntax errors, syntax highlighting, etc.</li> <li><strong>Rendering</strong> would be relatively straightforward to implement by static tools (tools that don’t need runtime execution), as the information can be extracted from the AST they normally already create.</li> <li>Deduplication of information: the name of a parameter would be defined in a single place, not duplicated inside of a docstring.</li> <li>Elimination of the possibility of having inconsistencies when removing a parameter or class variable and forgetting to remove its documentation.</li> <li>Minimization of the probability of adding a new parameter or class variable and forgetting to add its documentation.</li> <li>Elimination of the possibility of having inconsistencies between the name of a parameter in the signature and the name in the docstring when it is renamed.</li> <li>Access to the documentation string for each symbol at runtime, including existing (older) Python versions.</li> <li>A more formalized way to document other symbols, like type aliases, that could use <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code>.</li> <li>No microsyntax to learn for newcomers, it’s just Python syntax.</li> <li>Parameter documentation inheritance for functions captured by <a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.ParamSpec" title="(in Python v3.13)"><code class="xref py py-class docutils literal notranslate"><span class="pre">ParamSpec</span></code></a>.</li> </ul> </section> </section> <section id="specification"> <h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2> <p>The main proposal is to introduce a new class, <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code>. This class should only be used within <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> annotations. It takes a single positional-only string argument. It should be used to document the intended meaning and use of the symbol declared using <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code>.</p> <p>For example:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span><span class="p">,</span> <span class="n">Doc</span> <span class="k">class</span><span class="w"> </span><span class="nc">User</span><span class="p">:</span> <span class="n">name</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user&#39;s name&quot;</span><span class="p">)]</span> <span class="n">age</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user&#39;s age&quot;</span><span class="p">)]</span> <span class="o">...</span> </pre></div> </div> <p><code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> is normally used as a type annotation, in those cases, any <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> inside of it would document the symbol being annotated.</p> <p>When <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> is used to declare a type alias, <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> would then document the type alias symbol.</p> <p>For example:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span><span class="p">,</span> <span class="n">Doc</span><span class="p">,</span> <span class="n">TypeAlias</span> <span class="kn">from</span><span class="w"> </span><span class="nn">external_library</span><span class="w"> </span><span class="kn">import</span> <span class="n">UserResolver</span> <span class="n">CurrentUser</span><span class="p">:</span> <span class="n">TypeAlias</span> <span class="o">=</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The current system user&quot;</span><span class="p">),</span> <span class="n">UserResolver</span><span class="p">()]</span> <span class="k">def</span><span class="w"> </span><span class="nf">create_user</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user&#39;s name&quot;</span><span class="p">)]):</span> <span class="o">...</span> <span class="k">def</span><span class="w"> </span><span class="nf">delete_user</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user to delete&quot;</span><span class="p">)]):</span> <span class="o">...</span> </pre></div> </div> <p>In this case, if a user imported <code class="docutils literal notranslate"><span class="pre">CurrentUser</span></code>, tools like editors could provide a tooltip with the documentation string when a user hovers over that symbol, or documentation tools could include the type alias with its documentation in their generated output.</p> <p>For tools extracting the information at runtime, they would normally use <a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.get_type_hints" title="(in Python v3.13)"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_type_hints()</span></code></a> with the parameter <code class="docutils literal notranslate"><span class="pre">include_extras=True</span></code>, and as <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> is normalized (even with type aliases), this would mean they should use the last <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> available, if more than one is used, as that is the last one used.</p> <p>At runtime, <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> instances have an attribute <code class="docutils literal notranslate"><span class="pre">documentation</span></code> with the string passed to it.</p> <p>When a function’s signature is captured by a <a class="reference external" href="https://docs.python.org/3/library/typing.html#typing.ParamSpec" title="(in Python v3.13)"><code class="xref py py-class docutils literal notranslate"><span class="pre">ParamSpec</span></code></a>, any documentation strings associated with the parameters should be retained.</p> <p>Any tool processing <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> objects should interpret the string as a docstring, and therefore should normalize whitespace as if <code class="docutils literal notranslate"><span class="pre">inspect.cleandoc()</span></code> were used.</p> <p>The string passed to <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> should be of the form that would be a valid docstring. This means that <a class="reference external" href="https://docs.python.org/3/reference/lexical_analysis.html#formatted-string-literals">f-strings</a> and string operations should not be used. As this cannot be enforced by the Python runtime, tools should not rely on this behavior.</p> <p>When tools providing <strong>rendering</strong> show the raw signature, they could allow configuring if the whole raw <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> code should be displayed, but they should default to not include <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> and its internal code metadata, only the type of the symbols annotated. When those tools support <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> and rendering in other ways than just a raw signature, they should show the string value passed to <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> in a convenient way that shows the relation between the documented symbol and the documentation string.</p> <p>Tools providing <strong>rendering</strong> could allow ways to configure where to show the parameter documentation and the prose docstring in different ways. Otherwise, they could simply show the prose docstring first and then the parameter documentation second.</p> <section id="examples"> <h3><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h3> <p>Class attributes may be documented:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span><span class="p">,</span> <span class="n">Doc</span> <span class="k">class</span><span class="w"> </span><span class="nc">User</span><span class="p">:</span> <span class="n">name</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user&#39;s name&quot;</span><span class="p">)]</span> <span class="n">age</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user&#39;s age&quot;</span><span class="p">)]</span> <span class="o">...</span> </pre></div> </div> <p>As can function or method parameters and return values:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span><span class="p">,</span> <span class="n">Doc</span> <span class="k">def</span><span class="w"> </span><span class="nf">create_user</span><span class="p">(</span> <span class="n">name</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user&#39;s name&quot;</span><span class="p">)],</span> <span class="n">age</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user&#39;s age&quot;</span><span class="p">)],</span> <span class="n">cursor</span><span class="p">:</span> <span class="n">DatabaseConnection</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Annotated</span><span class="p">[</span><span class="n">User</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The created user after saving in the database&quot;</span><span class="p">)]:</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;Create a new user in the system.</span> <span class="sd"> It needs the database connection to be already initialized.</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="k">pass</span> </pre></div> </div> </section> </section> <section id="backwards-compatibility"> <h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2> <p>This proposal is fully backwards compatible with existing code and it doesn’t deprecate existing usage of docstring conventions.</p> <p>For developers that wish to adopt it before it is available in the standard library, or to support older versions of Python, they can use <code class="docutils literal notranslate"><span class="pre">typing_extensions</span></code> and import and use <code class="docutils literal notranslate"><span class="pre">Doc</span></code> from there.</p> <p>For example:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span> <span class="kn">from</span><span class="w"> </span><span class="nn">typing_extensions</span><span class="w"> </span><span class="kn">import</span> <span class="n">Doc</span> <span class="k">class</span><span class="w"> </span><span class="nc">User</span><span class="p">:</span> <span class="n">name</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user&#39;s name&quot;</span><span class="p">)]</span> <span class="n">age</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user&#39;s age&quot;</span><span class="p">)]</span> <span class="o">...</span> </pre></div> </div> </section> <section id="security-implications"> <h2><a class="toc-backref" href="#security-implications" role="doc-backlink">Security Implications</a></h2> <p>There are no known security implications.</p> </section> <section id="how-to-teach-this"> <h2><a class="toc-backref" href="#how-to-teach-this" role="doc-backlink">How to Teach This</a></h2> <p>The main mechanism of documentation should continue to be standard docstrings for prose information, this applies to modules, classes, functions and methods.</p> <p>For authors that want to adopt this proposal to add more granularity, they can use <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> inside of <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> annotations for the symbols that support it.</p> <p>Library authors that wish to adopt this proposal while keeping backwards compatibility with older versions of Python should use <code class="docutils literal notranslate"><span class="pre">typing_extensions.Doc</span></code> instead of <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code>.</p> </section> <section id="reference-implementation"> <h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2> <p><code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> is implemented equivalently to:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Doc</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">documentation</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="o">/</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">documentation</span> <span class="o">=</span> <span class="n">documentation</span> </pre></div> </div> <p>It has been implemented in the <a class="reference external" href="https://pypi.org/project/typing-extensions/">typing_extensions</a> package.</p> </section> <section id="survey-of-other-languages"> <h2><a class="toc-backref" href="#survey-of-other-languages" role="doc-backlink">Survey of Other languages</a></h2> <p>Here’s a short survey of how other languages document their symbols.</p> <section id="java"> <h3><a class="toc-backref" href="#java" role="doc-backlink">Java</a></h3> <p>Java functions and their parameters are documented with <a class="reference external" href="https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html">Javadoc</a>, a special format for comments put on top of the function definition. This would be similar to Python current docstring microsyntax conventions (but only one).</p> <p>For example:</p> <div class="highlight-java notranslate"><div class="highlight"><pre><span></span><span class="cm">/**</span> <span class="cm">* Returns an Image object that can then be painted on the screen.</span> <span class="cm">* The url argument must specify an absolute &lt;a href=&quot;#{@link}&quot;&gt;{@link URL}&lt;/a&gt;. The name</span> <span class="cm">* argument is a specifier that is relative to the url argument.</span> <span class="cm">* &lt;p&gt;</span> <span class="cm">* This method always returns immediately, whether or not the</span> <span class="cm">* image exists. When this applet attempts to draw the image on</span> <span class="cm">* the screen, the data will be loaded. The graphics primitives</span> <span class="cm">* that draw the image will incrementally paint on the screen.</span> <span class="cm">*</span> <span class="cm">* @param url an absolute URL giving the base location of the image</span> <span class="cm">* @param name the location of the image, relative to the url argument</span> <span class="cm">* @return the image at the specified URL</span> <span class="cm">* @see Image</span> <span class="cm">*/</span> <span class="kd">public</span><span class="w"> </span><span class="n">Image</span><span class="w"> </span><span class="nf">getImage</span><span class="p">(</span><span class="n">URL</span><span class="w"> </span><span class="n">url</span><span class="p">,</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="n">name</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">getImage</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">URL</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="p">));</span> <span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">MalformedURLException</span><span class="w"> </span><span class="n">e</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="kc">null</span><span class="p">;</span> <span class="w"> </span><span class="p">}</span> <span class="p">}</span> </pre></div> </div> </section> <section id="javascript"> <h3><a class="toc-backref" href="#javascript" role="doc-backlink">JavaScript</a></h3> <p>Both JavaScript and TypeScript use a similar system to Javadoc.</p> <p>JavaScript uses <a class="reference external" href="https://jsdoc.app/">JSDoc</a>.</p> <p>For example:</p> <div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="cm">/**</span> <span class="cm">* Represents a book.</span> <span class="cm">* @constructor</span> <span class="cm">* @param {string} title - The title of the book.</span> <span class="cm">* @param {string} author - The author of the book.</span> <span class="cm">*/</span> <span class="kd">function</span><span class="w"> </span><span class="nx">Book</span><span class="p">(</span><span class="nx">title</span><span class="p">,</span><span class="w"> </span><span class="nx">author</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="p">}</span> </pre></div> </div> </section> <section id="typescript"> <h3><a class="toc-backref" href="#typescript" role="doc-backlink">TypeScript</a></h3> <p>TypeScript has <a class="reference external" href="https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html">its own JSDoc reference</a> with some variations.</p> <p>For example:</p> <div class="highlight-typescript notranslate"><div class="highlight"><pre><span></span><span class="c1">// Parameters may be declared in a variety of syntactic forms</span> <span class="cm">/**</span> <span class="cm">* @param {string} p1 - A string param.</span> <span class="cm">* @param {string=} p2 - An optional param (Google Closure syntax)</span> <span class="cm">* @param {string} [p3] - Another optional param (JSDoc syntax).</span> <span class="cm">* @param {string} [p4=&quot;test&quot;] - An optional param with a default value</span> <span class="cm">* @returns {string} This is the result</span> <span class="cm">*/</span> <span class="kd">function</span><span class="w"> </span><span class="nx">stringsStringStrings</span><span class="p">(</span><span class="nx">p1</span><span class="p">,</span><span class="w"> </span><span class="nx">p2</span><span class="p">,</span><span class="w"> </span><span class="nx">p3</span><span class="p">,</span><span class="w"> </span><span class="nx">p4</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// TODO</span> <span class="p">}</span> </pre></div> </div> </section> <section id="rust"> <h3><a class="toc-backref" href="#rust" role="doc-backlink">Rust</a></h3> <p>Rust uses another similar variation of a microsyntax in <a class="reference external" href="https://doc.rust-lang.org/rust-by-example/meta/doc.html#doc-comments">Doc comments</a>.</p> <p>But it doesn’t have a particular well defined microsyntax structure to denote what documentation refers to what symbol/parameter other than what can be inferred from the pure Markdown.</p> <p>For example:</p> <div class="highlight-rust notranslate"><div class="highlight"><pre><span></span><span class="cp">#![crate_name = </span><span class="s">&quot;doc&quot;</span><span class="cp">]</span> <span class="sd">/// A human being is represented here</span> <span class="k">pub</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">Person</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="sd">/// A person must have a name, no matter how much Juliet may hate it</span> <span class="w"> </span><span class="n">name</span><span class="p">:</span><span class="w"> </span><span class="nb">String</span><span class="p">,</span> <span class="p">}</span> <span class="k">impl</span><span class="w"> </span><span class="n">Person</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="sd">/// Returns a person with the name given them</span> <span class="w"> </span><span class="sd">///</span> <span class="w"> </span><span class="sd">/// # Arguments</span> <span class="w"> </span><span class="sd">///</span> <span class="w"> </span><span class="sd">/// * `name` - A string slice that holds the name of the person</span> <span class="w"> </span><span class="sd">///</span> <span class="w"> </span><span class="sd">/// # Examples</span> <span class="w"> </span><span class="sd">///</span> <span class="w"> </span><span class="sd">/// ```</span> <span class="w"> </span><span class="sd">/// // You can have rust code between fences inside the comments</span> <span class="w"> </span><span class="sd">/// // If you pass --test to `rustdoc`, it will even test it for you!</span> <span class="w"> </span><span class="sd">/// use doc::Person;</span> <span class="w"> </span><span class="sd">/// let person = Person::new(&quot;name&quot;);</span> <span class="w"> </span><span class="sd">/// ```</span> <span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="nf">new</span><span class="p">(</span><span class="n">name</span><span class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span class="kt">str</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="nc">Person</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">Person</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="n">name</span><span class="p">:</span><span class="w"> </span><span class="nc">name</span><span class="p">.</span><span class="n">to_string</span><span class="p">(),</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="p">}</span> <span class="w"> </span><span class="sd">/// Gives a friendly hello!</span> <span class="w"> </span><span class="sd">///</span> <span class="w"> </span><span class="sd">/// Says &quot;Hello, [name](Person::name)&quot; to the `Person` it is called on.</span> <span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="nf">hello</span><span class="p">(</span><span class="o">&amp;</span><span class="w"> </span><span class="bp">self</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">&quot;Hello, {}!&quot;</span><span class="p">,</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">name</span><span class="p">);</span> <span class="w"> </span><span class="p">}</span> <span class="p">}</span> <span class="k">fn</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">john</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Person</span><span class="p">::</span><span class="n">new</span><span class="p">(</span><span class="s">&quot;John&quot;</span><span class="p">);</span> <span class="w"> </span><span class="n">john</span><span class="p">.</span><span class="n">hello</span><span class="p">();</span> <span class="p">}</span> </pre></div> </div> </section> <section id="go-lang"> <h3><a class="toc-backref" href="#go-lang" role="doc-backlink">Go Lang</a></h3> <p>Go also uses a form of <a class="reference external" href="https://go.dev/doc/comment">Doc Comments</a>.</p> <p>It doesn’t have a well defined microsyntax structure to denote what documentation refers to which symbol/parameter, but parameters can be referenced by name without any special syntax or marker, this also means that ordinary words that could appear in the documentation text should be avoided as parameter names.</p> <div class="highlight-go notranslate"><div class="highlight"><pre><span></span><span class="kn">package</span><span class="w"> </span><span class="nx">strconv</span> <span class="c1">// Quote returns a double-quoted Go string literal representing s.</span> <span class="c1">// The returned string uses Go escape sequences (\t, \n, \xFF, \u0100)</span> <span class="c1">// for control characters and non-printable characters as defined by IsPrint.</span> <span class="kd">func</span><span class="w"> </span><span class="nx">Quote</span><span class="p">(</span><span class="nx">s</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="o">...</span> <span class="p">}</span> </pre></div> </div> </section> </section> <section id="rejected-ideas"> <h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2> <section id="standardize-current-docstrings"> <h3><a class="toc-backref" href="#standardize-current-docstrings" role="doc-backlink">Standardize Current Docstrings</a></h3> <p>A possible alternative would be to support and try to push as a standard one of the existing docstring formats. But that would only solve the standardization.</p> <p>It wouldn’t solve any of the other problems derived from using a microsyntax inside of a docstring instead of pure Python syntax, the same as described above in the <strong>Rationale - Summary</strong>.</p> </section> <section id="extra-metadata-and-decorator"> <h3><a class="toc-backref" href="#extra-metadata-and-decorator" role="doc-backlink">Extra Metadata and Decorator</a></h3> <p>Some ideas before this proposal included having a function <code class="docutils literal notranslate"><span class="pre">doc()</span></code> instead of the single class <code class="docutils literal notranslate"><span class="pre">Doc</span></code> with several parameters to indicate whether an object is discouraged from use, what exceptions it may raise, etc. To allow also deprecating functions and classes, it was also expected that <code class="docutils literal notranslate"><span class="pre">doc()</span></code> could be used as a decorator. But this functionality is covered by <code class="docutils literal notranslate"><span class="pre">typing.deprecated()</span></code> in <a class="pep reference internal" href="../pep-0702/" title="PEP 702 – Marking deprecations using the type system">PEP 702</a>, so it was dropped from this proposal.</p> <p>A way to declare additional information could still be useful in the future, but taking early feedback on this idea, all that was postponed to future proposals.</p> <p>This also shifted the focus from an all-encompassing function <code class="docutils literal notranslate"><span class="pre">doc()</span></code> with multiple parameters to a single <code class="docutils literal notranslate"><span class="pre">Doc</span></code> class to be used in <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> in a way that could be composed with other future proposals.</p> <p>This design change also allows better interoperability with other proposals like <code class="docutils literal notranslate"><span class="pre">typing.deprecated()</span></code>, as in the future it could be considered to allow having <code class="docutils literal notranslate"><span class="pre">typing.deprecated()</span></code> also in <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> to deprecate individual parameters, coexisting with <code class="docutils literal notranslate"><span class="pre">Doc</span></code>.</p> </section> <section id="string-under-definition"> <h3><a class="toc-backref" href="#string-under-definition" role="doc-backlink">String Under Definition</a></h3> <p>A proposed alternative in the discussion is declaring a string under the definition of a symbol and providing runtime access to those values:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">User</span><span class="p">:</span> <span class="n">name</span><span class="p">:</span> <span class="nb">str</span> <span class="s2">&quot;The user&#39;s name&quot;</span> <span class="n">age</span><span class="p">:</span> <span class="nb">int</span> <span class="s2">&quot;The user&#39;s age&quot;</span> <span class="o">...</span> </pre></div> </div> <p>This was already proposed and rejected in <a class="pep reference internal" href="../pep-0224/" title="PEP 224 – Attribute Docstrings">PEP 224</a>, mainly due to the ambiguity of how is the string connected with the symbol it’s documenting.</p> <p>Additionally, there would be no way to provide runtime access to this value in previous versions of Python.</p> </section> <section id="plain-string-in-annotated"> <h3><a class="toc-backref" href="#plain-string-in-annotated" role="doc-backlink">Plain String in Annotated</a></h3> <p>In the discussion, it was also suggested to use a plain string inside of <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code>:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span> <span class="k">class</span><span class="w"> </span><span class="nc">User</span><span class="p">:</span> <span class="n">name</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="s2">&quot;The user&#39;s name&quot;</span><span class="p">]</span> <span class="n">age</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="s2">&quot;The user&#39;s age&quot;</span><span class="p">]</span> <span class="o">...</span> </pre></div> </div> <p>But this would create a predefined meaning for any plain string inside of <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code>, and any tool that was using plain strings in them for any other purpose, which is currently allowed, would now be invalid.</p> <p>Having an explicit <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code> makes it compatible with current valid uses of <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code>.</p> </section> <section id="another-annotated-like-type"> <h3><a class="toc-backref" href="#another-annotated-like-type" role="doc-backlink">Another Annotated-Like Type</a></h3> <p>In the discussion it was suggested to define a new type similar to <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code>, it would take the type and a parameter with the documentation string:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Doc</span> <span class="k">class</span><span class="w"> </span><span class="nc">User</span><span class="p">:</span> <span class="n">name</span><span class="p">:</span> <span class="n">Doc</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="s2">&quot;The user&#39;s name&quot;</span><span class="p">]</span> <span class="n">age</span><span class="p">:</span> <span class="n">Doc</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="s2">&quot;The user&#39;s age&quot;</span><span class="p">]</span> <span class="o">...</span> </pre></div> </div> <p>This idea was rejected as it would only support that use case and would make it more difficult to combine it with <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> for other purposes ( e.g. with FastAPI metadata, Pydantic fields, etc.) or adding additional metadata apart from the documentation string (e.g. deprecation).</p> </section> <section id="transferring-documentation-from-type-aliases"> <h3><a class="toc-backref" href="#transferring-documentation-from-type-aliases" role="doc-backlink">Transferring Documentation from Type aliases</a></h3> <p>A previous version of this proposal specified that when type aliases declared with <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> were used, and these type aliases were used in annotations, the documentation string would be transferred to the annotated symbol.</p> <p>For example:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Annotated</span><span class="p">,</span> <span class="n">Doc</span><span class="p">,</span> <span class="n">TypeAlias</span> <span class="n">UserName</span><span class="p">:</span> <span class="n">TypeAlias</span> <span class="o">=</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Doc</span><span class="p">(</span><span class="s2">&quot;The user&#39;s name&quot;</span><span class="p">)]</span> <span class="k">def</span><span class="w"> </span><span class="nf">create_user</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="n">UserName</span><span class="p">):</span> <span class="o">...</span> <span class="k">def</span><span class="w"> </span><span class="nf">delete_user</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="n">UserName</span><span class="p">):</span> <span class="o">...</span> </pre></div> </div> <p>This was rejected after receiving feedback from the maintainer of one of the main components used to provide editor support.</p> </section> <section id="shorthand-with-slices"> <h3><a class="toc-backref" href="#shorthand-with-slices" role="doc-backlink">Shorthand with Slices</a></h3> <p>In the discussion, it was suggested to use a shorthand with slices:</p> <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">is_approved</span><span class="p">:</span> <span class="n">Annotated</span><span class="p">[</span><span class="nb">str</span><span class="p">:</span> <span class="s2">&quot;The status of a PEP.&quot;</span><span class="p">]</span> </pre></div> </div> <p>Although this is a very clever idea and would remove the need for a new <code class="docutils literal notranslate"><span class="pre">Doc</span></code> class, runtime executing of current versions of Python don’t allow it.</p> <p>At runtime, <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> requires at least two arguments, and it requires the first argument to be type, it crashes if it is a slice.</p> </section> </section> <section id="open-issues"> <h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2> <section id="verbosity"> <h3><a class="toc-backref" href="#verbosity" role="doc-backlink">Verbosity</a></h3> <p>The main argument against this would be the increased verbosity.</p> <p>If the signature was not viewed independently of the documentation and the body of the function with the docstring was also measured, the total verbosity would be somewhat similar, as what this proposal does is to move some of the contents from the docstring in the body to the signature.</p> <p>Considering the signature alone, without the body, they could be much longer than they currently are, they could end up being more than one page long. In exchange, the equivalent docstrings that currently are more than one page long would be much shorter.</p> <p>When comparing the total verbosity, including the signature and the docstring, the main additional verbosity added by this would be from using <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> and <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code>. If <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> had more usage, it could make sense to have an improved shorter syntax for it and for the type of metadata it would carry. But that would only make sense once <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> is more widely used.</p> <p>On the other hand, this verbosity would not affect end users as they would not see the internal code using <code class="docutils literal notranslate"><span class="pre">typing.Doc</span></code>. The majority of users would interact with libraries through editors without looking at the internals, and if anything, they would have tooltips from editors supporting this proposal.</p> <p>The cost of dealing with the additional verbosity would mainly be carried by those library maintainers that use this feature.</p> <p>This argument could be analogous to the argument against type annotations in general, as they do indeed increase verbosity, in exchange for their features. But again, as with type annotations, this would be optional and only to be used by those that are willing to take the extra verbosity in exchange for the benefits.</p> <p>Of course, more advanced users might want to look at the source code of the libraries and if the authors of those libraries adopted this, those advanced users would end up having to look at that code with additional signature verbosity instead of docstring verbosity.</p> <p>Any authors that decide not to adopt it should be free to continue using docstrings with any particular format they decide, no docstrings at all, etc.</p> <p>Still, there’s a high chance that library authors could receive pressure to adopt this if it became the blessed solution.</p> </section> <section id="documentation-is-not-typing"> <h3><a class="toc-backref" href="#documentation-is-not-typing" role="doc-backlink">Documentation is not Typing</a></h3> <p>It could also be argued that documentation is not really part of typing, or that it should live in a different module. Or that this information should not be part of the signature but live in another place (like the docstring).</p> <p>Nevertheless, type annotations in Python could already be considered, by default, additional metadata: they carry additional information about variables, parameters, return types, and by default they don’t have any runtime behavior. And this proposal would add one more type of metadata to them.</p> <p>It could be argued that this proposal extends the type of information that type annotations carry, the same way as <a class="pep reference internal" href="../pep-0702/" title="PEP 702 – Marking deprecations using the type system">PEP 702</a> extends them to include deprecation information.</p> <p><code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> was added to the standard library precisely to support adding additional metadata to the annotations, and as the new proposed <code class="docutils literal notranslate"><span class="pre">Doc</span></code> class is tightly coupled to <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code>, it makes sense for it to live in the same module. If <code class="xref py py-class docutils literal notranslate"><span class="pre">Annotated</span></code> was moved to another module, it would make sense to move <code class="docutils literal notranslate"><span class="pre">Doc</span></code> with it.</p> </section> <section id="multiple-standards"> <h3><a class="toc-backref" href="#multiple-standards" role="doc-backlink">Multiple Standards</a></h3> <p>Another argument against this would be that it would create another standard, and that there are already several conventions for docstrings. It could seem better to formalize one of the currently existing standards.</p> <p>Nevertheless, as stated above, none of those conventions cover the general drawbacks of a doctsring-based approach that this proposal solves naturally.</p> <p>To see a list of the drawbacks of a docstring-based approach, see the section above in the <strong>Rationale - Summary</strong>.</p> <p>In the same way, it can be seen that, in many cases, a new standard that takes advantage of new features and solves several problems from previous methods can be worth having. As is the case with the new <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>, <code class="docutils literal notranslate"><span class="pre">dataclass_transform</span></code>, the new typing pipe/union (<code class="docutils literal notranslate"><span class="pre">|</span></code>) operator, and other cases.</p> </section> <section id="adoption"> <h3><a class="toc-backref" href="#adoption" role="doc-backlink">Adoption</a></h3> <p>As this is a new standard proposal, it would only make sense if it had interest from the community.</p> <p>Fortunately there’s already interest from several mainstream libraries from several developers and teams, including FastAPI, Typer, SQLModel, Asyncer (from the author of this proposal), Pydantic, Strawberry (GraphQL), and others.</p> <p>There’s also interest and support from documentation tools, like <a class="reference external" href="https://github.com/mkdocstrings/mkdocstrings">mkdocstrings</a>, which added support even for an earlier version of this proposal.</p> <p>All the CPython core developers contacted for early feedback (at least 4) have shown interest and support for this proposal.</p> <p>Editor developers (VS Code and PyCharm) have shown some interest, while showing concerns about the signature verbosity of the proposal, although not about the implementation (which is what would affect them the most). And they have shown they would consider adding support for this if it were to become an official standard. In that case, they would only need to add support for rendering, as support for editing, which is normally non-existing for other standards, is already there, as they already support editing standard Python syntax.</p> </section> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0727.rst">https://github.com/python/peps/blob/main/peps/pep-0727.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0727.rst">2025-02-01 08:55:40 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#motivation">Motivation</a></li> <li><a class="reference internal" href="#rationale">Rationale</a><ul> <li><a class="reference internal" href="#summary">Summary</a></li> </ul> </li> <li><a class="reference internal" href="#specification">Specification</a><ul> <li><a class="reference internal" href="#examples">Examples</a></li> </ul> </li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#security-implications">Security Implications</a></li> <li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li> <li><a class="reference internal" href="#survey-of-other-languages">Survey of Other languages</a><ul> <li><a class="reference internal" href="#java">Java</a></li> <li><a class="reference internal" href="#javascript">JavaScript</a></li> <li><a class="reference internal" href="#typescript">TypeScript</a></li> <li><a class="reference internal" href="#rust">Rust</a></li> <li><a class="reference internal" href="#go-lang">Go Lang</a></li> </ul> </li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul> <li><a class="reference internal" href="#standardize-current-docstrings">Standardize Current Docstrings</a></li> <li><a class="reference internal" href="#extra-metadata-and-decorator">Extra Metadata and Decorator</a></li> <li><a class="reference internal" href="#string-under-definition">String Under Definition</a></li> <li><a class="reference internal" href="#plain-string-in-annotated">Plain String in Annotated</a></li> <li><a class="reference internal" href="#another-annotated-like-type">Another Annotated-Like Type</a></li> <li><a class="reference internal" href="#transferring-documentation-from-type-aliases">Transferring Documentation from Type aliases</a></li> <li><a class="reference internal" href="#shorthand-with-slices">Shorthand with Slices</a></li> </ul> </li> <li><a class="reference internal" href="#open-issues">Open Issues</a><ul> <li><a class="reference internal" href="#verbosity">Verbosity</a></li> <li><a class="reference internal" href="#documentation-is-not-typing">Documentation is not Typing</a></li> <li><a class="reference internal" href="#multiple-standards">Multiple Standards</a></li> <li><a class="reference internal" href="#adoption">Adoption</a></li> </ul> </li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0727.rst">Page Source (GitHub)</a> </nav> </section> <script src="../_static/colour_scheme.js"></script> <script src="../_static/wrap_tables.js"></script> <script src="../_static/sticky_banner.js"></script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10