1071 lines
110 KiB
HTML
1071 lines
110 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<html lang="en" data-content_root="../">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<meta property="og:title" content="annotationlib — Functionality for introspecting annotations" />
|
||
<meta property="og:type" content="website" />
|
||
<meta property="og:url" content="https://docs.python.org/3/library/annotationlib.html" />
|
||
<meta property="og:site_name" content="Python documentation" />
|
||
<meta property="og:description" content="Source code: Lib/annotationlib.py The annotationlib module provides tools for introspecting annotations on modules, classes, and functions. Annotations are lazily evaluated and often contain forwar..." />
|
||
<meta property="og:image" content="_static/og-image.png" />
|
||
<meta property="og:image:alt" content="Python documentation" />
|
||
<meta name="description" content="Source code: Lib/annotationlib.py The annotationlib module provides tools for introspecting annotations on modules, classes, and functions. Annotations are lazily evaluated and often contain forwar..." />
|
||
<meta name="theme-color" content="#3776ab">
|
||
<meta property="og:image:width" content="200">
|
||
<meta property="og:image:height" content="200">
|
||
|
||
<title>annotationlib — Functionality for introspecting annotations — Python 3.15.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
||
<link rel="stylesheet" type="text/css" href="../_static/classic.css?v=234b1a7c" />
|
||
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?v=48df1187" />
|
||
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=0fc419ee" />
|
||
|
||
<script src="../_static/documentation_options.js?v=0fe728b1"></script>
|
||
<script src="../_static/doctools.js?v=9bcbadda"></script>
|
||
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
|
||
|
||
<script src="../_static/sidebar.js"></script>
|
||
|
||
<link rel="search" type="application/opensearchdescription+xml"
|
||
title="Search within Python 3.15.0 documentation"
|
||
href="../_static/opensearch.xml"/>
|
||
<link rel="author" title="About these documents" href="../about.html" />
|
||
<link rel="index" title="Index" href="../genindex.html" />
|
||
<link rel="search" title="Search" href="../search.html" />
|
||
<link rel="copyright" title="Copyright" href="../copyright.html" />
|
||
<link rel="next" title="site — Site-specific configuration hook" href="site.html" />
|
||
<link rel="prev" title="inspect — Inspect live objects" href="inspect.html" />
|
||
|
||
|
||
<link rel="canonical" href="https://docs.python.org/3/library/annotationlib.html">
|
||
|
||
|
||
|
||
|
||
<style>
|
||
@media only screen {
|
||
table.full-width-table {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
<link rel="stylesheet" href="../_static/pydoctheme_dark.css" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
|
||
<link rel="shortcut icon" type="image/png" href="../_static/py.svg">
|
||
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
||
<script type="text/javascript" src="../_static/menu.js"></script>
|
||
<script type="text/javascript" src="../_static/search-focus.js"></script>
|
||
<script type="text/javascript" src="../_static/themetoggle.js"></script>
|
||
<script type="text/javascript" src="../_static/rtd_switcher.js"></script>
|
||
<meta name="readthedocs-addons-api-version" content="1">
|
||
|
||
</head>
|
||
<body>
|
||
<div class="mobile-nav">
|
||
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
|
||
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu">
|
||
<nav class="nav-content" role="navigation">
|
||
<label for="menuToggler" class="toggler__label">
|
||
<span></span>
|
||
</label>
|
||
<span class="nav-items-wrapper">
|
||
<a href="https://www.python.org/" class="nav-logo">
|
||
<img src="../_static/py.svg" alt="Python logo">
|
||
</a>
|
||
<span class="version_switcher_placeholder"></span>
|
||
<form role="search" class="search" action="../search.html" method="get">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
|
||
<path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
|
||
</svg>
|
||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q">
|
||
<input type="submit" value="Go">
|
||
</form>
|
||
</span>
|
||
</nav>
|
||
<div class="menu-wrapper">
|
||
<nav class="menu" role="navigation" aria-label="main navigation">
|
||
<div class="language_switcher_placeholder"></div>
|
||
|
||
<label class="theme-selector-label">
|
||
Theme
|
||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||
<option value="auto" selected>Auto</option>
|
||
<option value="light">Light</option>
|
||
<option value="dark">Dark</option>
|
||
</select>
|
||
</label>
|
||
<div>
|
||
<h3><a href="../contents.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">annotationlib</span></code> — Functionality for introspecting annotations</a><ul>
|
||
<li><a class="reference internal" href="#annotation-semantics">Annotation semantics</a></li>
|
||
<li><a class="reference internal" href="#classes">Classes</a></li>
|
||
<li><a class="reference internal" href="#functions">Functions</a></li>
|
||
<li><a class="reference internal" href="#recipes">Recipes</a><ul>
|
||
<li><a class="reference internal" href="#using-annotations-in-a-metaclass">Using annotations in a metaclass</a></li>
|
||
<li><a class="reference internal" href="#creating-a-custom-callable-annotate-function">Creating a custom callable annotate function</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#limitations-of-the-string-format">Limitations of the <code class="docutils literal notranslate"><span class="pre">STRING</span></code> format</a></li>
|
||
<li><a class="reference internal" href="#limitations-of-the-forwardref-format">Limitations of the <code class="docutils literal notranslate"><span class="pre">FORWARDREF</span></code> format</a></li>
|
||
<li><a class="reference internal" href="#security-implications-of-introspecting-annotations">Security implications of introspecting annotations</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
</div>
|
||
<div>
|
||
<h4>Previous topic</h4>
|
||
<p class="topless"><a href="inspect.html"
|
||
title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">inspect</span></code> — Inspect live objects</a></p>
|
||
</div>
|
||
<div>
|
||
<h4>Next topic</h4>
|
||
<p class="topless"><a href="site.html"
|
||
title="next chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">site</span></code> — Site-specific configuration hook</a></p>
|
||
</div>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const title = document.querySelector('meta[property="og:title"]').content;
|
||
const elements = document.querySelectorAll('.improvepage');
|
||
const pageurl = window.location.href.split('?')[0];
|
||
elements.forEach(element => {
|
||
const url = new URL(element.href.split('?')[0].replace("-nojs", ""));
|
||
url.searchParams.set('pagetitle', title);
|
||
url.searchParams.set('pageurl', pageurl);
|
||
url.searchParams.set('pagesource', "library/annotationlib.rst");
|
||
element.href = url.toString();
|
||
});
|
||
});
|
||
</script>
|
||
<div role="note" aria-label="source link">
|
||
<h3>This page</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">Report a bug</a></li>
|
||
<li><a class="improvepage" href="../improve-page-nojs.html">Improve this page</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.15/Doc/library/annotationlib.rst?plain=1"
|
||
rel="nofollow">Show source
|
||
</a>
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div class="related" role="navigation" aria-label="Related">
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="General Index"
|
||
accesskey="I">index</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="right" >
|
||
<a href="site.html" title="site — Site-specific configuration hook"
|
||
accesskey="N">next</a> |</li>
|
||
<li class="right" >
|
||
<a href="inspect.html" title="inspect — Inspect live objects"
|
||
accesskey="P">previous</a> |</li>
|
||
|
||
<li class="root-icon"><img src="../_static/py.svg" alt="Python logo" style="vertical-align: middle; margin-top: -1px"></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.15.0 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >The Python standard library</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="python.html" accesskey="U">Python Runtime Services</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href=""><code class="xref py py-mod docutils literal notranslate"><span class="pre">annotationlib</span></code> — Functionality for introspecting annotations</a></li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box">
|
||
<input type="submit" value="Go">
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
<li class="right">
|
||
<label class="theme-selector-label">
|
||
Theme
|
||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||
<option value="auto" selected>Auto</option>
|
||
<option value="light">Light</option>
|
||
<option value="dark">Dark</option>
|
||
</select>
|
||
</label> |</li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section id="module-annotationlib">
|
||
<span id="annotationlib-functionality-for-introspecting-annotations"></span><h1><code class="xref py py-mod docutils literal notranslate"><span class="pre">annotationlib</span></code> — Functionality for introspecting annotations<a class="headerlink" href="#module-annotationlib" title="Link to this heading">¶</a></h1>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">Added in version 3.14.</span></p>
|
||
</div>
|
||
<p><strong>Source code:</strong> <a class="extlink-source reference external" href="https://github.com/python/cpython/tree/3.15/Lib/annotationlib.py">Lib/annotationlib.py</a></p>
|
||
<hr class="docutils" />
|
||
<p>The <code class="xref py py-mod docutils literal notranslate"><span class="pre">annotationlib</span></code> module provides tools for introspecting
|
||
<a class="reference internal" href="../glossary.html#term-annotation"><span class="xref std std-term">annotations</span></a> on modules, classes, and functions.</p>
|
||
<p>Annotations are <a class="reference internal" href="../reference/executionmodel.html#lazy-evaluation"><span class="std std-ref">lazily evaluated</span></a> and often contain
|
||
forward references to objects that are not yet defined when the annotation
|
||
is created. This module provides a set of low-level tools that can be used to retrieve annotations in a reliable way, even
|
||
in the presence of forward references and other edge cases.</p>
|
||
<p>This module supports retrieving annotations in three main formats
|
||
(see <a class="reference internal" href="#annotationlib.Format" title="annotationlib.Format"><code class="xref py py-class docutils literal notranslate"><span class="pre">Format</span></code></a>), each of which works best for different use cases:</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="#annotationlib.Format.VALUE" title="annotationlib.Format.VALUE"><code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE</span></code></a> evaluates the annotations and returns their value.
|
||
This is most straightforward to work with, but it may raise errors,
|
||
for example if the annotations contain references to undefined names.</p></li>
|
||
<li><p><a class="reference internal" href="#annotationlib.Format.FORWARDREF" title="annotationlib.Format.FORWARDREF"><code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code></a> returns <a class="reference internal" href="#annotationlib.ForwardRef" title="annotationlib.ForwardRef"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code></a> objects
|
||
for annotations that cannot be resolved, allowing you to inspect the
|
||
annotations without evaluating them. This is useful when you need to
|
||
work with annotations that may contain unresolved forward references.</p></li>
|
||
<li><p><a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a> returns the annotations as a string, similar
|
||
to how it would appear in the source file. This is useful for documentation
|
||
generators that want to display annotations in a readable way.</p></li>
|
||
</ul>
|
||
<p>The <a class="reference internal" href="#annotationlib.get_annotations" title="annotationlib.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotations()</span></code></a> function is the main entry point for
|
||
retrieving annotations. Given a function, class, or module, it returns
|
||
an annotations dictionary in the requested format. This module also provides
|
||
functionality for working directly with the <a class="reference internal" href="../glossary.html#term-annotate-function"><span class="xref std std-term">annotate function</span></a>
|
||
that is used to evaluate annotations, such as <a class="reference internal" href="#annotationlib.get_annotate_from_class_namespace" title="annotationlib.get_annotate_from_class_namespace"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotate_from_class_namespace()</span></code></a>
|
||
and <a class="reference internal" href="#annotationlib.call_annotate_function" title="annotationlib.call_annotate_function"><code class="xref py py-func docutils literal notranslate"><span class="pre">call_annotate_function()</span></code></a>, as well as the
|
||
<a class="reference internal" href="#annotationlib.call_evaluate_function" title="annotationlib.call_evaluate_function"><code class="xref py py-func docutils literal notranslate"><span class="pre">call_evaluate_function()</span></code></a> function for working with
|
||
<a class="reference internal" href="../glossary.html#term-evaluate-function"><span class="xref std std-term">evaluate functions</span></a>.</p>
|
||
<div class="admonition caution">
|
||
<p class="admonition-title">Caution</p>
|
||
<p>Most functionality in this module can execute arbitrary code; see
|
||
<a class="reference internal" href="#annotationlib-security"><span class="std std-ref">the security section</span></a> for more information.</p>
|
||
</div>
|
||
<div class="admonition seealso">
|
||
<p class="admonition-title">See also</p>
|
||
<p><span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-0649/"><strong>PEP 649</strong></a> proposed the current model for how annotations work in Python.</p>
|
||
<p><span class="target" id="index-1"></span><a class="pep reference external" href="https://peps.python.org/pep-0749/"><strong>PEP 749</strong></a> expanded on various aspects of <span class="target" id="index-2"></span><a class="pep reference external" href="https://peps.python.org/pep-0649/"><strong>PEP 649</strong></a> and introduced the
|
||
<code class="xref py py-mod docutils literal notranslate"><span class="pre">annotationlib</span></code> module.</p>
|
||
<p><a class="reference internal" href="../howto/annotations.html#annotations-howto"><span class="std std-ref">Annotations Best Practices</span></a> provides best practices for working with
|
||
annotations.</p>
|
||
<p><a class="extlink-pypi reference external" href="https://pypi.org/project/typing-extensions/">typing-extensions</a> provides a backport of <a class="reference internal" href="#annotationlib.get_annotations" title="annotationlib.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotations()</span></code></a>
|
||
that works on earlier versions of Python.</p>
|
||
</div>
|
||
<section id="annotation-semantics">
|
||
<h2>Annotation semantics<a class="headerlink" href="#annotation-semantics" title="Link to this heading">¶</a></h2>
|
||
<p>The way annotations are evaluated has changed over the history of Python 3,
|
||
and currently still depends on a <a class="reference internal" href="../reference/simple_stmts.html#future"><span class="std std-ref">future import</span></a>.
|
||
There have been execution models for annotations:</p>
|
||
<ul class="simple">
|
||
<li><p><em>Stock semantics</em> (default in Python 3.0 through 3.13; see <span class="target" id="index-3"></span><a class="pep reference external" href="https://peps.python.org/pep-3107/"><strong>PEP 3107</strong></a>
|
||
and <span class="target" id="index-4"></span><a class="pep reference external" href="https://peps.python.org/pep-0526/"><strong>PEP 526</strong></a>): Annotations are evaluated eagerly, as they are
|
||
encountered in the source code.</p></li>
|
||
<li><p><em>Stringified annotations</em> (used with <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">annotations</span></code>
|
||
in Python 3.7 and newer; see <span class="target" id="index-5"></span><a class="pep reference external" href="https://peps.python.org/pep-0563/"><strong>PEP 563</strong></a>): Annotations are stored as
|
||
strings only.</p></li>
|
||
<li><p><em>Deferred evaluation</em> (default in Python 3.14 and newer; see <span class="target" id="index-6"></span><a class="pep reference external" href="https://peps.python.org/pep-0649/"><strong>PEP 649</strong></a> and
|
||
<span class="target" id="index-7"></span><a class="pep reference external" href="https://peps.python.org/pep-0749/"><strong>PEP 749</strong></a>): Annotations are evaluated lazily, only when they are accessed.</p></li>
|
||
</ul>
|
||
<p>As an example, consider the following program:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">func</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="n">Cls</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
|
||
|
||
<span class="k">class</span><span class="w"> </span><span class="nc">Cls</span><span class="p">:</span> <span class="k">pass</span>
|
||
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">func</span><span class="o">.</span><span class="vm">__annotations__</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This will behave as follows:</p>
|
||
<ul class="simple">
|
||
<li><p>Under stock semantics (Python 3.13 and earlier), it will throw a
|
||
<a class="reference internal" href="../builtins/exceptions.html#NameError" title="NameError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">NameError</span></code></a> at the line where <code class="docutils literal notranslate"><span class="pre">func</span></code> is defined,
|
||
because <code class="docutils literal notranslate"><span class="pre">Cls</span></code> is an undefined name at that point.</p></li>
|
||
<li><p>Under stringified annotations (if <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">annotations</span></code>
|
||
is used), it will print <code class="docutils literal notranslate"><span class="pre">{'a':</span> <span class="pre">'Cls',</span> <span class="pre">'return':</span> <span class="pre">'None'}</span></code>.</p></li>
|
||
<li><p>Under deferred evaluation (Python 3.14 and later), it will print
|
||
<code class="docutils literal notranslate"><span class="pre">{'a':</span> <span class="pre"><class</span> <span class="pre">'Cls'>,</span> <span class="pre">'return':</span> <span class="pre">None}</span></code>.</p></li>
|
||
</ul>
|
||
<p>Stock semantics were used when function annotations were first introduced
|
||
in Python 3.0 (by <span class="target" id="index-8"></span><a class="pep reference external" href="https://peps.python.org/pep-3107/"><strong>PEP 3107</strong></a>) because this was the simplest, most obvious
|
||
way to implement annotations. The same execution model was used when variable
|
||
annotations were introduced in Python 3.6 (by <span class="target" id="index-9"></span><a class="pep reference external" href="https://peps.python.org/pep-0526/"><strong>PEP 526</strong></a>). However,
|
||
stock semantics caused problems when using annotations as type hints,
|
||
such as a need to refer to names that are not yet defined when the
|
||
annotation is encountered. In addition, there were performance problems
|
||
with executing annotations at module import time. Therefore, in Python 3.7,
|
||
<span class="target" id="index-10"></span><a class="pep reference external" href="https://peps.python.org/pep-0563/"><strong>PEP 563</strong></a> introduced the ability to store annotations as strings using the
|
||
<code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">annotations</span></code> syntax. The plan at the time was to
|
||
eventually make this behavior the default, but a problem appeared:
|
||
stringified annotations are more difficult to process for those who
|
||
introspect annotations at runtime. An alternative proposal, <span class="target" id="index-11"></span><a class="pep reference external" href="https://peps.python.org/pep-0649/"><strong>PEP 649</strong></a>,
|
||
introduced the third execution model, deferred evaluation, and was implemented
|
||
in Python 3.14. Stringified annotations are still used if
|
||
<code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">annotations</span></code> is present, but this behavior will
|
||
eventually be removed.</p>
|
||
</section>
|
||
<section id="classes">
|
||
<h2>Classes<a class="headerlink" href="#classes" title="Link to this heading">¶</a></h2>
|
||
<dl class="py class">
|
||
<dt class="sig sig-object py" id="annotationlib.Format">
|
||
<em class="property"><span class="k"><span class="pre">class</span></span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">annotationlib.</span></span><span class="sig-name descname"><span class="pre">Format</span></span><a class="headerlink" href="#annotationlib.Format" title="Link to this definition">¶</a></dt>
|
||
<dd><p>An <a class="reference internal" href="enum.html#enum.IntEnum" title="enum.IntEnum"><code class="xref py py-class docutils literal notranslate"><span class="pre">IntEnum</span></code></a> describing the formats in which annotations
|
||
can be returned. Members of the enum, or their equivalent integer values,
|
||
can be passed to <a class="reference internal" href="#annotationlib.get_annotations" title="annotationlib.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotations()</span></code></a> and other functions in this
|
||
module, as well as to <a class="reference internal" href="../reference/datamodel.html#object.__annotate__" title="object.__annotate__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__annotate__</span></code></a> functions.</p>
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="annotationlib.Format.VALUE">
|
||
<span class="sig-name descname"><span class="pre">VALUE</span></span><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">1</span></em><a class="headerlink" href="#annotationlib.Format.VALUE" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Values are the result of evaluating the annotation expressions.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="annotationlib.Format.VALUE_WITH_FAKE_GLOBALS">
|
||
<span class="sig-name descname"><span class="pre">VALUE_WITH_FAKE_GLOBALS</span></span><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">2</span></em><a class="headerlink" href="#annotationlib.Format.VALUE_WITH_FAKE_GLOBALS" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Special value used to signal that an annotate function is being
|
||
evaluated in a special environment with fake globals. When passed this
|
||
value, annotate functions should either return the same value as for
|
||
the <a class="reference internal" href="#annotationlib.Format.VALUE" title="annotationlib.Format.VALUE"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Format.VALUE</span></code></a> format, or raise <a class="reference internal" href="../builtins/exceptions.html#NotImplementedError" title="NotImplementedError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">NotImplementedError</span></code></a>
|
||
to signal that they do not support execution in this environment.
|
||
This format is only used internally and should not be passed to
|
||
the functions in this module.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="annotationlib.Format.FORWARDREF">
|
||
<span class="sig-name descname"><span class="pre">FORWARDREF</span></span><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">3</span></em><a class="headerlink" href="#annotationlib.Format.FORWARDREF" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Values are real annotation values (as per <a class="reference internal" href="#annotationlib.Format.VALUE" title="annotationlib.Format.VALUE"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Format.VALUE</span></code></a> format)
|
||
for defined values, and <a class="reference internal" href="#annotationlib.ForwardRef" title="annotationlib.ForwardRef"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code></a> proxies for undefined
|
||
values. Real objects may contain references to <code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code>
|
||
proxy objects.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="annotationlib.Format.STRING">
|
||
<span class="sig-name descname"><span class="pre">STRING</span></span><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">4</span></em><a class="headerlink" href="#annotationlib.Format.STRING" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Values are the text string of the annotation as it appears in the
|
||
source code, up to modifications including, but not restricted to,
|
||
whitespace normalizations and constant values optimizations.</p>
|
||
<p>The exact values of these strings may change in future versions of Python.</p>
|
||
</dd></dl>
|
||
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">Added in version 3.14.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="py class">
|
||
<dt class="sig sig-object py" id="annotationlib.ForwardRef">
|
||
<em class="property"><span class="k"><span class="pre">class</span></span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">annotationlib.</span></span><span class="sig-name descname"><span class="pre">ForwardRef</span></span><a class="headerlink" href="#annotationlib.ForwardRef" title="Link to this definition">¶</a></dt>
|
||
<dd><p>A proxy object for forward references in annotations.</p>
|
||
<p>Instances of this class are returned when the <a class="reference internal" href="#annotationlib.Format.FORWARDREF" title="annotationlib.Format.FORWARDREF"><code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code></a>
|
||
format is used and annotations contain a name that cannot be resolved.
|
||
This can happen when a forward reference is used in an annotation, such as
|
||
when a class is referenced before it is defined.</p>
|
||
<dl class="py attribute">
|
||
<dt class="sig sig-object py" id="annotationlib.ForwardRef.__forward_arg__">
|
||
<span class="sig-name descname"><span class="pre">__forward_arg__</span></span><a class="headerlink" href="#annotationlib.ForwardRef.__forward_arg__" title="Link to this definition">¶</a></dt>
|
||
<dd><p>A string containing the code that was evaluated to produce the
|
||
<code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code>. The string may not be exactly equivalent
|
||
to the original source.</p>
|
||
</dd></dl>
|
||
|
||
<dl class="py method">
|
||
<dt class="sig sig-object py" id="annotationlib.ForwardRef.evaluate">
|
||
<span class="sig-name descname"><span class="pre">evaluate</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">owner</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">globals</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">locals</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">type_params</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">format</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">Format.VALUE</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#annotationlib.ForwardRef.evaluate" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Evaluate the forward reference, returning its value.</p>
|
||
<p>If the <em>format</em> argument is <a class="reference internal" href="#annotationlib.Format.VALUE" title="annotationlib.Format.VALUE"><code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE</span></code></a> (the default),
|
||
this method may throw an exception, such as <a class="reference internal" href="../builtins/exceptions.html#NameError" title="NameError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">NameError</span></code></a>, if the forward
|
||
reference refers to a name that cannot be resolved. The arguments to this
|
||
method can be used to provide bindings for names that would otherwise
|
||
be undefined. If the <em>format</em> argument is <a class="reference internal" href="#annotationlib.Format.FORWARDREF" title="annotationlib.Format.FORWARDREF"><code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code></a>,
|
||
the method will never throw an exception, but may return a <code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code>
|
||
instance. For example, if the forward reference object contains the code
|
||
<code class="docutils literal notranslate"><span class="pre">list[undefined]</span></code>, where <code class="docutils literal notranslate"><span class="pre">undefined</span></code> is a name that is not defined,
|
||
evaluating it with the <code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code> format will return
|
||
<code class="docutils literal notranslate"><span class="pre">list[ForwardRef('undefined')]</span></code>. If the <em>format</em> argument is
|
||
<a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a>, the method will return <a class="reference internal" href="#annotationlib.ForwardRef.__forward_arg__" title="annotationlib.ForwardRef.__forward_arg__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__forward_arg__</span></code></a>.</p>
|
||
<p>The <em>owner</em> parameter provides the preferred mechanism for passing scope
|
||
information to this method. The owner of a <code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code> is the
|
||
object that contains the annotation from which the <code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code>
|
||
derives, such as a module object, type object, or function object.</p>
|
||
<p>The <em>globals</em>, <em>locals</em>, and <em>type_params</em> parameters provide a more precise
|
||
mechanism for influencing the names that are available when the <code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code>
|
||
is evaluated. <em>globals</em> and <em>locals</em> are passed to <a class="reference internal" href="../builtins/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>, representing
|
||
the global and local namespaces in which the name is evaluated.
|
||
The <em>type_params</em> parameter is relevant for objects created using the native
|
||
syntax for <a class="reference internal" href="../reference/compound_stmts.html#generic-classes"><span class="std std-ref">generic classes</span></a> and <a class="reference internal" href="../reference/compound_stmts.html#generic-functions"><span class="std std-ref">functions</span></a>.
|
||
It is a tuple of <a class="reference internal" href="../reference/compound_stmts.html#type-params"><span class="std std-ref">type parameters</span></a> that are in scope
|
||
while the forward reference is being evaluated. For example, if evaluating a
|
||
<code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code> retrieved from an annotation found in the class namespace
|
||
of a generic class <code class="docutils literal notranslate"><span class="pre">C</span></code>, <em>type_params</em> should be set to <code class="docutils literal notranslate"><span class="pre">C.__type_params__</span></code>.</p>
|
||
<p><code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code> instances returned by <a class="reference internal" href="#annotationlib.get_annotations" title="annotationlib.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotations()</span></code></a>
|
||
retain references to information about the scope they originated from,
|
||
so calling this method with no further arguments may be sufficient to
|
||
evaluate such objects. <code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code> instances created by other
|
||
means may not have any information about their scope, so passing
|
||
arguments to this method may be necessary to evaluate them successfully.</p>
|
||
<p>If no <em>owner</em>, <em>globals</em>, <em>locals</em>, or <em>type_params</em> are provided and the
|
||
<code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code> does not contain information about its origin,
|
||
empty globals and locals dictionaries are used.</p>
|
||
</dd></dl>
|
||
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">Added in version 3.14.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="functions">
|
||
<h2>Functions<a class="headerlink" href="#functions" title="Link to this heading">¶</a></h2>
|
||
<dl class="py function">
|
||
<dt class="sig sig-object py" id="annotationlib.annotations_to_string">
|
||
<span class="sig-prename descclassname"><span class="pre">annotationlib.</span></span><span class="sig-name descname"><span class="pre">annotations_to_string</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">annotations</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#annotationlib.annotations_to_string" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Convert an annotations dict containing runtime values to a
|
||
dict containing only strings. If the values are not already strings,
|
||
they are converted using <a class="reference internal" href="#annotationlib.type_repr" title="annotationlib.type_repr"><code class="xref py py-func docutils literal notranslate"><span class="pre">type_repr()</span></code></a>.
|
||
This is meant as a helper for user-provided
|
||
annotate functions that support the <a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a> format but
|
||
do not have access to the code creating the annotations.</p>
|
||
<p>For example, this is used to implement the <a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a> format
|
||
for <a class="reference internal" href="typing.html#typing.TypedDict" title="typing.TypedDict"><code class="xref py py-class docutils literal notranslate"><span class="pre">typing.TypedDict</span></code></a> classes created through the functional syntax:</p>
|
||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </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">TypedDict</span>
|
||
<span class="gp">>>> </span><span class="n">Movie</span> <span class="o">=</span> <span class="n">TypedDict</span><span class="p">(</span><span class="s2">"movie"</span><span class="p">,</span> <span class="p">{</span><span class="s2">"name"</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="s2">"year"</span><span class="p">:</span> <span class="nb">int</span><span class="p">})</span>
|
||
<span class="gp">>>> </span><span class="n">get_annotations</span><span class="p">(</span><span class="n">Movie</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="n">Format</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span>
|
||
<span class="go">{'name': 'str', 'year': 'int'}</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">Added in version 3.14.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="py function">
|
||
<dt class="sig sig-object py" id="annotationlib.call_annotate_function">
|
||
<span class="sig-prename descclassname"><span class="pre">annotationlib.</span></span><span class="sig-name descname"><span class="pre">call_annotate_function</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">annotate</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">format</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">owner</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#annotationlib.call_annotate_function" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Call the <a class="reference internal" href="../glossary.html#term-annotate-function"><span class="xref std std-term">annotate function</span></a> <em>annotate</em> with the given <em>format</em>,
|
||
a member of the <a class="reference internal" href="#annotationlib.Format" title="annotationlib.Format"><code class="xref py py-class docutils literal notranslate"><span class="pre">Format</span></code></a> enum, and return the annotations
|
||
dictionary produced by the function.</p>
|
||
<p>This helper function is required because annotate functions generated by
|
||
the compiler for functions, classes, and modules only support
|
||
the <a class="reference internal" href="#annotationlib.Format.VALUE" title="annotationlib.Format.VALUE"><code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE</span></code></a> format when called directly.
|
||
To support other formats, this function calls the annotate function
|
||
in a special environment that allows it to produce annotations in the
|
||
other formats. This is a useful building block when implementing
|
||
functionality that needs to partially evaluate annotations while a class
|
||
is being constructed.</p>
|
||
<p><em>owner</em> is the object that owns the annotation function, usually
|
||
a function, class, or module. If provided, it is used in the
|
||
<a class="reference internal" href="#annotationlib.Format.FORWARDREF" title="annotationlib.Format.FORWARDREF"><code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code></a> format to produce a <a class="reference internal" href="#annotationlib.ForwardRef" title="annotationlib.ForwardRef"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code></a>
|
||
object that carries more information.</p>
|
||
<div class="admonition seealso">
|
||
<p class="admonition-title">See also</p>
|
||
<p><span class="target" id="index-12"></span><a class="pep reference external" href="https://peps.python.org/pep-0649/#the-stringizer-and-the-fake-globals-environment"><strong>PEP 649</strong></a>
|
||
contains an explanation of the implementation technique used by this
|
||
function.</p>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">Added in version 3.14.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="py function">
|
||
<dt class="sig sig-object py" id="annotationlib.call_evaluate_function">
|
||
<span class="sig-prename descclassname"><span class="pre">annotationlib.</span></span><span class="sig-name descname"><span class="pre">call_evaluate_function</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">evaluate</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">format</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">owner</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#annotationlib.call_evaluate_function" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Call the <a class="reference internal" href="../glossary.html#term-evaluate-function"><span class="xref std std-term">evaluate function</span></a> <em>evaluate</em> with the given <em>format</em>,
|
||
a member of the <a class="reference internal" href="#annotationlib.Format" title="annotationlib.Format"><code class="xref py py-class docutils literal notranslate"><span class="pre">Format</span></code></a> enum, and return the value produced by
|
||
the function. This is similar to <a class="reference internal" href="#annotationlib.call_annotate_function" title="annotationlib.call_annotate_function"><code class="xref py py-func docutils literal notranslate"><span class="pre">call_annotate_function()</span></code></a>,
|
||
but the latter always returns a dictionary mapping strings to annotations,
|
||
while this function returns a single value.</p>
|
||
<p>This is intended for use with the evaluate functions generated for lazily
|
||
evaluated elements related to type aliases and type parameters:</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="typing.html#typing.TypeAliasType.evaluate_value" title="typing.TypeAliasType.evaluate_value"><code class="xref py py-meth docutils literal notranslate"><span class="pre">typing.TypeAliasType.evaluate_value()</span></code></a>, the value of type aliases</p></li>
|
||
<li><p><a class="reference internal" href="typing.html#typing.TypeVar.evaluate_bound" title="typing.TypeVar.evaluate_bound"><code class="xref py py-meth docutils literal notranslate"><span class="pre">typing.TypeVar.evaluate_bound()</span></code></a>, the bound of type variables</p></li>
|
||
<li><p><a class="reference internal" href="typing.html#typing.TypeVar.evaluate_constraints" title="typing.TypeVar.evaluate_constraints"><code class="xref py py-meth docutils literal notranslate"><span class="pre">typing.TypeVar.evaluate_constraints()</span></code></a>, the constraints of
|
||
type variables</p></li>
|
||
<li><p><a class="reference internal" href="typing.html#typing.TypeVar.evaluate_default" title="typing.TypeVar.evaluate_default"><code class="xref py py-meth docutils literal notranslate"><span class="pre">typing.TypeVar.evaluate_default()</span></code></a>, the default value of
|
||
type variables</p></li>
|
||
<li><p><a class="reference internal" href="typing.html#typing.ParamSpec.evaluate_default" title="typing.ParamSpec.evaluate_default"><code class="xref py py-meth docutils literal notranslate"><span class="pre">typing.ParamSpec.evaluate_default()</span></code></a>, the default value of
|
||
parameter specifications</p></li>
|
||
<li><p><a class="reference internal" href="typing.html#typing.TypeVarTuple.evaluate_default" title="typing.TypeVarTuple.evaluate_default"><code class="xref py py-meth docutils literal notranslate"><span class="pre">typing.TypeVarTuple.evaluate_default()</span></code></a>, the default value of
|
||
type variable tuples</p></li>
|
||
</ul>
|
||
<p><em>owner</em> is the object that owns the evaluate function, such as the type
|
||
alias or type variable object.</p>
|
||
<p><em>format</em> can be used to control the format in which the value is returned:</p>
|
||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">type</span> <span class="n">Alias</span> <span class="o">=</span> <span class="n">undefined</span>
|
||
<span class="gp">>>> </span><span class="n">call_evaluate_function</span><span class="p">(</span><span class="n">Alias</span><span class="o">.</span><span class="n">evaluate_value</span><span class="p">,</span> <span class="n">Format</span><span class="o">.</span><span class="n">VALUE</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="c">...</span>
|
||
<span class="gr">NameError</span>: <span class="n">name 'undefined' is not defined</span>
|
||
<span class="gp">>>> </span><span class="n">call_evaluate_function</span><span class="p">(</span><span class="n">Alias</span><span class="o">.</span><span class="n">evaluate_value</span><span class="p">,</span> <span class="n">Format</span><span class="o">.</span><span class="n">FORWARDREF</span><span class="p">)</span>
|
||
<span class="go">ForwardRef('undefined')</span>
|
||
<span class="gp">>>> </span><span class="n">call_evaluate_function</span><span class="p">(</span><span class="n">Alias</span><span class="o">.</span><span class="n">evaluate_value</span><span class="p">,</span> <span class="n">Format</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span>
|
||
<span class="go">'undefined'</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">Added in version 3.14.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="py function">
|
||
<dt class="sig sig-object py" id="annotationlib.get_annotate_from_class_namespace">
|
||
<span class="sig-prename descclassname"><span class="pre">annotationlib.</span></span><span class="sig-name descname"><span class="pre">get_annotate_from_class_namespace</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">namespace</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#annotationlib.get_annotate_from_class_namespace" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Retrieve the <a class="reference internal" href="../glossary.html#term-annotate-function"><span class="xref std std-term">annotate function</span></a> from a class namespace dictionary <em>namespace</em>.
|
||
Return <code class="xref py py-const docutils literal notranslate"><span class="pre">None</span></code> if the namespace does not contain an annotate function.
|
||
This is primarily useful before the class has been fully created (e.g., in a metaclass);
|
||
after the class exists, the annotate function can be retrieved with <code class="docutils literal notranslate"><span class="pre">cls.__annotate__</span></code>.
|
||
See <a class="reference internal" href="#annotationlib-metaclass"><span class="std std-ref">below</span></a> for an example using this function in a metaclass.</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">Added in version 3.14.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="py function">
|
||
<dt class="sig sig-object py" id="annotationlib.get_annotations">
|
||
<span class="sig-prename descclassname"><span class="pre">annotationlib.</span></span><span class="sig-name descname"><span class="pre">get_annotations</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">obj</span></span></em>, <em class="sig-param"><span class="keyword-only-separator o"><abbr title="Keyword-only parameters separator (PEP 3102)"><span class="pre">*</span></abbr></span></em>, <em class="sig-param"><span class="n"><span class="pre">globals</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">locals</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">eval_str</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">format</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">Format.VALUE</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#annotationlib.get_annotations" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Compute the annotations dict for an object.</p>
|
||
<p><em>obj</em> may be a callable, class, module, or other object with
|
||
<a class="reference internal" href="../reference/datamodel.html#object.__annotate__" title="object.__annotate__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__annotate__</span></code></a> or <a class="reference internal" href="../reference/datamodel.html#object.__annotations__" title="object.__annotations__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__annotations__</span></code></a> attributes.
|
||
Passing any other object raises <a class="reference internal" href="../builtins/exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a>.</p>
|
||
<p>The <em>format</em> parameter controls the format in which annotations are returned,
|
||
and must be a member of the <a class="reference internal" href="#annotationlib.Format" title="annotationlib.Format"><code class="xref py py-class docutils literal notranslate"><span class="pre">Format</span></code></a> enum or its integer equivalent.
|
||
The different formats work as follows:</p>
|
||
<ul class="simple">
|
||
<li><p>VALUE: <code class="xref py py-attr docutils literal notranslate"><span class="pre">object.__annotations__</span></code> is tried first; if that does not exist,
|
||
the <code class="xref py py-attr docutils literal notranslate"><span class="pre">object.__annotate__</span></code> function is called if it exists.</p></li>
|
||
<li><p>FORWARDREF: If <code class="xref py py-attr docutils literal notranslate"><span class="pre">object.__annotations__</span></code> exists and can be evaluated successfully,
|
||
it is used; otherwise, the <code class="xref py py-attr docutils literal notranslate"><span class="pre">object.__annotate__</span></code> function is called. If it
|
||
does not exist either, <code class="xref py py-attr docutils literal notranslate"><span class="pre">object.__annotations__</span></code> is tried again and any error
|
||
from accessing it is re-raised.</p>
|
||
<ul>
|
||
<li><p>When calling <code class="xref py py-attr docutils literal notranslate"><span class="pre">object.__annotate__</span></code> it is first called with <a class="reference internal" href="#annotationlib.Format.FORWARDREF" title="annotationlib.Format.FORWARDREF"><code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code></a>.
|
||
If this is not implemented, it will then check if <a class="reference internal" href="#annotationlib.Format.VALUE_WITH_FAKE_GLOBALS" title="annotationlib.Format.VALUE_WITH_FAKE_GLOBALS"><code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE_WITH_FAKE_GLOBALS</span></code></a>
|
||
is supported and use that in the fake globals environment.
|
||
If neither of these formats are supported, it will fall back to using <a class="reference internal" href="#annotationlib.Format.VALUE" title="annotationlib.Format.VALUE"><code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE</span></code></a>.
|
||
If <code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE</span></code> fails, the error from this call will be raised.</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p>STRING: If <code class="xref py py-attr docutils literal notranslate"><span class="pre">object.__annotate__</span></code> exists, it is called first;
|
||
otherwise, <code class="xref py py-attr docutils literal notranslate"><span class="pre">object.__annotations__</span></code> is used and stringified
|
||
using <a class="reference internal" href="#annotationlib.annotations_to_string" title="annotationlib.annotations_to_string"><code class="xref py py-func docutils literal notranslate"><span class="pre">annotations_to_string()</span></code></a>.</p>
|
||
<ul>
|
||
<li><p>When calling <code class="xref py py-attr docutils literal notranslate"><span class="pre">object.__annotate__</span></code> it is first called with <a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a>.
|
||
If this is not implemented, it will then check if <a class="reference internal" href="#annotationlib.Format.VALUE_WITH_FAKE_GLOBALS" title="annotationlib.Format.VALUE_WITH_FAKE_GLOBALS"><code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE_WITH_FAKE_GLOBALS</span></code></a>
|
||
is supported and use that in the fake globals environment.
|
||
If neither of these formats are supported, it will fall back to using <a class="reference internal" href="#annotationlib.Format.VALUE" title="annotationlib.Format.VALUE"><code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE</span></code></a>
|
||
with the result converted using <a class="reference internal" href="#annotationlib.annotations_to_string" title="annotationlib.annotations_to_string"><code class="xref py py-func docutils literal notranslate"><span class="pre">annotations_to_string()</span></code></a>.
|
||
If <code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE</span></code> fails, the error from this call will be raised.</p></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<p>Returns a dict. <code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotations()</span></code> returns a new dict every time
|
||
it’s called; calling it twice on the same object will return two
|
||
different but equivalent dicts.</p>
|
||
<p>This function handles several details for you:</p>
|
||
<ul class="simple">
|
||
<li><p>If <em>eval_str</em> is true, values of type <code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code> will
|
||
be un-stringized using <a class="reference internal" href="../builtins/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>. This is intended
|
||
for use with stringized annotations
|
||
(<code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">annotations</span></code>). It is an error
|
||
to set <em>eval_str</em> to true with formats other than <a class="reference internal" href="#annotationlib.Format.VALUE" title="annotationlib.Format.VALUE"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Format.VALUE</span></code></a>.</p></li>
|
||
<li><p>If <em>obj</em> doesn’t have an annotations dict, returns an
|
||
empty dict. (Functions and methods always have an
|
||
annotations dict; classes, modules, and other types of
|
||
callables may not.)</p></li>
|
||
<li><p>Ignores inherited annotations on classes, as well as annotations
|
||
on metaclasses. If a class
|
||
doesn’t have its own annotations dict, returns an empty dict.</p></li>
|
||
<li><p>All accesses to object members and dict values are done
|
||
using <code class="docutils literal notranslate"><span class="pre">getattr()</span></code> and <code class="docutils literal notranslate"><span class="pre">dict.get()</span></code> for safety.</p></li>
|
||
</ul>
|
||
<p><em>eval_str</em> controls whether or not values of type <code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code> are
|
||
replaced with the result of calling <a class="reference internal" href="../builtins/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a> on those values:</p>
|
||
<ul class="simple">
|
||
<li><p>If eval_str is true, <a class="reference internal" href="../builtins/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a> is called on values of type
|
||
<code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code>. (Note that <code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotations()</span></code> doesn’t catch
|
||
exceptions; if <code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code> raises an exception, it will unwind
|
||
the stack past the <code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotations()</span></code> call.)</p></li>
|
||
<li><p>If <em>eval_str</em> is false (the default), values of type <code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code> are
|
||
unchanged.</p></li>
|
||
</ul>
|
||
<p><em>globals</em> and <em>locals</em> are passed in to <a class="reference internal" href="../builtins/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>; see the documentation
|
||
for <code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code> for more information. If <em>globals</em> or <em>locals</em>
|
||
is <code class="xref py py-const docutils literal notranslate"><span class="pre">None</span></code>, this function may replace that value with a
|
||
context-specific default, contingent on <code class="docutils literal notranslate"><span class="pre">type(obj)</span></code>:</p>
|
||
<ul class="simple">
|
||
<li><p>If <em>obj</em> is a module, <em>globals</em> defaults to <code class="docutils literal notranslate"><span class="pre">obj.__dict__</span></code>.</p></li>
|
||
<li><p>If <em>obj</em> is a class, <em>globals</em> defaults to
|
||
<code class="docutils literal notranslate"><span class="pre">sys.modules[obj.__module__].__dict__</span></code> and <em>locals</em> defaults
|
||
to the <em>obj</em> class namespace.</p></li>
|
||
<li><p>If <em>obj</em> is a callable, <em>globals</em> defaults to
|
||
<a class="reference internal" href="../reference/datamodel.html#function.__globals__" title="function.__globals__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">obj.__globals__</span></code></a>,
|
||
although if <em>obj</em> is a wrapped function (using
|
||
<a class="reference internal" href="functools.html#functools.update_wrapper" title="functools.update_wrapper"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.update_wrapper()</span></code></a>) or a <a class="reference internal" href="functools.html#functools.partial" title="functools.partial"><code class="xref py py-class docutils literal notranslate"><span class="pre">functools.partial</span></code></a> object,
|
||
it is unwrapped until a non-wrapped function is found.</p></li>
|
||
</ul>
|
||
<p>Calling <code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotations()</span></code> is best practice for accessing the
|
||
annotations dict of any object. See <a class="reference internal" href="../howto/annotations.html#annotations-howto"><span class="std std-ref">Annotations Best Practices</span></a> for
|
||
more information on annotations best practices.</p>
|
||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">def</span><span class="w"> </span><span class="nf">f</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">float</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">pass</span>
|
||
<span class="gp">>>> </span><span class="n">get_annotations</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
||
<span class="go">{'a': <class 'int'>, 'b': <class 'str'>, 'return': <class 'float'>}</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">Added in version 3.14.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="py function">
|
||
<dt class="sig sig-object py" id="annotationlib.type_repr">
|
||
<span class="sig-prename descclassname"><span class="pre">annotationlib.</span></span><span class="sig-name descname"><span class="pre">type_repr</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">value</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#annotationlib.type_repr" title="Link to this definition">¶</a></dt>
|
||
<dd><p>Convert an arbitrary Python value to a format suitable for use by the
|
||
<a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a> format. This calls <a class="reference internal" href="../builtins/functions.html#repr" title="repr"><code class="xref py py-func docutils literal notranslate"><span class="pre">repr()</span></code></a> for most
|
||
objects, but has special handling for some objects, such as type objects.</p>
|
||
<p>This is meant as a helper for user-provided
|
||
annotate functions that support the <a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a> format but
|
||
do not have access to the code creating the annotations. It can also
|
||
be used to provide a user-friendly string representation for other
|
||
objects that contain values that are commonly encountered in annotations.</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">Added in version 3.14.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="recipes">
|
||
<h2>Recipes<a class="headerlink" href="#recipes" title="Link to this heading">¶</a></h2>
|
||
<section id="using-annotations-in-a-metaclass">
|
||
<span id="annotationlib-metaclass"></span><h3>Using annotations in a metaclass<a class="headerlink" href="#using-annotations-in-a-metaclass" title="Link to this heading">¶</a></h3>
|
||
<p>A <a class="reference internal" href="../reference/datamodel.html#metaclasses"><span class="std std-ref">metaclass</span></a> may want to inspect or even modify the annotations
|
||
in a class body during class creation. Doing so requires retrieving annotations
|
||
from the class namespace dictionary. For classes created with
|
||
<code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">annotations</span></code>, the annotations will be in the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>
|
||
key of the dictionary. For other classes with annotations,
|
||
<a class="reference internal" href="#annotationlib.get_annotate_from_class_namespace" title="annotationlib.get_annotate_from_class_namespace"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotate_from_class_namespace()</span></code></a> can be used to get the
|
||
annotate function, and <a class="reference internal" href="#annotationlib.call_annotate_function" title="annotationlib.call_annotate_function"><code class="xref py py-func docutils literal notranslate"><span class="pre">call_annotate_function()</span></code></a> can be used to call it and
|
||
retrieve the annotations. Using the <a class="reference internal" href="#annotationlib.Format.FORWARDREF" title="annotationlib.Format.FORWARDREF"><code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code></a> format will usually
|
||
be best, because this allows the annotations to refer to names that cannot yet be
|
||
resolved when the class is created.</p>
|
||
<p>To modify the annotations, it is best to create a wrapper annotate function
|
||
that calls the original annotate function, makes any necessary adjustments, and
|
||
returns the result.</p>
|
||
<p>Below is an example of a metaclass that filters out all <a class="reference internal" href="typing.html#typing.ClassVar" title="typing.ClassVar"><code class="xref py py-class docutils literal notranslate"><span class="pre">typing.ClassVar</span></code></a>
|
||
annotations from the class and puts them in a separate attribute:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">annotationlib</span>
|
||
<span class="kn">import</span><span class="w"> </span><span class="nn">typing</span>
|
||
|
||
<span class="k">class</span><span class="w"> </span><span class="nc">ClassVarSeparator</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="fm">__new__</span><span class="p">(</span><span class="n">mcls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">ns</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="s2">"__annotations__"</span> <span class="ow">in</span> <span class="n">ns</span><span class="p">:</span> <span class="c1"># from __future__ import annotations</span>
|
||
<span class="n">annotations</span> <span class="o">=</span> <span class="n">ns</span><span class="p">[</span><span class="s2">"__annotations__"</span><span class="p">]</span>
|
||
<span class="n">classvar_keys</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="n">key</span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">annotations</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
|
||
<span class="c1"># Use string comparison for simplicity; a more robust solution</span>
|
||
<span class="c1"># could use annotationlib.ForwardRef.evaluate</span>
|
||
<span class="k">if</span> <span class="n">value</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"ClassVar"</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
<span class="n">classvars</span> <span class="o">=</span> <span class="p">{</span><span class="n">key</span><span class="p">:</span> <span class="n">annotations</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">classvar_keys</span><span class="p">}</span>
|
||
<span class="n">ns</span><span class="p">[</span><span class="s2">"__annotations__"</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="n">key</span><span class="p">:</span> <span class="n">value</span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">annotations</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">classvar_keys</span>
|
||
<span class="p">}</span>
|
||
<span class="n">wrapped_annotate</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="k">elif</span> <span class="n">annotate</span> <span class="o">:=</span> <span class="n">annotationlib</span><span class="o">.</span><span class="n">get_annotate_from_class_namespace</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span>
|
||
<span class="n">annotations</span> <span class="o">=</span> <span class="n">annotationlib</span><span class="o">.</span><span class="n">call_annotate_function</span><span class="p">(</span>
|
||
<span class="n">annotate</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="n">annotationlib</span><span class="o">.</span><span class="n">Format</span><span class="o">.</span><span class="n">FORWARDREF</span>
|
||
<span class="p">)</span>
|
||
<span class="n">classvar_keys</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="n">key</span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">annotations</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="n">typing</span><span class="o">.</span><span class="n">get_origin</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="ow">is</span> <span class="n">typing</span><span class="o">.</span><span class="n">ClassVar</span>
|
||
<span class="p">}</span>
|
||
<span class="n">classvars</span> <span class="o">=</span> <span class="p">{</span><span class="n">key</span><span class="p">:</span> <span class="n">annotations</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">classvar_keys</span><span class="p">}</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">wrapped_annotate</span><span class="p">(</span><span class="nb">format</span><span class="p">):</span>
|
||
<span class="n">annos</span> <span class="o">=</span> <span class="n">annotationlib</span><span class="o">.</span><span class="n">call_annotate_function</span><span class="p">(</span><span class="n">annotate</span><span class="p">,</span> <span class="nb">format</span><span class="p">,</span> <span class="n">owner</span><span class="o">=</span><span class="n">typ</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="p">{</span><span class="n">key</span><span class="p">:</span> <span class="n">value</span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">annos</span><span class="o">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">classvar_keys</span><span class="p">}</span>
|
||
|
||
<span class="k">else</span><span class="p">:</span> <span class="c1"># no annotations</span>
|
||
<span class="n">classvars</span> <span class="o">=</span> <span class="p">{}</span>
|
||
<span class="n">wrapped_annotate</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="n">typ</span> <span class="o">=</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__new__</span><span class="p">(</span><span class="n">mcls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="n">wrapped_annotate</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="c1"># Wrap the original __annotate__ with a wrapper that removes ClassVars</span>
|
||
<span class="n">typ</span><span class="o">.</span><span class="n">__annotate__</span> <span class="o">=</span> <span class="n">wrapped_annotate</span>
|
||
<span class="n">typ</span><span class="o">.</span><span class="n">classvars</span> <span class="o">=</span> <span class="n">classvars</span> <span class="c1"># Store the ClassVars in a separate attribute</span>
|
||
<span class="k">return</span> <span class="n">typ</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="creating-a-custom-callable-annotate-function">
|
||
<h3>Creating a custom callable annotate function<a class="headerlink" href="#creating-a-custom-callable-annotate-function" title="Link to this heading">¶</a></h3>
|
||
<p>Custom <a class="reference internal" href="../glossary.html#term-annotate-function"><span class="xref std std-term">annotate functions</span></a> may be literal functions like those
|
||
automatically generated for functions, classes, and modules. Or, they may wish to utilise
|
||
the encapsulation provided by classes, in which case any <a class="reference internal" href="../glossary.html#term-callable"><span class="xref std std-term">callable</span></a> can be used as
|
||
an <span class="xref std std-term">annotate function</span>.</p>
|
||
<p>To provide the <a class="reference internal" href="#annotationlib.Format.VALUE" title="annotationlib.Format.VALUE"><code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE</span></code></a>, <a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a>, or
|
||
<a class="reference internal" href="#annotationlib.Format.FORWARDREF" title="annotationlib.Format.FORWARDREF"><code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code></a> formats directly, an <a class="reference internal" href="../glossary.html#term-annotate-function"><span class="xref std std-term">annotate function</span></a> must provide
|
||
the following attribute:</p>
|
||
<ul class="simple">
|
||
<li><p>A callable <code class="docutils literal notranslate"><span class="pre">__call__</span></code> with signature <code class="docutils literal notranslate"><span class="pre">__call__(format,</span> <span class="pre">/)</span> <span class="pre">-></span> <span class="pre">dict</span></code>, that does not
|
||
raise a <a class="reference internal" href="../builtins/exceptions.html#NotImplementedError" title="NotImplementedError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">NotImplementedError</span></code></a> when called with a supported format.</p></li>
|
||
</ul>
|
||
<p>To provide the <a class="reference internal" href="#annotationlib.Format.VALUE_WITH_FAKE_GLOBALS" title="annotationlib.Format.VALUE_WITH_FAKE_GLOBALS"><code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE_WITH_FAKE_GLOBALS</span></code></a> format, which is used to
|
||
automatically generate <a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a> or <a class="reference internal" href="#annotationlib.Format.FORWARDREF" title="annotationlib.Format.FORWARDREF"><code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code></a> if they are
|
||
not supported directly, <a class="reference internal" href="../glossary.html#term-annotate-function"><span class="xref std std-term">annotate functions</span></a> must provide the
|
||
following attributes:</p>
|
||
<ul class="simple">
|
||
<li><p>A callable <code class="docutils literal notranslate"><span class="pre">__call__</span></code> with signature <code class="docutils literal notranslate"><span class="pre">__call__(format,</span> <span class="pre">/)</span> <span class="pre">-></span> <span class="pre">dict</span></code>, that does not
|
||
raise a <a class="reference internal" href="../builtins/exceptions.html#NotImplementedError" title="NotImplementedError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">NotImplementedError</span></code></a> when called with
|
||
<a class="reference internal" href="#annotationlib.Format.VALUE_WITH_FAKE_GLOBALS" title="annotationlib.Format.VALUE_WITH_FAKE_GLOBALS"><code class="xref py py-attr docutils literal notranslate"><span class="pre">VALUE_WITH_FAKE_GLOBALS</span></code></a>.</p></li>
|
||
<li><p>A <a class="reference internal" href="../reference/datamodel.html#code-objects"><span class="std std-ref">code object</span></a> <code class="docutils literal notranslate"><span class="pre">__code__</span></code> containing the compiled code for the
|
||
annotate function.</p></li>
|
||
<li><p>Optional: A tuple of the function’s positional defaults <code class="docutils literal notranslate"><span class="pre">__kwdefaults__</span></code>, if the
|
||
function represented by <code class="docutils literal notranslate"><span class="pre">__code__</span></code> uses any positional defaults.</p></li>
|
||
<li><p>Optional: A dict of the function’s keyword defaults <code class="docutils literal notranslate"><span class="pre">__defaults__</span></code>, if the function
|
||
represented by <code class="docutils literal notranslate"><span class="pre">__code__</span></code> uses any keyword defaults.</p></li>
|
||
<li><p>Optional: All other <a class="reference internal" href="inspect.html#inspect-types"><span class="std std-ref">function attributes</span></a>.</p></li>
|
||
</ul>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Annotate</span><span class="p">:</span>
|
||
<span class="n">called_formats</span> <span class="o">=</span> <span class="p">[]</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">/</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">_self</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||
<span class="c1"># When called with fake globals, `_self` will be the</span>
|
||
<span class="c1"># actual self value, and `self` will be the format.</span>
|
||
<span class="k">if</span> <span class="n">_self</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="p">,</span> <span class="nb">format</span> <span class="o">=</span> <span class="n">_self</span><span class="p">,</span> <span class="bp">self</span>
|
||
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">called_formats</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">format</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="nb">format</span> <span class="o"><=</span> <span class="mi">2</span><span class="p">:</span> <span class="c1"># VALUE or VALUE_WITH_FAKE_GLOBALS</span>
|
||
<span class="k">return</span> <span class="p">{</span><span class="s2">"x"</span><span class="p">:</span> <span class="n">MyType</span><span class="p">}</span>
|
||
<span class="k">raise</span> <span class="ne">NotImplementedError</span>
|
||
|
||
<span class="vm">__code__</span> <span class="o">=</span> <span class="fm">__call__</span><span class="o">.</span><span class="vm">__code__</span>
|
||
<span class="vm">__defaults__</span> <span class="o">=</span> <span class="p">(</span><span class="kc">None</span><span class="p">,)</span>
|
||
<span class="vm">__kwdefaults__</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="k">lambda</span> <span class="bp">self</span><span class="p">:</span> <span class="nb">dict</span><span class="p">(</span><span class="n">_self</span><span class="o">=</span><span class="bp">self</span><span class="p">))</span>
|
||
|
||
<span class="vm">__globals__</span> <span class="o">=</span> <span class="p">{}</span>
|
||
<span class="n">__builtins__</span> <span class="o">=</span> <span class="p">{}</span>
|
||
<span class="vm">__closure__</span> <span class="o">=</span> <span class="kc">None</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This can then be called with:</p>
|
||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span><span class="w"> </span><span class="nn">annotationlib</span><span class="w"> </span><span class="kn">import</span> <span class="n">call_annotate_function</span><span class="p">,</span> <span class="n">Format</span>
|
||
<span class="gp">>>> </span><span class="n">call_annotate_function</span><span class="p">(</span><span class="n">Annotate</span><span class="p">(),</span> <span class="nb">format</span><span class="o">=</span><span class="n">Format</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span>
|
||
<span class="go">{'x': 'MyType'}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Or used as the annotate function for an object:</p>
|
||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span><span class="w"> </span><span class="nn">annotationlib</span><span class="w"> </span><span class="kn">import</span> <span class="n">get_annotations</span><span class="p">,</span> <span class="n">Format</span>
|
||
<span class="gp">>>> </span><span class="k">class</span><span class="w"> </span><span class="nc">C</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">pass</span>
|
||
<span class="gp">>>> </span><span class="n">C</span><span class="o">.</span><span class="n">__annotate__</span> <span class="o">=</span> <span class="n">Annotate</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">get_annotations</span><span class="p">(</span><span class="n">Annotate</span><span class="p">(),</span> <span class="nb">format</span><span class="o">=</span><span class="n">Format</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span>
|
||
<span class="go">{'x': 'MyType'}</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="limitations-of-the-string-format">
|
||
<h2>Limitations of the <code class="docutils literal notranslate"><span class="pre">STRING</span></code> format<a class="headerlink" href="#limitations-of-the-string-format" title="Link to this heading">¶</a></h2>
|
||
<p>The <a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a> format is meant to approximate the source code
|
||
of the annotation, but the implementation strategy used means that it is not
|
||
always possible to recover the exact source code.</p>
|
||
<p>First, the stringifier of course cannot recover any information that is not present in
|
||
the compiled code, including comments, whitespace, parenthesization, and operations that
|
||
get simplified by the compiler.</p>
|
||
<p>Second, the stringifier can intercept almost all operations that involve names looked
|
||
up in some scope, but it cannot intercept operations that operate fully on constants.
|
||
As a corollary, this also means it is not safe to request the <code class="docutils literal notranslate"><span class="pre">STRING</span></code> format on
|
||
untrusted code: Python is powerful enough that it is possible to achieve arbitrary
|
||
code execution even with no access to any globals or builtins. For example:</p>
|
||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">def</span><span class="w"> </span><span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="n">__base__</span><span class="o">.</span><span class="n">__subclasses__</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="fm">__init__</span><span class="o">.</span><span class="n">__builtins__</span><span class="p">[</span><span class="s2">"print"</span><span class="p">](</span><span class="s2">"Hello world"</span><span class="p">)):</span> <span class="k">pass</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">annotationlib</span><span class="o">.</span><span class="n">get_annotations</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="n">annotationlib</span><span class="o">.</span><span class="n">Format</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span>
|
||
<span class="go">Hello world</span>
|
||
<span class="go">{'x': 'None'}</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>This particular example works as of the time of writing, but it relies on
|
||
implementation details and is not guaranteed to work in the future.</p>
|
||
</div>
|
||
<p>Among the different kinds of expressions that exist in Python,
|
||
as represented by the <a class="reference internal" href="ast.html#module-ast" title="ast: Abstract Syntax Tree classes and manipulation."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ast</span></code></a> module, some expressions are supported,
|
||
meaning that the <code class="docutils literal notranslate"><span class="pre">STRING</span></code> format can generally recover the original source code;
|
||
others are unsupported, meaning that they may result in incorrect output or an error.</p>
|
||
<p>The following are supported (sometimes with caveats):</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="ast.html#ast.BinOp" title="ast.BinOp"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.BinOp</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.UnaryOp" title="ast.UnaryOp"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.UnaryOp</span></code></a></p>
|
||
<ul>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Invert" title="ast.Invert"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Invert</span></code></a> (<code class="docutils literal notranslate"><span class="pre">~</span></code>), <a class="reference internal" href="ast.html#ast.UAdd" title="ast.UAdd"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.UAdd</span></code></a> (<code class="docutils literal notranslate"><span class="pre">+</span></code>), and <a class="reference internal" href="ast.html#ast.USub" title="ast.USub"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.USub</span></code></a> (<code class="docutils literal notranslate"><span class="pre">-</span></code>) are supported</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Not" title="ast.Not"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Not</span></code></a> (<code class="docutils literal notranslate"><span class="pre">not</span></code>) is not supported</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Dict" title="ast.Dict"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Dict</span></code></a> (except when using <code class="docutils literal notranslate"><span class="pre">**</span></code> unpacking)</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Set" title="ast.Set"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Set</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Compare" title="ast.Compare"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Compare</span></code></a></p>
|
||
<ul>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Eq" title="ast.Eq"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Eq</span></code></a> and <a class="reference internal" href="ast.html#ast.NotEq" title="ast.NotEq"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.NotEq</span></code></a> are supported</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Lt" title="ast.Lt"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Lt</span></code></a>, <a class="reference internal" href="ast.html#ast.LtE" title="ast.LtE"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.LtE</span></code></a>, <a class="reference internal" href="ast.html#ast.Gt" title="ast.Gt"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Gt</span></code></a>, and <a class="reference internal" href="ast.html#ast.GtE" title="ast.GtE"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.GtE</span></code></a> are supported, but the operand may be flipped</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Is" title="ast.Is"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Is</span></code></a>, <a class="reference internal" href="ast.html#ast.IsNot" title="ast.IsNot"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.IsNot</span></code></a>, <a class="reference internal" href="ast.html#ast.In" title="ast.In"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.In</span></code></a>, and <a class="reference internal" href="ast.html#ast.NotIn" title="ast.NotIn"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.NotIn</span></code></a> are not supported</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Call" title="ast.Call"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Call</span></code></a> (except when using <code class="docutils literal notranslate"><span class="pre">**</span></code> unpacking)</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Constant" title="ast.Constant"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Constant</span></code></a> (though not the exact representation of the constant; for example, escape
|
||
sequences in strings are lost; hexadecimal numbers are converted to decimal)</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Attribute" title="ast.Attribute"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Attribute</span></code></a> (assuming the value is not a constant)</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Subscript" title="ast.Subscript"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Subscript</span></code></a> (assuming the value is not a constant)</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Starred" title="ast.Starred"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Starred</span></code></a> (<code class="docutils literal notranslate"><span class="pre">*</span></code> unpacking)</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Name" title="ast.Name"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Name</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.List" title="ast.List"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.List</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Tuple" title="ast.Tuple"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Tuple</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Slice" title="ast.Slice"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Slice</span></code></a></p></li>
|
||
</ul>
|
||
<p>The following are unsupported, but throw an informative error when encountered by the
|
||
stringifier:</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="ast.html#ast.FormattedValue" title="ast.FormattedValue"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.FormattedValue</span></code></a> (f-strings; error is not detected if conversion specifiers like <code class="docutils literal notranslate"><span class="pre">!r</span></code>
|
||
are used)</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.JoinedStr" title="ast.JoinedStr"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.JoinedStr</span></code></a> (f-strings)</p></li>
|
||
</ul>
|
||
<p>The following are unsupported and result in incorrect output:</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="ast.html#ast.BoolOp" title="ast.BoolOp"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.BoolOp</span></code></a> (<code class="docutils literal notranslate"><span class="pre">and</span></code> and <code class="docutils literal notranslate"><span class="pre">or</span></code>)</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.IfExp" title="ast.IfExp"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.IfExp</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Lambda" title="ast.Lambda"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Lambda</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.ListComp" title="ast.ListComp"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.ListComp</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.SetComp" title="ast.SetComp"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.SetComp</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.DictComp" title="ast.DictComp"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.DictComp</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.GeneratorExp" title="ast.GeneratorExp"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.GeneratorExp</span></code></a></p></li>
|
||
</ul>
|
||
<p>The following are disallowed in annotation scopes and therefore not relevant:</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="ast.html#ast.NamedExpr" title="ast.NamedExpr"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.NamedExpr</span></code></a> (<code class="docutils literal notranslate"><span class="pre">:=</span></code>)</p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Await" title="ast.Await"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Await</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.Yield" title="ast.Yield"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.Yield</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="ast.html#ast.YieldFrom" title="ast.YieldFrom"><code class="xref py py-class docutils literal notranslate"><span class="pre">ast.YieldFrom</span></code></a></p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="limitations-of-the-forwardref-format">
|
||
<h2>Limitations of the <code class="docutils literal notranslate"><span class="pre">FORWARDREF</span></code> format<a class="headerlink" href="#limitations-of-the-forwardref-format" title="Link to this heading">¶</a></h2>
|
||
<p>The <a class="reference internal" href="#annotationlib.Format.FORWARDREF" title="annotationlib.Format.FORWARDREF"><code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code></a> format aims to produce real values as much
|
||
as possible, with anything that cannot be resolved replaced with
|
||
<a class="reference internal" href="#annotationlib.ForwardRef" title="annotationlib.ForwardRef"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code></a> objects. It is affected by broadly the same Limitations
|
||
as the <a class="reference internal" href="#annotationlib.Format.STRING" title="annotationlib.Format.STRING"><code class="xref py py-attr docutils literal notranslate"><span class="pre">STRING</span></code></a> format: annotations that perform operations on
|
||
literals or that use unsupported expression types may raise exceptions when
|
||
evaluated using the <code class="xref py py-attr docutils literal notranslate"><span class="pre">FORWARDREF</span></code> format.</p>
|
||
<p>Below are a few examples of the behavior with unsupported expressions:</p>
|
||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span><span class="w"> </span><span class="nn">annotationlib</span><span class="w"> </span><span class="kn">import</span> <span class="n">get_annotations</span><span class="p">,</span> <span class="n">Format</span>
|
||
<span class="gp">>>> </span><span class="k">def</span><span class="w"> </span><span class="nf">zerodiv</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="mi">1</span> <span class="o">/</span> <span class="mi">0</span><span class="p">):</span> <span class="o">...</span>
|
||
<span class="gp">>>> </span><span class="n">get_annotations</span><span class="p">(</span><span class="n">zerodiv</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="n">Format</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">ZeroDivisionError</span>: <span class="n">division by zero</span>
|
||
<span class="gp">>>> </span><span class="n">get_annotations</span><span class="p">(</span><span class="n">zerodiv</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="n">Format</span><span class="o">.</span><span class="n">FORWARDREF</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="w"> </span><span class="c">...</span>
|
||
<span class="gr">ZeroDivisionError</span>: <span class="n">division by zero</span>
|
||
<span class="gp">>>> </span><span class="k">def</span><span class="w"> </span><span class="nf">ifexp</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">y</span> <span class="k">else</span> <span class="mi">0</span><span class="p">):</span> <span class="o">...</span>
|
||
<span class="gp">>>> </span><span class="n">get_annotations</span><span class="p">(</span><span class="n">ifexp</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="n">Format</span><span class="o">.</span><span class="n">STRING</span><span class="p">)</span>
|
||
<span class="go">{'x': '1'}</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="security-implications-of-introspecting-annotations">
|
||
<span id="annotationlib-security"></span><h2>Security implications of introspecting annotations<a class="headerlink" href="#security-implications-of-introspecting-annotations" title="Link to this heading">¶</a></h2>
|
||
<p>Much of the functionality in this module involves executing code related to annotations,
|
||
which can then do arbitrary things. For example,
|
||
<a class="reference internal" href="#annotationlib.get_annotations" title="annotationlib.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_annotations()</span></code></a> may call an arbitrary <a class="reference internal" href="../glossary.html#term-annotate-function"><span class="xref std std-term">annotate function</span></a>, and
|
||
<a class="reference internal" href="#annotationlib.ForwardRef.evaluate" title="annotationlib.ForwardRef.evaluate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">ForwardRef.evaluate()</span></code></a> may call <a class="reference internal" href="../builtins/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a> on an arbitrary string. Code contained
|
||
in an annotation might make arbitrary system calls, enter an infinite loop, or perform any
|
||
other operation. This is also true for any access of the <a class="reference internal" href="../reference/datamodel.html#object.__annotations__" title="object.__annotations__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__annotations__</span></code></a> attribute,
|
||
and for various functions in the <a class="reference internal" href="typing.html#module-typing" title="typing: Support for type hints (see :pep:`484`)."><code class="xref py py-mod docutils literal notranslate"><span class="pre">typing</span></code></a> module that work with annotations, such as
|
||
<a class="reference internal" href="typing.html#typing.get_type_hints" title="typing.get_type_hints"><code class="xref py py-func docutils literal notranslate"><span class="pre">typing.get_type_hints()</span></code></a>.</p>
|
||
<p>Any security issue arising from this also applies immediately after importing
|
||
code that may contain untrusted annotations: importing code can always cause arbitrary operations
|
||
to be performed. However, it is unsafe to accept strings or other input from an untrusted source and
|
||
pass them to any of the APIs for introspecting annotations, for example by editing an
|
||
<code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> dictionary or directly creating a <a class="reference internal" href="#annotationlib.ForwardRef" title="annotationlib.ForwardRef"><code class="xref py py-class docutils literal notranslate"><span class="pre">ForwardRef</span></code></a> object.</p>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
<div class="clearer"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||
<div class="sphinxsidebarwrapper">
|
||
<div>
|
||
<h3><a href="../contents.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#"><code class="xref py py-mod docutils literal notranslate"><span class="pre">annotationlib</span></code> — Functionality for introspecting annotations</a><ul>
|
||
<li><a class="reference internal" href="#annotation-semantics">Annotation semantics</a></li>
|
||
<li><a class="reference internal" href="#classes">Classes</a></li>
|
||
<li><a class="reference internal" href="#functions">Functions</a></li>
|
||
<li><a class="reference internal" href="#recipes">Recipes</a><ul>
|
||
<li><a class="reference internal" href="#using-annotations-in-a-metaclass">Using annotations in a metaclass</a></li>
|
||
<li><a class="reference internal" href="#creating-a-custom-callable-annotate-function">Creating a custom callable annotate function</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#limitations-of-the-string-format">Limitations of the <code class="docutils literal notranslate"><span class="pre">STRING</span></code> format</a></li>
|
||
<li><a class="reference internal" href="#limitations-of-the-forwardref-format">Limitations of the <code class="docutils literal notranslate"><span class="pre">FORWARDREF</span></code> format</a></li>
|
||
<li><a class="reference internal" href="#security-implications-of-introspecting-annotations">Security implications of introspecting annotations</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
</div>
|
||
<div>
|
||
<h4>Previous topic</h4>
|
||
<p class="topless"><a href="inspect.html"
|
||
title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">inspect</span></code> — Inspect live objects</a></p>
|
||
</div>
|
||
<div>
|
||
<h4>Next topic</h4>
|
||
<p class="topless"><a href="site.html"
|
||
title="next chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">site</span></code> — Site-specific configuration hook</a></p>
|
||
</div>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const title = document.querySelector('meta[property="og:title"]').content;
|
||
const elements = document.querySelectorAll('.improvepage');
|
||
const pageurl = window.location.href.split('?')[0];
|
||
elements.forEach(element => {
|
||
const url = new URL(element.href.split('?')[0].replace("-nojs", ""));
|
||
url.searchParams.set('pagetitle', title);
|
||
url.searchParams.set('pageurl', pageurl);
|
||
url.searchParams.set('pagesource', "library/annotationlib.rst");
|
||
element.href = url.toString();
|
||
});
|
||
});
|
||
</script>
|
||
<div role="note" aria-label="source link">
|
||
<h3>This page</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">Report a bug</a></li>
|
||
<li><a class="improvepage" href="../improve-page-nojs.html">Improve this page</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.15/Doc/library/annotationlib.rst?plain=1"
|
||
rel="nofollow">Show source
|
||
</a>
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div id="sidebarbutton" title="Collapse sidebar">
|
||
<span>«</span>
|
||
</div>
|
||
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="Related">
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="General Index"
|
||
>index</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="right" >
|
||
<a href="site.html" title="site — Site-specific configuration hook"
|
||
>next</a> |</li>
|
||
<li class="right" >
|
||
<a href="inspect.html" title="inspect — Inspect live objects"
|
||
>previous</a> |</li>
|
||
|
||
<li class="root-icon"><img src="../_static/py.svg" alt="Python logo" style="vertical-align: middle; margin-top: -1px"></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.15.0 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >The Python standard library</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="python.html" >Python Runtime Services</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href=""><code class="xref py py-mod docutils literal notranslate"><span class="pre">annotationlib</span></code> — Functionality for introspecting annotations</a></li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box">
|
||
<input type="submit" value="Go">
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
<li class="right">
|
||
<label class="theme-selector-label">
|
||
Theme
|
||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||
<option value="auto" selected>Auto</option>
|
||
<option value="light">Light</option>
|
||
<option value="dark">Dark</option>
|
||
</select>
|
||
</label> |</li>
|
||
|
||
</ul>
|
||
</div>
|
||
<div class="footer">
|
||
© <a href="../copyright.html">Copyright</a> 2001 Python Software Foundation.
|
||
<br>
|
||
This page is licensed under the Python Software Foundation License Version 2.
|
||
<br>
|
||
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
|
||
<br>
|
||
|
||
See <a href="/license.html">History and License</a> for more information.<br>
|
||
|
||
|
||
<br>
|
||
|
||
The Python Software Foundation is a non-profit corporation.
|
||
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
||
<br>
|
||
<br>
|
||
Last updated on Oct 09, 2026 (11:35 UTC).
|
||
|
||
<a href="/bugs.html">Found a bug</a>?
|
||
|
||
<br>
|
||
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
|
||
</div>
|
||
|
||
</body>
|
||
</html> |