CINXE.COM

PEP 737 – C API to format a type fully qualified name | 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 737 – C API to format a type fully qualified name | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0737/"> <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 737 – C API to format a type fully qualified name | peps.python.org'> <meta property="og:description" content="Add new convenient C APIs to format a type fully qualified name. No longer format type names differently depending on how types are implemented."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0737/"> <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="Add new convenient C APIs to format a type fully qualified name. No longer format type names differently depending on how types are implemented."> <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 737</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 737 – C API to format a type fully qualified name</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Victor Stinner &lt;vstinner&#32;&#97;t&#32;python.org&gt;</dd> <dt class="field-even">Discussions-To<span class="colon">:</span></dt> <dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/pep-737-unify-type-name-formatting/39872">Discourse thread</a></dd> <dt class="field-odd">Status<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd> <dt class="field-even">Type<span class="colon">:</span></dt> <dd class="field-even"><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-odd">Created<span class="colon">:</span></dt> <dd class="field-odd">29-Nov-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/pep-737-unify-type-name-formatting/39872" title="Discourse thread">29-Nov-2023</a></dd> <dt class="field-even">Resolution<span class="colon">:</span></dt> <dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/pep-737-unify-type-name-formatting/39872/60">Discourse message</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="#rationale">Rationale</a><ul> <li><a class="reference internal" href="#standard-library">Standard library</a><ul> <li><a class="reference internal" href="#python-code">Python code</a></li> <li><a class="reference internal" href="#c-code">C code</a></li> </ul> </li> <li><a class="reference internal" href="#using-pytypeobject-tp-name-is-inconsistent-with-python">Using PyTypeObject.tp_name is inconsistent with Python</a></li> <li><a class="reference internal" href="#limited-c-api">Limited C API</a></li> <li><a class="reference internal" href="#truncating-type-names-in-c">Truncating type names in C</a></li> </ul> </li> <li><a class="reference internal" href="#specification">Specification</a><ul> <li><a class="reference internal" href="#add-pytype-getfullyqualifiedname-function">Add PyType_GetFullyQualifiedName() function</a></li> <li><a class="reference internal" href="#add-pytype-getmodulename-function">Add PyType_GetModuleName() function</a></li> <li><a class="reference internal" href="#add-formats-to-pyunicode-fromformat">Add formats to PyUnicode_FromFormat()</a></li> <li><a class="reference internal" href="#formats-summary">Formats Summary</a></li> <li><a class="reference internal" href="#recommend-using-the-type-fully-qualified-name">Recommend using the type fully qualified name</a></li> <li><a class="reference internal" href="#recommend-not-truncating-type-names">Recommend not truncating type names</a></li> </ul> </li> <li><a class="reference internal" href="#implementation">Implementation</a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul> <li><a class="reference internal" href="#id1">Add type.__fully_qualified_name__ attribute</a></li> <li><a class="reference internal" href="#add-type-format-method">Add type.__format__() method</a></li> <li><a class="reference internal" href="#change-str-type">Change str(type)</a></li> <li><a class="reference internal" href="#add-t-formatter-to-get-an-object-type">Add !t formatter to get an object type</a></li> <li><a class="reference internal" href="#add-formats-to-str-args">Add formats to str % args</a></li> <li><a class="reference internal" href="#other-ways-to-format-type-names-in-c">Other ways to format type names in C</a></li> <li><a class="reference internal" href="#use-t-format-with-py-type-pass-a-type">Use %T format with Py_TYPE(): pass a type</a></li> <li><a class="reference internal" href="#other-proposed-apis-to-get-a-type-fully-qualified-name">Other proposed APIs to get a type fully qualified name</a></li> <li><a class="reference internal" href="#include-the-main-module-in-the-type-fully-qualified-name">Include the __main__ module in the type fully qualified name</a></li> </ul> </li> <li><a class="reference internal" href="#discussions">Discussions</a></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>Add new convenient C APIs to format a type fully qualified name. No longer format type names differently depending on how types are implemented.</p> <p>Recommend using the type fully qualified name in error messages and in <code class="docutils literal notranslate"><span class="pre">__repr__()</span></code> methods in new C code. Recommend not truncating type names in new C code.</p> <p>Add <code class="docutils literal notranslate"><span class="pre">%T</span></code>, <code class="docutils literal notranslate"><span class="pre">%#T</span></code>, <code class="docutils literal notranslate"><span class="pre">%N</span></code> and <code class="docutils literal notranslate"><span class="pre">%#N</span></code> formats to <code class="docutils literal notranslate"><span class="pre">PyUnicode_FromFormat()</span></code> to format the fully qualified, respectively, of an object type and of a type.</p> <p>Make C code safer by avoiding borrowed reference which can lead to crashes. The new C API is compatible with the limited C API.</p> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <section id="standard-library"> <h3><a class="toc-backref" href="#standard-library" role="doc-backlink">Standard library</a></h3> <p>In the Python standard library, formatting a type name or the type name of an object is a common operation to format an error message and to implement a <code class="docutils literal notranslate"><span class="pre">__repr__()</span></code> method. There are different ways to format a type name which give different outputs.</p> <p>Example with the <code class="docutils literal notranslate"><span class="pre">datetime.timedelta</span></code> type:</p> <ul class="simple"> <li>The type short name (<code class="docutils literal notranslate"><span class="pre">type.__name__</span></code>) and the type qualified name (<code class="docutils literal notranslate"><span class="pre">type.__qualname__</span></code>) are <code class="docutils literal notranslate"><span class="pre">'timedelta'</span></code>.</li> <li>The type module (<code class="docutils literal notranslate"><span class="pre">type.__module__</span></code>) is <code class="docutils literal notranslate"><span class="pre">'datetime'</span></code>.</li> <li>The type fully qualified name is <code class="docutils literal notranslate"><span class="pre">'datetime.timedelta'</span></code>.</li> <li>The type representation (<code class="docutils literal notranslate"><span class="pre">repr(type)</span></code>) contains the fully qualified name: <code class="docutils literal notranslate"><span class="pre">&lt;class</span> <span class="pre">'datetime.timedelta'&gt;</span></code>.</li> </ul> <section id="python-code"> <h4><a class="toc-backref" href="#python-code" role="doc-backlink">Python code</a></h4> <p>In Python, <code class="docutils literal notranslate"><span class="pre">type.__name__</span></code> gets the type short name, whereas <code class="docutils literal notranslate"><span class="pre">f&quot;{type.__module__}.{type.__qualname__}&quot;</span></code> formats the type “fully qualified name”. Usually, <code class="docutils literal notranslate"><span class="pre">type(obj)</span></code> or <code class="docutils literal notranslate"><span class="pre">obj.__class__</span></code> are used to get the type of the object <em>obj</em>. Sometimes, the type name is put between quotes.</p> <p>Examples:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">raise</span> <span class="pre">TypeError(&quot;str</span> <span class="pre">expected,</span> <span class="pre">not</span> <span class="pre">%s&quot;</span> <span class="pre">%</span> <span class="pre">type(value).__name__)</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">raise</span> <span class="pre">TypeError(&quot;can't</span> <span class="pre">serialize</span> <span class="pre">%s&quot;</span> <span class="pre">%</span> <span class="pre">self.__class__.__name__)</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">name</span> <span class="pre">=</span> <span class="pre">&quot;%s.%s&quot;</span> <span class="pre">%</span> <span class="pre">(obj.__module__,</span> <span class="pre">obj.__qualname__)</span></code></li> </ul> <p>Qualified names were added to types (<code class="docutils literal notranslate"><span class="pre">type.__qualname__</span></code>) in Python 3.3 by <a class="pep reference internal" href="../pep-3155/" title="PEP 3155 – Qualified name for classes and functions">PEP 3155</a> “Qualified name for classes and functions”.</p> </section> <section id="c-code"> <h4><a class="toc-backref" href="#c-code" role="doc-backlink">C code</a></h4> <p>In C, the most common way to format a type name is to get the <code class="docutils literal notranslate"><span class="pre">PyTypeObject.tp_name</span></code> member of the type. Example:</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyErr_Format</span><span class="p">(</span><span class="n">PyExc_TypeError</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;globals must be a dict, not %.100s&quot;</span><span class="p">,</span> <span class="w"> </span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">globals</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">tp_name</span><span class="p">);</span> </pre></div> </div> <p>The type “fully qualified name” is used in a few places: <code class="docutils literal notranslate"><span class="pre">PyErr_Display()</span></code>, <code class="docutils literal notranslate"><span class="pre">type.__repr__()</span></code> implementation, and <code class="docutils literal notranslate"><span class="pre">sys.unraisablehook</span></code> implementation.</p> <p>Using <code class="docutils literal notranslate"><span class="pre">Py_TYPE(obj)-&gt;tp_name</span></code> is preferred since it is more convenient than calling <code class="docutils literal notranslate"><span class="pre">PyType_GetQualName()</span></code> which requires <code class="docutils literal notranslate"><span class="pre">Py_DECREF()</span></code>. Moreover, <code class="docutils literal notranslate"><span class="pre">PyType_GetQualName()</span></code> was only added recently, in Python 3.11.</p> <p>Some functions use <code class="docutils literal notranslate"><span class="pre">%R</span></code> (<code class="docutils literal notranslate"><span class="pre">repr(type)</span></code>) to format a type name, the output contains the type fully qualified name. Example:</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyErr_Format</span><span class="p">(</span><span class="n">PyExc_TypeError</span><span class="p">,</span> <span class="w"> </span><span class="s">&quot;calling %R should have returned an instance &quot;</span> <span class="w"> </span><span class="s">&quot;of BaseException, not %R&quot;</span><span class="p">,</span> <span class="w"> </span><span class="n">type</span><span class="p">,</span><span class="w"> </span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">value</span><span class="p">));</span> </pre></div> </div> </section> </section> <section id="using-pytypeobject-tp-name-is-inconsistent-with-python"> <h3><a class="toc-backref" href="#using-pytypeobject-tp-name-is-inconsistent-with-python" role="doc-backlink">Using PyTypeObject.tp_name is inconsistent with Python</a></h3> <p>The <code class="docutils literal notranslate"><span class="pre">PyTypeObject.tp_name</span></code> member is different depending on the type implementation:</p> <ul class="simple"> <li>Static types and heap types in C: <em>tp_name</em> is the type fully qualified name.</li> <li>Python class: <em>tp_name</em> is the type short name (<code class="docutils literal notranslate"><span class="pre">type.__name__</span></code>).</li> </ul> <p>So using <code class="docutils literal notranslate"><span class="pre">Py_TYPE(obj)-&gt;tp_name</span></code> to format an object type name gives a different output depending if a type is implemented in C or in Python.</p> <p>It goes against <a class="pep reference internal" href="../pep-0399/" title="PEP 399 – Pure Python/C Accelerator Module Compatibility Requirements">PEP 399</a> “Pure Python/C Accelerator Module Compatibility Requirements” principles which recommends code behaves the same way if written in Python or in C.</p> <p>Example:</p> <div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="go">$ python3.12</span> <span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">_datetime</span><span class="p">;</span> <span class="n">c_obj</span> <span class="o">=</span> <span class="n">_datetime</span><span class="o">.</span><span class="n">date</span><span class="p">(</span><span class="mi">1970</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">_pydatetime</span><span class="p">;</span> <span class="n">py_obj</span> <span class="o">=</span> <span class="n">_pydatetime</span><span class="o">.</span><span class="n">date</span><span class="p">(</span><span class="mi">1970</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">my_list</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">))</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">my_list</span><span class="p">[</span><span class="n">c_obj</span><span class="p">]</span> <span class="c1"># C type</span> <span class="go">TypeError: list indices must be integers or slices, not datetime.date</span> <span class="gp">&gt;&gt;&gt; </span><span class="n">my_list</span><span class="p">[</span><span class="n">py_obj</span><span class="p">]</span> <span class="c1"># Python type</span> <span class="go">TypeError: list indices must be integers or slices, not date</span> </pre></div> </div> <p>The error message contains the type fully qualified name (<code class="docutils literal notranslate"><span class="pre">datetime.date</span></code>) if the type is implemented in C, or the type short name (<code class="docutils literal notranslate"><span class="pre">date</span></code>) if the type is implemented in Python.</p> </section> <section id="limited-c-api"> <h3><a class="toc-backref" href="#limited-c-api" role="doc-backlink">Limited C API</a></h3> <p>The <code class="docutils literal notranslate"><span class="pre">Py_TYPE(obj)-&gt;tp_name</span></code> code cannot be used with the limited C API, since the <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span></code> members are excluded from the limited C API.</p> <p>The type name should be read using <code class="docutils literal notranslate"><span class="pre">PyType_GetName()</span></code>, <code class="docutils literal notranslate"><span class="pre">PyType_GetQualName()</span></code> and <code class="docutils literal notranslate"><span class="pre">PyType_GetModule()</span></code> functions which are less convenient to use.</p> </section> <section id="truncating-type-names-in-c"> <h3><a class="toc-backref" href="#truncating-type-names-in-c" role="doc-backlink">Truncating type names in C</a></h3> <p>In 1998, when the <code class="docutils literal notranslate"><span class="pre">PyErr_Format()</span></code> function was added, the implementation used a fixed buffer of 500 bytes. The function had the following comment:</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/* Caller is responsible for limiting the format */</span> </pre></div> </div> <p>In 2001, the function was modified to allocate a dynamic buffer on the heap. Too late, the practice of truncating type names, like using the <code class="docutils literal notranslate"><span class="pre">%.100s</span></code> format, already became a habit, and developers forgot why type names are truncated. In Python, type names are not truncated.</p> <p>Truncating type names in C but not in Python goes against <a class="pep reference internal" href="../pep-0399/" title="PEP 399 – Pure Python/C Accelerator Module Compatibility Requirements">PEP 399</a> “Pure Python/C Accelerator Module Compatibility Requirements” principles which recommends code behaves the same way if written in Python or in C.</p> <p>See the issue: <a class="reference external" href="https://github.com/python/cpython/issues/55042">Replace %.100s by %s in PyErr_Format(): the arbitrary limit of 500 bytes is outdated</a> (2011).</p> </section> </section> <section id="specification"> <h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2> <ul class="simple"> <li>Add <code class="docutils literal notranslate"><span class="pre">PyType_GetFullyQualifiedName()</span></code> function.</li> <li>Add <code class="docutils literal notranslate"><span class="pre">PyType_GetModuleName()</span></code> function.</li> <li>Add formats to <code class="docutils literal notranslate"><span class="pre">PyUnicode_FromFormat()</span></code>.</li> <li>Recommend using the type fully qualified name in error messages and in <code class="docutils literal notranslate"><span class="pre">__repr__()</span></code> methods in new C code.</li> <li>Recommend not truncating type names in new C code.</li> </ul> <section id="add-pytype-getfullyqualifiedname-function"> <h3><a class="toc-backref" href="#add-pytype-getfullyqualifiedname-function" role="doc-backlink">Add PyType_GetFullyQualifiedName() function</a></h3> <p>Add the <code class="docutils literal notranslate"><span class="pre">PyType_GetFullyQualifiedName()</span></code> function to get the fully qualified name of a type: similar to <code class="docutils literal notranslate"><span class="pre">f&quot;{type.__module__}.{type.__qualname__}&quot;</span></code>, or <code class="docutils literal notranslate"><span class="pre">type.__qualname__</span></code> if <code class="docutils literal notranslate"><span class="pre">type.__module__</span></code> is not a string or is equal to <code class="docutils literal notranslate"><span class="pre">&quot;builtins&quot;</span></code> or is equal to <code class="docutils literal notranslate"><span class="pre">&quot;__main__&quot;</span></code>.</p> <p>API:</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span><span class="o">*</span><span class="w"> </span><span class="n">PyType_GetFullyQualifiedName</span><span class="p">(</span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">type</span><span class="p">)</span> </pre></div> </div> <p>On success, return a new reference to the string. On error, raise an exception and return <code class="docutils literal notranslate"><span class="pre">NULL</span></code>.</p> </section> <section id="add-pytype-getmodulename-function"> <h3><a class="toc-backref" href="#add-pytype-getmodulename-function" role="doc-backlink">Add PyType_GetModuleName() function</a></h3> <p>Add the <code class="docutils literal notranslate"><span class="pre">PyType_GetModuleName()</span></code> function to get the module name of a type (<code class="docutils literal notranslate"><span class="pre">type.__module__</span></code> string). API:</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span><span class="o">*</span><span class="w"> </span><span class="n">PyType_GetModuleName</span><span class="p">(</span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">type</span><span class="p">)</span> </pre></div> </div> <p>On success, return a new reference to the string. On error, raise an exception and return <code class="docutils literal notranslate"><span class="pre">NULL</span></code>.</p> </section> <section id="add-formats-to-pyunicode-fromformat"> <h3><a class="toc-backref" href="#add-formats-to-pyunicode-fromformat" role="doc-backlink">Add formats to PyUnicode_FromFormat()</a></h3> <p>Add the following formats to <code class="docutils literal notranslate"><span class="pre">PyUnicode_FromFormat()</span></code>:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">%N</span></code> formats the <strong>fully qualified name</strong> of a <strong>type</strong>, similar to <code class="docutils literal notranslate"><span class="pre">PyType_GetFullyQualifiedName(type)</span></code>; <strong>N</strong> stands for type <strong>N</strong>ame.</li> <li><code class="docutils literal notranslate"><span class="pre">%T</span></code> formats the type <strong>fully qualified name</strong> of an object’s <strong>type</strong>, similar to <code class="docutils literal notranslate"><span class="pre">PyType_GetFullyQualifiedName(Py_TYPE(obj))</span></code>; <strong>T</strong> stands for object <strong>T</strong>ype.</li> <li><code class="docutils literal notranslate"><span class="pre">%#N</span></code> and <code class="docutils literal notranslate"><span class="pre">%#T</span></code>: the alternative form uses the <strong>colon</strong> separator (<code class="docutils literal notranslate"><span class="pre">:</span></code>), instead of the dot separator (<code class="docutils literal notranslate"><span class="pre">.</span></code>), between the module name and the qualified name.</li> </ul> <p>For example, the existing code using <em>tp_name</em>:</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyErr_Format</span><span class="p">(</span><span class="n">PyExc_TypeError</span><span class="p">,</span> <span class="w"> </span><span class="s">&quot;__format__ must return a str, not %.200s&quot;</span><span class="p">,</span> <span class="w"> </span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">result</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">tp_name</span><span class="p">);</span> </pre></div> </div> <p>can be replaced with the <code class="docutils literal notranslate"><span class="pre">%T</span></code> format:</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyErr_Format</span><span class="p">(</span><span class="n">PyExc_TypeError</span><span class="p">,</span> <span class="w"> </span><span class="s">&quot;__format__ must return a str, not %T&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">result</span><span class="p">);</span> </pre></div> </div> <p>Advantages of the updated code:</p> <ul class="simple"> <li>Safer C code: avoid <code class="docutils literal notranslate"><span class="pre">Py_TYPE()</span></code> which returns a borrowed reference.</li> <li>The <code class="docutils literal notranslate"><span class="pre">PyTypeObject.tp_name</span></code> member is no longer read explicitly: the code becomes compatible with the limited C API.</li> <li>The formatted type name no longer depends on the type implementation.</li> <li>The type name is no longer truncated.</li> </ul> <p>Note: The <code class="docutils literal notranslate"><span class="pre">%T</span></code> format is used by <code class="docutils literal notranslate"><span class="pre">time.strftime()</span></code>, but not by <code class="docutils literal notranslate"><span class="pre">printf()</span></code>.</p> </section> <section id="formats-summary"> <h3><a class="toc-backref" href="#formats-summary" role="doc-backlink">Formats Summary</a></h3> <table class="docutils align-default"> <thead> <tr class="row-odd"><th class="head">C object</th> <th class="head">C type</th> <th class="head">Format</th> </tr> </thead> <tbody> <tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">%T</span></code></td> <td><code class="docutils literal notranslate"><span class="pre">%N</span></code></td> <td>Type <strong>fully qualified</strong> name.</td> </tr> <tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">%#T</span></code></td> <td><code class="docutils literal notranslate"><span class="pre">%#N</span></code></td> <td>Type <strong>fully qualified</strong> name, <strong>colon</strong> separator.</td> </tr> </tbody> </table> </section> <section id="recommend-using-the-type-fully-qualified-name"> <h3><a class="toc-backref" href="#recommend-using-the-type-fully-qualified-name" role="doc-backlink">Recommend using the type fully qualified name</a></h3> <p>The type fully qualified name is recommended in error messages and in <code class="docutils literal notranslate"><span class="pre">__repr__()</span></code> methods in new C code.</p> <p>In non-trivial applications, it is likely to have two types with the same short name defined in two different modules, especially with generic names. Using the fully qualified name helps identifying the type in an unambiguous way.</p> </section> <section id="recommend-not-truncating-type-names"> <h3><a class="toc-backref" href="#recommend-not-truncating-type-names" role="doc-backlink">Recommend not truncating type names</a></h3> <p>Type names should not be truncated in new C code. For example, the <code class="docutils literal notranslate"><span class="pre">%.100s</span></code> format should be avoided: use the <code class="docutils literal notranslate"><span class="pre">%s</span></code> format instead (or <code class="docutils literal notranslate"><span class="pre">%T</span></code> format in C).</p> </section> </section> <section id="implementation"> <h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2> <ul class="simple"> <li>Pull request: <a class="reference external" href="https://github.com/python/cpython/pull/112133">Add type.__fully_qualified_name__ attribute</a>.</li> <li>Pull request: <a class="reference external" href="https://github.com/python/cpython/pull/111703">Add %T format to PyUnicode_FromFormat()</a>.</li> </ul> </section> <section id="backwards-compatibility"> <h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2> <p>Changes proposed in this PEP are backward compatible.</p> <p>Adding new C APIs has no effect on the backward compatibility. Existing C APIs are left unchanged. No Python API is changed.</p> <p>Replacing the type short name with the type fully qualified name is only recommended in new C code. No longer truncating type names is only recommended in new C code. Existing code should be left unchanged and so remains backward compatible. There is no recommendation for Python code.</p> </section> <section id="rejected-ideas"> <h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2> <section id="id1"> <h3><a class="toc-backref" href="#id1" role="doc-backlink">Add type.__fully_qualified_name__ attribute</a></h3> <p>Add <code class="docutils literal notranslate"><span class="pre">type.__fully_qualified_name__</span></code> read-only attribute, the fully qualified name of a type: similar to <code class="docutils literal notranslate"><span class="pre">f&quot;{type.__module__}.{type.__qualname__}&quot;</span></code>, or <code class="docutils literal notranslate"><span class="pre">type.__qualname__</span></code> if <code class="docutils literal notranslate"><span class="pre">type.__module__</span></code> is not a string or is equal to <code class="docutils literal notranslate"><span class="pre">&quot;builtins&quot;</span></code> or is equal to <code class="docutils literal notranslate"><span class="pre">&quot;__main__&quot;</span></code>.</p> <p>The <code class="docutils literal notranslate"><span class="pre">type.__repr__()</span></code> is left unchanged, it only omits the module if the module is equal to <code class="docutils literal notranslate"><span class="pre">&quot;builtins&quot;</span></code>.</p> <p>This change was <a class="reference external" href="https://discuss.python.org/t/pep-737-unify-type-name-formatting/39872/51">rejected by the Steering Council</a>:</p> <blockquote> <div>We can see the usefulness of the C API changes proposed by the PEP and would likely accept those changes as is.<p>We see less justification for the Python level changes. We especially question the need for <code class="docutils literal notranslate"><span class="pre">__fully_qualified_name__</span></code>.</p> </div></blockquote> <p>Thomas Wouters added:</p> <blockquote> <div>If there really is a desire for formatting types the exact same way the C API does it, a utility function would make more sense to me, personally, than <code class="docutils literal notranslate"><span class="pre">type.__format__</span></code>, but I think the SC could be persuaded given some concrete use-cases.</div></blockquote> </section> <section id="add-type-format-method"> <h3><a class="toc-backref" href="#add-type-format-method" role="doc-backlink">Add type.__format__() method</a></h3> <p>Add <code class="docutils literal notranslate"><span class="pre">type.__format__()</span></code> method with the following formats:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">N</span></code> formats the type <strong>fully qualified name</strong> (<code class="docutils literal notranslate"><span class="pre">type.__fully_qualified_name__</span></code>); <code class="docutils literal notranslate"><span class="pre">N</span></code> stands for <strong>N</strong>ame.</li> <li><code class="docutils literal notranslate"><span class="pre">#N</span></code> (alternative form) formats the type <strong>fully qualified name</strong> using the <strong>colon</strong> (<code class="docutils literal notranslate"><span class="pre">:</span></code>) separator, instead of the dot separator (<code class="docutils literal notranslate"><span class="pre">.</span></code>), between the module name and the qualified name.</li> </ul> <p>Examples using f-string:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">datetime</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">datetime</span><span class="o">.</span><span class="n">timedelta</span><span class="si">:</span><span class="s2">N</span><span class="si">}</span><span class="s2">&quot;</span> <span class="c1"># fully qualified name</span> <span class="go">&#39;datetime.timedelta&#39;</span> <span class="gp">&gt;&gt;&gt; </span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">datetime</span><span class="o">.</span><span class="n">timedelta</span><span class="si">:</span><span class="s2">#N</span><span class="si">}</span><span class="s2">&quot;</span> <span class="c1"># fully qualified name, colon separator</span> <span class="go">&#39;datetime:timedelta&#39;</span> </pre></div> </div> <p>The colon (<code class="docutils literal notranslate"><span class="pre">:</span></code>) separator used by the <code class="docutils literal notranslate"><span class="pre">#N</span></code> format eliminates guesswork when you want to import the name, see <code class="docutils literal notranslate"><span class="pre">pkgutil.resolve_name()</span></code>, <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">inspect</span></code> command line interface, and <code class="docutils literal notranslate"><span class="pre">setuptools</span></code> entry points.</p> <p>This change was <a class="reference external" href="https://discuss.python.org/t/pep-737-unify-type-name-formatting/39872/52">rejected by the Steering Council</a>.</p> </section> <section id="change-str-type"> <h3><a class="toc-backref" href="#change-str-type" role="doc-backlink">Change str(type)</a></h3> <p>The <code class="docutils literal notranslate"><span class="pre">type.__str__()</span></code> method can be modified to format a type name differently. For example, it can return the type fully qualified name.</p> <p>The problem is that it’s a backward incompatible change. For example, <code class="docutils literal notranslate"><span class="pre">enum</span></code>, <code class="docutils literal notranslate"><span class="pre">functools</span></code>, <code class="docutils literal notranslate"><span class="pre">optparse</span></code>, <code class="docutils literal notranslate"><span class="pre">pdb</span></code> and <code class="docutils literal notranslate"><span class="pre">xmlrpc.server</span></code> modules of the standard library have to be updated. <code class="docutils literal notranslate"><span class="pre">test_dataclasses</span></code>, <code class="docutils literal notranslate"><span class="pre">test_descrtut</span></code> and <code class="docutils literal notranslate"><span class="pre">test_cmd_line_script</span></code> tests have to be updated as well.</p> <p>See the <a class="reference external" href="https://github.com/python/cpython/pull/112129">pull request: type(str) returns the fully qualified name</a>.</p> </section> <section id="add-t-formatter-to-get-an-object-type"> <h3><a class="toc-backref" href="#add-t-formatter-to-get-an-object-type" role="doc-backlink">Add !t formatter to get an object type</a></h3> <p>Use <code class="docutils literal notranslate"><span class="pre">f&quot;{obj!t:T}&quot;</span></code> to format <code class="docutils literal notranslate"><span class="pre">type(obj).__fully_qualified_name__</span></code>, similar to <code class="docutils literal notranslate"><span class="pre">f&quot;{type(obj):T}&quot;</span></code>.</p> <p>When the <code class="docutils literal notranslate"><span class="pre">!t</span></code> formatter was proposed in 2018, <a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/message/BMIW3FEB77OS7OB3YYUUDUBITPWLRG3U/">Eric Smith was strongly opposed to this</a>; Eric is the author of the f-string <a class="pep reference internal" href="../pep-0498/" title="PEP 498 – Literal String Interpolation">PEP 498</a> “Literal String Interpolation”.</p> </section> <section id="add-formats-to-str-args"> <h3><a class="toc-backref" href="#add-formats-to-str-args" role="doc-backlink">Add formats to str % args</a></h3> <p>It was proposed to add formats to format a type name in <code class="docutils literal notranslate"><span class="pre">str</span> <span class="pre">%</span> <span class="pre">arg</span></code>. For example, add the <code class="docutils literal notranslate"><span class="pre">%T</span></code> format to format a type fully qualified name.</p> <p>Nowadays, f-strings are preferred for new code.</p> </section> <section id="other-ways-to-format-type-names-in-c"> <h3><a class="toc-backref" href="#other-ways-to-format-type-names-in-c" role="doc-backlink">Other ways to format type names in C</a></h3> <p>The <code class="docutils literal notranslate"><span class="pre">printf()</span></code> function supports multiple size modifiers: <code class="docutils literal notranslate"><span class="pre">hh</span></code> (<code class="docutils literal notranslate"><span class="pre">char</span></code>), <code class="docutils literal notranslate"><span class="pre">h</span></code> (<code class="docutils literal notranslate"><span class="pre">short</span></code>), <code class="docutils literal notranslate"><span class="pre">l</span></code> (<code class="docutils literal notranslate"><span class="pre">long</span></code>), <code class="docutils literal notranslate"><span class="pre">ll</span></code> (<code class="docutils literal notranslate"><span class="pre">long</span> <span class="pre">long</span></code>), <code class="docutils literal notranslate"><span class="pre">z</span></code> (<code class="docutils literal notranslate"><span class="pre">size_t</span></code>), <code class="docutils literal notranslate"><span class="pre">t</span></code> (<code class="docutils literal notranslate"><span class="pre">ptrdiff_t</span></code>) and <code class="docutils literal notranslate"><span class="pre">j</span></code> (<code class="docutils literal notranslate"><span class="pre">intmax_t</span></code>). The <code class="docutils literal notranslate"><span class="pre">PyUnicode_FromFormat()</span></code> function supports most of them.</p> <p>Proposed formats using <code class="docutils literal notranslate"><span class="pre">h</span></code> and <code class="docutils literal notranslate"><span class="pre">hh</span></code> length modifiers:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">%hhT</span></code> formats <code class="docutils literal notranslate"><span class="pre">type.__name__</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">%hT</span></code> formats <code class="docutils literal notranslate"><span class="pre">type.__qualname__</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">%T</span></code> formats <code class="docutils literal notranslate"><span class="pre">type.__fully_qualified_name__</span></code>.</li> </ul> <p>Length modifiers are used to specify the C type of the argument, not to change how an argument is formatted. The alternate form (<code class="docutils literal notranslate"><span class="pre">#</span></code>) changes how an argument is formatted. Here the argument C type is always <code class="docutils literal notranslate"><span class="pre">PyObject*</span></code>.</p> <p>Other proposed formats:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">%Q</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">%t</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">%lT</span></code> formats <code class="docutils literal notranslate"><span class="pre">type.__fully_qualified_name__</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">%Tn</span></code> formats <code class="docutils literal notranslate"><span class="pre">type.__name__</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">%Tq</span></code> formats <code class="docutils literal notranslate"><span class="pre">type.__qualname__</span></code>.</li> <li><code class="docutils literal notranslate"><span class="pre">%Tf</span></code> formats <code class="docutils literal notranslate"><span class="pre">type.__fully_qualified_name__</span></code>.</li> </ul> <p>Having more options to format type names can lead to inconsistencies between different modules and make the API more error prone.</p> <p>About the <code class="docutils literal notranslate"><span class="pre">%t</span></code> format, <code class="docutils literal notranslate"><span class="pre">printf()</span></code> now uses <code class="docutils literal notranslate"><span class="pre">t</span></code> as a length modifier for <code class="docutils literal notranslate"><span class="pre">ptrdiff_t</span></code> argument.</p> <p>The following APIs to be used to format a type:</p> <table class="docutils align-default"> <thead> <tr class="row-odd"><th class="head">C API</th> <th class="head">Python API</th> <th class="head">Format</th> </tr> </thead> <tbody> <tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">PyType_GetName()</span></code></td> <td><code class="docutils literal notranslate"><span class="pre">type.__name__</span></code></td> <td>Type <strong>short</strong> name.</td> </tr> <tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">PyType_GetQualName()</span></code></td> <td><code class="docutils literal notranslate"><span class="pre">type.__qualname__</span></code></td> <td>Type <strong>qualified</strong> name.</td> </tr> <tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">PyType_GetModuleName()</span></code></td> <td><code class="docutils literal notranslate"><span class="pre">type.__module__</span></code></td> <td>Type <strong>module</strong> name.</td> </tr> </tbody> </table> </section> <section id="use-t-format-with-py-type-pass-a-type"> <h3><a class="toc-backref" href="#use-t-format-with-py-type-pass-a-type" role="doc-backlink">Use %T format with Py_TYPE(): pass a type</a></h3> <p>It was proposed to pass a type to the <code class="docutils literal notranslate"><span class="pre">%T</span></code> format, like:</p> <div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyErr_Format</span><span class="p">(</span><span class="n">PyExc_TypeError</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;object type name: %T&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">obj</span><span class="p">));</span> </pre></div> </div> <p>The <code class="docutils literal notranslate"><span class="pre">Py_TYPE()</span></code> functions returns a borrowed reference. Just to format an error, using a borrowed reference to a type looks safe. In practice, it can lead to crash. Example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">gc</span> <span class="kn">import</span><span class="w"> </span><span class="nn">my_cext</span> <span class="k">class</span><span class="w"> </span><span class="nc">ClassA</span><span class="p">:</span> <span class="k">pass</span> <span class="k">def</span><span class="w"> </span><span class="nf">create_object</span><span class="p">():</span> <span class="k">class</span><span class="w"> </span><span class="nc">ClassB</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span> <span class="o">=</span> <span class="n">ClassA</span> <span class="n">gc</span><span class="o">.</span><span class="n">collect</span><span class="p">()</span> <span class="k">return</span> <span class="s2">&quot;ClassB repr&quot;</span> <span class="k">return</span> <span class="n">ClassB</span><span class="p">()</span> <span class="n">obj</span> <span class="o">=</span> <span class="n">create_object</span><span class="p">()</span> <span class="n">my_cext</span><span class="o">.</span><span class="n">func</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> </pre></div> </div> <p>where <code class="docutils literal notranslate"><span class="pre">my_cext.func()</span></code> is a C function which calls:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PyErr_Format</span><span class="p">(</span><span class="n">PyExc_ValueError</span><span class="p">,</span> <span class="s2">&quot;Unexpected value %R of type %T&quot;</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">Py_TYPE</span><span class="p">(</span><span class="n">obj</span><span class="p">));</span> </pre></div> </div> <p><code class="docutils literal notranslate"><span class="pre">PyErr_Format()</span></code> is called with a borrowed reference to <code class="docutils literal notranslate"><span class="pre">ClassB</span></code>. When <code class="docutils literal notranslate"><span class="pre">repr(obj)</span></code> is called by the <code class="docutils literal notranslate"><span class="pre">%R</span></code> format, the last reference to <code class="docutils literal notranslate"><span class="pre">ClassB</span></code> is removed and the class is deallocated. When the <code class="docutils literal notranslate"><span class="pre">%T</span></code> format is proceed, <code class="docutils literal notranslate"><span class="pre">Py_TYPE(obj)</span></code> is already a dangling pointer and Python does crash.</p> </section> <section id="other-proposed-apis-to-get-a-type-fully-qualified-name"> <h3><a class="toc-backref" href="#other-proposed-apis-to-get-a-type-fully-qualified-name" role="doc-backlink">Other proposed APIs to get a type fully qualified name</a></h3> <ul class="simple"> <li>Add <code class="docutils literal notranslate"><span class="pre">type.__fullyqualname__</span></code> attribute: name without underscore between words. Several dunders, including some of the most recently added ones, include an underscore in the word: <code class="docutils literal notranslate"><span class="pre">__class_getitem__</span></code>, <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code>, <code class="docutils literal notranslate"><span class="pre">__type_params__</span></code>, <code class="docutils literal notranslate"><span class="pre">__init_subclass__</span></code> and <code class="docutils literal notranslate"><span class="pre">__text_signature__</span></code>.</li> <li>Add <code class="docutils literal notranslate"><span class="pre">type.__fqn__</span></code> attribute: FQN name stands for <strong>F</strong>ully <strong>Q</strong>ualified <strong>N</strong>ame.</li> <li>Add <code class="docutils literal notranslate"><span class="pre">type.fully_qualified_name()</span></code> method. Methods added to <code class="docutils literal notranslate"><span class="pre">type</span></code> are inherited by all types and so can affect existing code.</li> <li>Add a function to the <code class="docutils literal notranslate"><span class="pre">inspect</span></code> module. Need to import the <code class="docutils literal notranslate"><span class="pre">inspect</span></code> module to use it.</li> </ul> </section> <section id="include-the-main-module-in-the-type-fully-qualified-name"> <h3><a class="toc-backref" href="#include-the-main-module-in-the-type-fully-qualified-name" role="doc-backlink">Include the __main__ module in the type fully qualified name</a></h3> <p>Format <code class="docutils literal notranslate"><span class="pre">type.__fully_qualified_name__</span></code> as <code class="docutils literal notranslate"><span class="pre">f&quot;{type.__module__}.{type.__qualname__}&quot;</span></code>, or <code class="docutils literal notranslate"><span class="pre">type.__qualname__</span></code> if <code class="docutils literal notranslate"><span class="pre">type.__module__</span></code> is not a string or is equal to <code class="docutils literal notranslate"><span class="pre">&quot;builtins&quot;</span></code>. Do not treat the <code class="docutils literal notranslate"><span class="pre">__main__</span></code> module differently: include it in the name.</p> <p>Existing code such as <code class="docutils literal notranslate"><span class="pre">type.__repr__()</span></code>, <code class="docutils literal notranslate"><span class="pre">collections.abc</span></code> and <code class="docutils literal notranslate"><span class="pre">unittest</span></code> modules format a type name with <code class="docutils literal notranslate"><span class="pre">f'{obj.__module__}.{obj.__qualname__}'</span></code> and only omit the module part if the module is equal to <code class="docutils literal notranslate"><span class="pre">builtins</span></code>.</p> <p>Only the <code class="docutils literal notranslate"><span class="pre">traceback</span></code> and <code class="docutils literal notranslate"><span class="pre">pdb</span></code> modules also omit the module if it’s equal to <code class="docutils literal notranslate"><span class="pre">&quot;builtins&quot;</span></code> or <code class="docutils literal notranslate"><span class="pre">&quot;__main__&quot;</span></code>.</p> <p>The <code class="docutils literal notranslate"><span class="pre">type.__fully_qualified_name__</span></code> attribute omits the <code class="docutils literal notranslate"><span class="pre">__main__</span></code> module to produce shorter names for a common case: types defined in a script run with <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">script.py</span></code>. For debugging, the <code class="docutils literal notranslate"><span class="pre">repr()</span></code> function can be used on a type, it includes the <code class="docutils literal notranslate"><span class="pre">__main__</span></code> module in the type name. Or use <code class="docutils literal notranslate"><span class="pre">f&quot;{type.__module__}.{type.__qualname__}&quot;</span></code> format to always include the module name, even for the <code class="docutils literal notranslate"><span class="pre">&quot;builtins&quot;</span></code> module.</p> <p>Example of script:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MyType</span><span class="p">:</span> <span class="k">pass</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;name: </span><span class="si">{</span><span class="n">MyType</span><span class="o">.</span><span class="n">__fully_qualified_name__</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;repr: </span><span class="si">{</span><span class="nb">repr</span><span class="p">(</span><span class="n">MyType</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> </pre></div> </div> <p>Output:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>name: MyType repr: &lt;class &#39;__main__.MyType&#39;&gt; </pre></div> </div> </section> </section> <section id="discussions"> <h2><a class="toc-backref" href="#discussions" role="doc-backlink">Discussions</a></h2> <ul class="simple"> <li>Discourse: <a class="reference external" href="https://discuss.python.org/t/pep-737-unify-type-name-formatting/39872">PEP 737 – Unify type name formatting</a> (2023).</li> <li>Discourse: <a class="reference external" href="https://discuss.python.org/t/enhance-type-name-formatting-when-raising-an-exception-add-t-format-in-c-and-add-type-fullyqualname/38129">Enhance type name formatting when raising an exception: add %T format in C, and add type.__fullyqualname__</a> (2023).</li> <li>Issue: <a class="reference external" href="https://github.com/python/cpython/issues/111696">PyUnicode_FromFormat(): Add %T format to format the type name of an object</a> (2023).</li> <li>Issue: <a class="reference external" href="https://github.com/python/cpython/issues/105970">C API: Investigate how the PyTypeObject members can be removed from the public C API</a> (2023).</li> <li>python-dev thread: <a class="reference external" href="https://mail.python.org/archives/list/python-dev&#64;python.org/thread/HKYUMTVHNBVB5LJNRMZ7TPUQKGKAERCJ/">bpo-34595: How to format a type name?</a> (2018).</li> <li>Issue: <a class="reference external" href="https://github.com/python/cpython/issues/78776">PyUnicode_FromFormat(): add %T format for an object type name</a> (2018).</li> <li>Issue: <a class="reference external" href="https://github.com/python/cpython/issues/55042">Replace %.100s by %s in PyErr_Format(): the arbitrary limit of 500 bytes is outdated</a> (2011).</li> </ul> </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-0737.rst">https://github.com/python/peps/blob/main/peps/pep-0737.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0737.rst">2024-06-01 20:53:34 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="#rationale">Rationale</a><ul> <li><a class="reference internal" href="#standard-library">Standard library</a><ul> <li><a class="reference internal" href="#python-code">Python code</a></li> <li><a class="reference internal" href="#c-code">C code</a></li> </ul> </li> <li><a class="reference internal" href="#using-pytypeobject-tp-name-is-inconsistent-with-python">Using PyTypeObject.tp_name is inconsistent with Python</a></li> <li><a class="reference internal" href="#limited-c-api">Limited C API</a></li> <li><a class="reference internal" href="#truncating-type-names-in-c">Truncating type names in C</a></li> </ul> </li> <li><a class="reference internal" href="#specification">Specification</a><ul> <li><a class="reference internal" href="#add-pytype-getfullyqualifiedname-function">Add PyType_GetFullyQualifiedName() function</a></li> <li><a class="reference internal" href="#add-pytype-getmodulename-function">Add PyType_GetModuleName() function</a></li> <li><a class="reference internal" href="#add-formats-to-pyunicode-fromformat">Add formats to PyUnicode_FromFormat()</a></li> <li><a class="reference internal" href="#formats-summary">Formats Summary</a></li> <li><a class="reference internal" href="#recommend-using-the-type-fully-qualified-name">Recommend using the type fully qualified name</a></li> <li><a class="reference internal" href="#recommend-not-truncating-type-names">Recommend not truncating type names</a></li> </ul> </li> <li><a class="reference internal" href="#implementation">Implementation</a></li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul> <li><a class="reference internal" href="#id1">Add type.__fully_qualified_name__ attribute</a></li> <li><a class="reference internal" href="#add-type-format-method">Add type.__format__() method</a></li> <li><a class="reference internal" href="#change-str-type">Change str(type)</a></li> <li><a class="reference internal" href="#add-t-formatter-to-get-an-object-type">Add !t formatter to get an object type</a></li> <li><a class="reference internal" href="#add-formats-to-str-args">Add formats to str % args</a></li> <li><a class="reference internal" href="#other-ways-to-format-type-names-in-c">Other ways to format type names in C</a></li> <li><a class="reference internal" href="#use-t-format-with-py-type-pass-a-type">Use %T format with Py_TYPE(): pass a type</a></li> <li><a class="reference internal" href="#other-proposed-apis-to-get-a-type-fully-qualified-name">Other proposed APIs to get a type fully qualified name</a></li> <li><a class="reference internal" href="#include-the-main-module-in-the-type-fully-qualified-name">Include the __main__ module in the type fully qualified name</a></li> </ul> </li> <li><a class="reference internal" href="#discussions">Discussions</a></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-0737.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