<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Knowledge Bits - Python</title><link href="https://jwodder.github.io/kbits/" rel="alternate"></link><link href="https://jwodder.github.io/kbits/feeds/tag.python.atom.xml" rel="self"></link><id>https://jwodder.github.io/kbits/</id><updated>2023-09-28T00:00:00-04:00</updated><subtitle>References I wish I'd already found</subtitle><entry><title>Python Asynchronous Programming Fundamentals</title><link href="https://jwodder.github.io/kbits/posts/pyasync-fundam/" rel="alternate"></link><published>2022-05-29T00:00:00-04:00</published><updated>2022-07-17T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2022-05-29:/kbits/posts/pyasync-fundam/</id><summary type="html">&lt;p class="first last"&gt;Python introduced asynchronous programming capabilities in version 3.4 in
2014, with further notable improvements in almost every minor version
since.  However, to many Python programmers, this area of the language
remains esoteric, misunderstood, and underutilized.  This article aims to
elucidate the fundamental concepts of asynchronous programming as part of
the first step towards mastery.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Python introduced asynchronous programming capabilities in version 3.4 in 2014,
with further notable improvements in almost every minor version since.
However, to many Python programmers, this area of the language remains
esoteric, misunderstood, and underutilized.  This article aims to elucidate the
fundamental concepts of asynchronous programming as part of the first step
towards mastery.&lt;/p&gt;
&lt;p&gt;There won’t be many code samples in this article, but reading it should make it
easier to grok &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio.html"&gt;the asyncio documentation&lt;/a&gt; and figure out how to piece things
together.&lt;/p&gt;
&lt;div class="contents topic" id="contents"&gt;
&lt;p class="topic-title"&gt;Contents&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#high-level-overview" id="toc-entry-1"&gt;High-Level Overview&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#definitions" id="toc-entry-2"&gt;Definitions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#syntax" id="toc-entry-3"&gt;Syntax&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#type-annotations" id="toc-entry-4"&gt;Type Annotations&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#special-methods" id="toc-entry-5"&gt;Special Methods&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#historical-note-generator-based-coroutines" id="toc-entry-6"&gt;Historical Note: Generator-Based Coroutines&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#running-more-than-one-coroutine-at-once" id="toc-entry-7"&gt;Running More than One Coroutine at Once&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#exception-handling" id="toc-entry-8"&gt;Exception Handling&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#example-code" id="toc-entry-9"&gt;Example Code&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#asynchronous-programming-vs-threads" id="toc-entry-10"&gt;Asynchronous Programming vs. Threads&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#async-version-history" id="toc-entry-11"&gt;Async Version History&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#alternative-async-implementations" id="toc-entry-12"&gt;Alternative Async Implementations&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="high-level-overview"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;High-Level Overview&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Asynchronous programming provides a way to interleave execution of multiple
functions (&lt;a class="reference internal" href="#coroutines"&gt;coroutines&lt;/a&gt;) at once; at any given point, only one of the functions
is actually doing operations, while the others are waiting for things like
blocking I/O to complete (or, if the I/O has already completed, they’re waiting
for the current coroutine to be suspended so that they get a chance to resume).&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;In the Python standard library and all third-party async libraries that I
am aware of, the kinds of low-level operations that one can ultimately
suspend execution waiting for are almost exclusively I/O-related.  If
you’re seeking to add concurrency to CPU-bound code (e.g., anything
involving number crunching), you are likely to be better off using
multiprocessing instead.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Specifically, whenever execution of a currently-running coroutine reaches an
&lt;tt class="docutils literal"&gt;await&lt;/tt&gt; expression, the coroutine may be suspended, and another
previously-suspended coroutine may resume execution if what it was suspended on
has since returned a value.  Suspension can also happen when an &lt;tt class="docutils literal"&gt;async for&lt;/tt&gt;
block requests the next value from an asynchronous iterator or when an &lt;tt class="docutils literal"&gt;async
with&lt;/tt&gt; block is entered or exited, as these operations use &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; under the
hood.&lt;/p&gt;
&lt;p&gt;Note that, although multiple coroutines can be processed at once, effectively
finishing in any order, operations within a single coroutine continue to be
executed in the order they’re written.  For example, given the following code:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;g&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;amain&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amain&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;When &lt;tt class="docutils literal"&gt;await f()&lt;/tt&gt; is reached, &lt;tt class="docutils literal"&gt;amain()&lt;/tt&gt; will be suspended until &lt;tt class="docutils literal"&gt;f()&lt;/tt&gt; is
finished, and only after that will execution proceed to the next line, starting
coroutine &lt;tt class="docutils literal"&gt;g()&lt;/tt&gt;.  If you want to execute &lt;tt class="docutils literal"&gt;f()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;g()&lt;/tt&gt; concurrently,
you need to use &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task"&gt;&lt;tt class="docutils literal"&gt;asyncio.create_task()&lt;/tt&gt;&lt;/a&gt;, &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.gather"&gt;&lt;tt class="docutils literal"&gt;asyncio.gather()&lt;/tt&gt;&lt;/a&gt;, or similar.  See
&lt;a class="reference external" href="https://hynek.me/articles/waiting-in-asyncio/"&gt;this article&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;In general, coroutines can only be called or scheduled by other coroutines.  To
run a “top-level” coroutine from inside synchronous code (i.e., either inside a
non-coroutine function or at module level), the simplest &amp;amp; preferred way is to
use the &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.run"&gt;&lt;tt class="docutils literal"&gt;asyncio.run()&lt;/tt&gt;&lt;/a&gt; function introduced in Python 3.7.  Code meant to run on
older Pythons must use the lower-level &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_until_complete"&gt;&lt;tt class="docutils literal"&gt;loop.run_until_complete()&lt;/tt&gt;&lt;/a&gt; instead,
along with other loop methods for cleanup.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="definitions"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Definitions&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Asynchronous programming&lt;/em&gt; features the execution of multiple tasks
concurrently, with one task being run while waiting for others to complete.
Asynchronous programming in Python is an example of &lt;em&gt;cooperative multitasking&lt;/em&gt;
[&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Cooperative_multitasking"&gt;wiki&lt;/a&gt;], as it requires the running coroutines to cooperate and yield control
on their own; if the current coroutine goes for a long time without calling
&lt;tt class="docutils literal"&gt;await&lt;/tt&gt;, execution will remain on that coroutine all the while, and all other
coroutines in the thread will remain in a suspended state.  This is contrast to
the &lt;em&gt;preemptive multitasking&lt;/em&gt; [&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Preemption_(computing)"&gt;wiki&lt;/a&gt;] of multithreaded and multiprocess
programs, where the Python interpreter or OS scheduler decides on its own when
to switch between running contexts, with the points at which switches can occur
being difficult or impossible to predict in general.&lt;/p&gt;
&lt;p id="coroutines"&gt;A &lt;em&gt;coroutine function&lt;/em&gt; is a function defined with &lt;tt class="docutils literal"&gt;async def&lt;/tt&gt; instead of just
&lt;tt class="docutils literal"&gt;def&lt;/tt&gt;.  (In the context of asynchronous programming, a function defined with
just &lt;tt class="docutils literal"&gt;def&lt;/tt&gt; is called a &lt;em&gt;synchronous function&lt;/em&gt;.)  Only coroutine functions can
contain &lt;tt class="docutils literal"&gt;await&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;async for&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;async with&lt;/tt&gt; constructs, and, as of
Python 3.10, they cannot contain &lt;tt class="docutils literal"&gt;yield from&lt;/tt&gt; constructs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Note that just calling a coroutine function does not cause it to start
running; you need to either schedule it for concurrent execution with
&lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task"&gt;&lt;tt class="docutils literal"&gt;asyncio.create_task()&lt;/tt&gt;&lt;/a&gt; or similar or else &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; on it directly.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A &lt;em&gt;coroutine object&lt;/em&gt; is the result of calling a coroutine function.  This is
not the value &lt;tt class="docutils literal"&gt;return&lt;/tt&gt;ed (or &lt;tt class="docutils literal"&gt;raise&lt;/tt&gt;d) by the function; rather, it is a
pending computation that can be suspended &amp;amp; resumed at any point that the
coroutine function uses &lt;tt class="docutils literal"&gt;await&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;async for&lt;/tt&gt;, or &lt;tt class="docutils literal"&gt;async with&lt;/tt&gt;.  The
actual &lt;tt class="docutils literal"&gt;return&lt;/tt&gt; value or exception is obtained either by awaiting on the
coroutine object (possibly wrapped in a task and/or something like
&lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.gather"&gt;&lt;tt class="docutils literal"&gt;asyncio.gather()&lt;/tt&gt;&lt;/a&gt;) from within another coroutine function or by running it as a
“top-level” entry point using &lt;tt class="docutils literal"&gt;asyncio.run()&lt;/tt&gt; within synchronous code.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Asynchronous generators — coroutine functions that use &lt;tt class="docutils literal"&gt;yield&lt;/tt&gt; — are a bit
of an exception.  You do not &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; the result of the function; instead,
you iterate through it using either &lt;tt class="docutils literal"&gt;async for ... in &lt;span class="pre"&gt;...:&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;await
&lt;span class="pre"&gt;anext(...)&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Confusingly, both coroutine functions and coroutine objects can be referred
to as just “coroutines.”&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The actual scheduling of coroutine execution is managed by an &lt;em&gt;event loop&lt;/em&gt;.  An
event loop is created by &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.run"&gt;&lt;tt class="docutils literal"&gt;asyncio.run()&lt;/tt&gt;&lt;/a&gt; or &lt;tt class="docutils literal"&gt;asyncio.new_event_loop()&lt;/tt&gt;, handed
one or more coroutines and/or synchronous callbacks, and then set off to run
either forever or until completion of a “top-level” coroutine.  It’s the event
loop’s job to execute the current coroutine until it suspends on an &lt;tt class="docutils literal"&gt;await&lt;/tt&gt;,
after which it looks to see if any suspended coroutines are now done with their
suspension and either picks one to resume or, if none are ready, waits until
one is.&lt;/p&gt;
&lt;p id="awaitable"&gt;An &lt;em&gt;awaitable&lt;/em&gt; is any value that the &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; keyword can be applied to; this
includes coroutine objects, futures, future-likes, and tasks (see below).
Awaiting on an awaitable causes the current coroutine to be suspended until the
awaitable is ready to provide a value or raise an exception.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;future&lt;/em&gt; (class &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-future.html#asyncio.Future"&gt;&lt;tt class="docutils literal"&gt;asyncio.Future&lt;/tt&gt;&lt;/a&gt;) is a low-level container for the result of
a computation (a value or exception) that starts out empty and is assigned a
value or exception later.  Awaiting on a future will suspend the current
coroutine until something else either stores a result in the future or cancels
it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;You may already be familiar with futures in the form of the &lt;tt class="docutils literal"&gt;Future&lt;/tt&gt; class
from the &lt;a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html"&gt;&lt;tt class="docutils literal"&gt;concurrent.futures&lt;/tt&gt;&lt;/a&gt; module, which provides access to the results
of operations evaluated in other threads or processes.  The
&lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-future.html#asyncio.Future"&gt;&lt;tt class="docutils literal"&gt;asyncio.Future&lt;/tt&gt;&lt;/a&gt; class is similar in spirit, but has a different API.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A &lt;em&gt;future-like&lt;/em&gt; is an object with an &lt;tt class="docutils literal"&gt;__await__()&lt;/tt&gt; method, which must return
an iterator.  Awaiting on a future-like causes the current coroutine to be
suspended until the iterator is exhausted, at which point the &lt;tt class="docutils literal"&gt;value&lt;/tt&gt;
attribute of the terminating &lt;tt class="docutils literal"&gt;StopIteration&lt;/tt&gt; exception is returned as the
result of the &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; expression.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;task&lt;/em&gt; (class &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.Task"&gt;&lt;tt class="docutils literal"&gt;asyncio.Task&lt;/tt&gt;&lt;/a&gt;) represents a running coroutine.  Creating a
task from a coroutine object with &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task"&gt;&lt;tt class="docutils literal"&gt;asyncio.create_task()&lt;/tt&gt;&lt;/a&gt; will cause the
coroutine to be scheduled for execution concurrently with other running
coroutines.  The task instance can later be awaited on to suspend the current
coroutine until the wrapped coroutine finishes executing, returning its result.&lt;/p&gt;
&lt;p&gt;A running task can be &lt;em&gt;cancelled&lt;/em&gt; by calling its &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel"&gt;&lt;tt class="docutils literal"&gt;Task.cancel()&lt;/tt&gt;&lt;/a&gt; method.  This
will cause the underlying coroutine to receive an &lt;tt class="docutils literal"&gt;asyncio.CancelledError&lt;/tt&gt;
exception the next time it &lt;tt class="docutils literal"&gt;await&lt;/tt&gt;s, likely putting an end to the task’s
execution.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="syntax"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Syntax&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Asynchronous programming in Python takes place inside &lt;a class="reference internal" href="#coroutines"&gt;coroutines&lt;/a&gt;, functions
defined using &lt;tt class="docutils literal"&gt;async def&lt;/tt&gt; instead of just &lt;tt class="docutils literal"&gt;def&lt;/tt&gt;.  Within a coroutine, the
&lt;tt class="docutils literal"&gt;await&lt;/tt&gt; keyword can be applied to any &lt;a class="reference internal" href="#awaitable"&gt;awaitable&lt;/a&gt; expression (such as a call
to another coroutine) to suspend execution of the coroutine until the awaitable
has a value or exception ready, at which point the coroutine is resumed and the
&lt;tt class="docutils literal"&gt;await&lt;/tt&gt; expression returns that value or raises that exception.&lt;/p&gt;
&lt;p&gt;Here’s a basic example you’ve seen in all the tutorials:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;asyncio&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;waiter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Before sleep&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;After sleep&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;waiter&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This code prints a message, waits for a five-second sleep to elapse, and then
prints another message.  As written, it’s rather pointless; we’re only running
one coroutine at once, so there’s no advantage over using a synchronous
function with &lt;tt class="docutils literal"&gt;time.sleep()&lt;/tt&gt;.  Here’s something slightly more involved:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;asyncio&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;operate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Spending &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds doing operations ...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Operations done after &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;amain&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;operate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Got &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;=}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="si"&gt;=}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amain&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This code mocks spending time on two blocking operations in parallel.  If you
run the script (Python 3.8+ required) and time it, you’ll see that it only
takes about 5 seconds in total, and the 2-second task completes three seconds
before the 5-second one.  After both tasks are done, the final “Got x=42, y=23”
message is printed.&lt;/p&gt;
&lt;p&gt;Besides &lt;tt class="docutils literal"&gt;await&lt;/tt&gt;, there are two other syntactical constructs specific to
coroutines: &lt;tt class="docutils literal"&gt;async for ... in &lt;span class="pre"&gt;...:&lt;/span&gt;&lt;/tt&gt; (for iterating over asynchronous
iterables) and &lt;tt class="docutils literal"&gt;async with &lt;span class="pre"&gt;...:&lt;/span&gt;&lt;/tt&gt; (for entering &amp;amp; exiting asynchronous context
managers).  These work the same way as their non-&lt;tt class="docutils literal"&gt;async&lt;/tt&gt; counterparts, except
that the iterables and context managers in question need to support
asynchronous usage; for example, an &lt;tt class="docutils literal"&gt;async for&lt;/tt&gt; cannot iterate over a
&lt;tt class="docutils literal"&gt;list&lt;/tt&gt;, and an &lt;tt class="docutils literal"&gt;async with&lt;/tt&gt; cannot operate on an ordinary filehandle.
Similarly, a regular &lt;tt class="docutils literal"&gt;for&lt;/tt&gt; cannot be applied to an asynchronous iterator, and
a regular &lt;tt class="docutils literal"&gt;with&lt;/tt&gt; cannot be applied to, say, &lt;tt class="docutils literal"&gt;asyncio.Lock&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Speaking of asynchronous iteration, this works pretty much how you’d expect: by
using &lt;tt class="docutils literal"&gt;yield&lt;/tt&gt; inside a coroutine, it becomes an asynchronous generator that
can be iterated over with &lt;tt class="docutils literal"&gt;async for&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;await &lt;span class="pre"&gt;anext(...)&lt;/span&gt;&lt;/tt&gt;.  Note that, in
contrast to non-generator coroutines, you do not apply &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; to an
asynchronous generator.  For example, given this function:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;aiterator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;you use it like this:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;aiterator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;No &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; anywhere in the &lt;tt class="docutils literal"&gt;async for&lt;/tt&gt; loop.&lt;/p&gt;
&lt;p&gt;Note that there is no way to get a value out of a coroutine without awaiting on
it (either directly or via something like &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.gather"&gt;&lt;tt class="docutils literal"&gt;asyncio.gather()&lt;/tt&gt;&lt;/a&gt;); if a coroutine is
never awaited and never converted into a task, &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; will complain when
it is garbage-collected.  Moreover, &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; (and &lt;tt class="docutils literal"&gt;async for&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;async
with&lt;/tt&gt;) cannot be used outside of a coroutine; in order to start the awaiting
on a “top-level” coroutine, you need to use &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.run"&gt;&lt;tt class="docutils literal"&gt;asyncio.run()&lt;/tt&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note that the body of a coroutine isn’t required to contain any &lt;tt class="docutils literal"&gt;await&lt;/tt&gt;s or
similar, though if it doesn’t, there often isn’t much point in making it a
coroutine in the first place.  An exception is the &lt;tt class="docutils literal"&gt;__aenter__()&lt;/tt&gt; special
method of asynchronous context managers; usually, the body will just be
&lt;tt class="docutils literal"&gt;return self&lt;/tt&gt;, but it’s still required to define the method with &lt;tt class="docutils literal"&gt;async
def&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="section" id="type-annotations"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Type Annotations&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Adding type annotations to asynchronous code works the same way as for
synchronous code.  If an asynchronous &lt;tt class="docutils literal"&gt;func()&lt;/tt&gt; take an integer &lt;tt class="docutils literal"&gt;x&lt;/tt&gt; and
returns a string, you write its annotated signature as &lt;tt class="docutils literal"&gt;async def func(x: int)
&lt;span class="pre"&gt;-&amp;gt;&lt;/span&gt; str&lt;/tt&gt;.  However, if you pass around an unawaited coroutine object (not
always the best idea), you annotate it as &lt;tt class="docutils literal"&gt;Awaitable[T]&lt;/tt&gt;, where &lt;tt class="docutils literal"&gt;T&lt;/tt&gt; is the
return type of the coroutine.&lt;/p&gt;
&lt;p&gt;Async callables do not have their own type; they are instead annotated as
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Callable[...,&lt;/span&gt; Awaitable[T]]&lt;/tt&gt;, where &lt;tt class="docutils literal"&gt;T&lt;/tt&gt; is the return type of the
coroutine function.&lt;/p&gt;
&lt;p&gt;Asynchronous iterators, iterables, and context managers, though, do get their
own types: &lt;tt class="docutils literal"&gt;AsyncIterator&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;AsyncIterable&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;typing.AsyncContextManager&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;contextlib.AbstractAsyncContextManager&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="special-methods"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Special Methods&lt;/a&gt;&lt;/h3&gt;
&lt;p class="rubric"&gt;&lt;tt class="docutils literal"&gt;__aiter__()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__anext__()&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;These methods are used to implement asynchronous iterator &amp;amp; iterable classes as
an alternative to writing asynchronous generator functions, analogously to how
a class can be defined with &lt;tt class="docutils literal"&gt;__iter__()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__next__()&lt;/tt&gt; methods to
implement a synchronous iterator as an alternative to writing a generator
function.&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;__aiter__()&lt;/tt&gt; must be a synchronous function that returns an object with
&lt;tt class="docutils literal"&gt;__aiter__()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__anext__()&lt;/tt&gt; methods.  &lt;tt class="docutils literal"&gt;__anext__()&lt;/tt&gt; must be a
coroutine that either returns a value or raises a &lt;tt class="docutils literal"&gt;StopAsyncIteration&lt;/tt&gt;
exception.&lt;/p&gt;
&lt;p class="rubric"&gt;&lt;tt class="docutils literal"&gt;__aenter__()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__aexit__()&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;These methods are used to implement asynchronous context managers.  They are
defined the same way as the &lt;tt class="docutils literal"&gt;__enter__()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__exit__()&lt;/tt&gt; methods of
synchronous context managers, except that the asynchronous versions must be
coroutines.&lt;/p&gt;
&lt;p class="rubric"&gt;&lt;tt class="docutils literal"&gt;__await__()&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;This method is used to create a future-like class that can be awaited directly.
There is generally very little need to implement this, but we include it here
for completeness.&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;__await__()&lt;/tt&gt; must be a synchronous function that returns an iterator.  This
iterator will be advanced each time the event loop checks to see if the
future-like is ready to return a value.  If the future-like is not ready, the
iterator must yield a special value (see below).  If the future-like is ready,
it must either &lt;tt class="docutils literal"&gt;return&lt;/tt&gt; a result or raise an exception; this result or
exception will then be the result of the &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; expression acting on the
future-like.&lt;/p&gt;
&lt;p&gt;The values that the iterator yields depend on what async implementation the
code is running under (See “&lt;a class="reference internal" href="#alternative-async-implementations"&gt;Alternative Async Implementations&lt;/a&gt;” below).  When
using the Python standard library’s &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt;, you generally want to yield
&lt;tt class="docutils literal"&gt;None&lt;/tt&gt;.  When using trio, you need to yield an instance of one of several
private classes internal to trio.  When using curio, you need to yield a
&lt;tt class="docutils literal"&gt;(&amp;quot;trap_name&amp;quot;, *trap_args)&lt;/tt&gt; tuple instructing the kernel to invoke a special
“trap” function; yielding &lt;tt class="docutils literal"&gt;(&amp;quot;trap_sleep&amp;quot;, 0)&lt;/tt&gt; instructs the kernel to do
nothing special.&lt;/p&gt;
&lt;p&gt;For example, if you want to implement your own &lt;tt class="docutils literal"&gt;Future&lt;/tt&gt; class for use with
&lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt;, you might start out writing it like so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;MyFuture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;set_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__await__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;            &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="historical-note-generator-based-coroutines"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Historical Note: Generator-Based Coroutines&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; was first introduced in Python 3.4, the &lt;tt class="docutils literal"&gt;async&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;await&lt;/tt&gt; keywords were not yet present.  Instead, coroutine functions were
created by applying the &lt;tt class="docutils literal"&gt;&amp;#64;asyncio.coroutine&lt;/tt&gt; decorator to a normal generator
function, and awaiting was done using &lt;tt class="docutils literal"&gt;yield from&lt;/tt&gt;.  There were no
asynchronous iterators or asynchronous context managers in 3.4, either.  Even
after &lt;tt class="docutils literal"&gt;async&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; were introduced in Python 3.5, the older
generator-based coroutines could not use them.&lt;/p&gt;
&lt;p&gt;This style of writing coroutines was deprecated in Python 3.8 and removed
entirely in Python 3.11.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="running-more-than-one-coroutine-at-once"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Running More than One Coroutine at Once&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now for the part you’ve been waiting for, and the part that makes asynchronous
programming worth it: actually running multiple functions concurrently.&lt;/p&gt;
&lt;p&gt;The simplest way to start running another coroutine concurrently is to pass a
coroutine object to &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task"&gt;&lt;tt class="docutils literal"&gt;asyncio.create_task()&lt;/tt&gt;&lt;/a&gt;; this schedules the coroutine for
execution, but it won’t actually start running until the next time the current
coroutine calls &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; (and maybe not even then).  &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task"&gt;&lt;tt class="docutils literal"&gt;asyncio.create_task()&lt;/tt&gt;&lt;/a&gt;
returns an &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.Task"&gt;&lt;tt class="docutils literal"&gt;asyncio.Task&lt;/tt&gt;&lt;/a&gt; object that can be used to query the state of the
coroutine or cancel it; awaiting on the task object will cause the current
coroutine to be suspended until the task is complete, at which point the return
value of the task’s underlying coroutine is returned.&lt;/p&gt;
&lt;p&gt;If you create multiple tasks and then &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; on them one by one, a given
&lt;tt class="docutils literal"&gt;await&lt;/tt&gt; will not return a result until the task in question is done; if task
B finishes running while you’re still awaiting on task A, the coroutine doing
the awaiting will continue to be suspended until A is done, and when it then
later awaits on B, it will get back B’s return value immediately, because B is
already done.  For example, the following code:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;asyncio&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%H:%M:%S&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;operate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: Spending &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds doing operations ...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: Operations done after &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;amain&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;task1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;task2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;task1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: task1 returned &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;task2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: task2 returned &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amain&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;outputs something like the following:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
17:12:56: Spending 5 seconds doing operations ...
17:12:56: Spending 2 seconds doing operations ...
17:12:58: Operations done after 2 seconds!
17:13:01: Operations done after 5 seconds!
17:13:01: task1 returned 42
17:13:01: task2 returned 23
&lt;/pre&gt;
&lt;p&gt;If you need to await on multiple coroutines but don’t care about the exact
order in which they finish, you can use &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.gather"&gt;&lt;tt class="docutils literal"&gt;asyncio.gather()&lt;/tt&gt;&lt;/a&gt;,
&lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.as_completed"&gt;&lt;tt class="docutils literal"&gt;asyncio.as_completed()&lt;/tt&gt;&lt;/a&gt;, or &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.wait"&gt;&lt;tt class="docutils literal"&gt;asyncio.wait()&lt;/tt&gt;&lt;/a&gt; to await on them together; &lt;a class="reference external" href="https://hynek.me/articles/waiting-in-asyncio/"&gt;this
article&lt;/a&gt; gives a good overview and explanation of the differences
between the functions.&lt;/p&gt;
&lt;p id="bgerr"&gt;You don’t have to await on a task if you don’t need its return value or don’t
need to be assured that it ever finishes, but if such a “background task”
raises an uncaught exception, &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; will complain.  One way to address
this is to attach a synchronous callback function to the task with
&lt;tt class="docutils literal"&gt;Task.add_done_callback()&lt;/tt&gt; that retrieves any uncaught exceptions with
&lt;tt class="docutils literal"&gt;Task.exception()&lt;/tt&gt;, like so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;asyncio&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%H:%M:%S&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;bg_task&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: In the background&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Ouch&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;done_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;            &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: Task &amp;lt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt; raised an error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;            &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: Task &amp;lt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt; finished successfully&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CancelledError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: Task &amp;lt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt; was cancelled!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;fg_task&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bg_task&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;bg_task&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_done_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;done_callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: Now we sleep and let bg_task do its thing&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: I'm awake!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fg_task&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The output from the above will look like:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
17:16:33: Now we sleep and let bg_task do its thing
17:16:33: In the background
17:16:33: Task &amp;lt;bg_task&amp;gt; raised an error: Ouch
17:16:35: I'm awake!
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="exception-handling"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Exception Handling&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Whenever an exception occurs inside a coroutine, it propagates upwards to
whatever’s awaiting on it; if unhandled, it will propagate all the way out
through the &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.run"&gt;&lt;tt class="docutils literal"&gt;asyncio.run()&lt;/tt&gt;&lt;/a&gt; call, at which point all still-running tasks are
cancelled.  If there is no chain of &lt;tt class="docutils literal"&gt;await&lt;/tt&gt;s leading to the “top-level”
coroutine (say, because you did &lt;tt class="docutils literal"&gt;asyncio.create_task()&lt;/tt&gt; and then didn’t await
on the result, letting it run in the background), &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; will end up
complaining when the coroutine is eventually garbage-collected.  See &lt;a class="reference internal" href="#bgerr"&gt;the
passage above&lt;/a&gt; on using &lt;tt class="docutils literal"&gt;Task.add_done_callback()&lt;/tt&gt; to handle such
errors.&lt;/p&gt;
&lt;p&gt;For the specific case of &lt;tt class="docutils literal"&gt;KeyboardInterrupt&lt;/tt&gt;, the exception is raised in
whatever coroutine the main thread is currently running at the time.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="example-code"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Example Code&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://gist.github.com/jwodder/c0ad1a5a0b6fda18c15dbdb405e1e549"&gt;This gist&lt;/a&gt; provides an example of using asynchronous programming in Python
to download assets for one or more releases of a GitHub repository in parallel.
Try it out with an invocation like:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
python download-assets.py --download-dir jq stedolan/jq jq-1.5 jq-1.6
&lt;/pre&gt;
&lt;p&gt;The script requires Python 3.8 or higher and the &lt;a class="reference external" href="https://github.com/jwodder/ghrepo"&gt;ghrepo&lt;/a&gt; and &lt;a class="reference external" href="https://www.python-httpx.org"&gt;httpx&lt;/a&gt; packages on
PyPI to run.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="asynchronous-programming-vs-threads"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Asynchronous Programming vs. Threads&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Asynchronous programming does not use threads; by default, all coroutines and
their operations are run in whichever thread called &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.run"&gt;&lt;tt class="docutils literal"&gt;asyncio.run()&lt;/tt&gt;&lt;/a&gt;.  The
exception is when &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread"&gt;&lt;tt class="docutils literal"&gt;asyncio.to_thread()&lt;/tt&gt;&lt;/a&gt; or &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor"&gt;&lt;tt class="docutils literal"&gt;loop.run_in_executor()&lt;/tt&gt;&lt;/a&gt; is used to
run a synchronous function in a separate thread (or, with the latter function,
even a separate process), returning an object that can be awaited on to receive
the function’s result.&lt;/p&gt;
&lt;p&gt;If multiple threads call &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.run"&gt;&lt;tt class="docutils literal"&gt;asyncio.run()&lt;/tt&gt;&lt;/a&gt; separately, each thread will get its
own event loop and collection of coroutines.&lt;/p&gt;
&lt;p&gt;Note that each thread in a Python process has at most one event loop at a time,
and an event loop can only belong to one thread.  An important consequence of
this is that, if you have a synchronous function &lt;tt class="docutils literal"&gt;foo()&lt;/tt&gt; that calls
&lt;a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.run"&gt;&lt;tt class="docutils literal"&gt;asyncio.run()&lt;/tt&gt;&lt;/a&gt; on some coroutine, then &lt;tt class="docutils literal"&gt;foo()&lt;/tt&gt; cannot be called by another
coroutine, because that would lead to two event loops in the same thread, which
doesn’t work.&lt;/p&gt;
&lt;p&gt;Compared to threads, asynchronous programming provides the following
advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;In asynchronous programming, the coroutine being executed can only change
when the current coroutine uses &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; or similar.  This allows the
programmer to be assured that, between &lt;tt class="docutils literal"&gt;await&lt;/tt&gt;s in the same coroutine,
operations will not be interfered with and data will not be modified by other
coroutines.&lt;/p&gt;
&lt;p&gt;When using threads, on the other hand, the running thread &lt;a class="footnote-reference" href="#gil" id="footnote-reference-1"&gt;[1]&lt;/a&gt; can change
at almost any point as chosen by the interpreter, which necessitates careful
programming and copious use of locks in order to ensure that variables are
not modified by one thread “behind the back of” another thread that’s also
using them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If you’ve done serious work with threads, you’ve likely encountered the fact
that you cannot “kill” a thread in the middle of its execution unless the
“killable” thread is deliberately programmed to allow for this by, say,
regularly checking some flag and exiting if it’s true.  Asynchronous
programming, on the other hand, makes it possible to &lt;em&gt;cancel&lt;/em&gt; a running
coroutine via the &lt;tt class="docutils literal"&gt;asyncio.Task.cancel()&lt;/tt&gt; method; once a coroutine is
cancelled, the next time the event loop checks on it while it’s suspended on
an &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; or similar, the coroutine will be resumed, but instead of
receiving the value it was awaiting for, an &lt;tt class="docutils literal"&gt;asyncio.CancelledError&lt;/tt&gt; will
be raised at the &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; expression, likely putting an end to the
coroutine’s execution.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table class="docutils footnote" frame="void" id="gil" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Recall that, due to Python’s global interpreter lock (GIL),
regardless of how many threads a Python program uses or how many cores your
machine has, only one thread will be executing Python bytecode at any
moment.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class="section" id="async-version-history"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Async Version History&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here follows a list of the notable developments &amp;amp; changes in asynchronous
programming across Python versions.&lt;/p&gt;
&lt;p class="rubric"&gt;Python 3.4&lt;/p&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; module is added, implementing &lt;a class="reference external" href="https://peps.python.org/pep-3156"&gt;PEP 3156&lt;/a&gt;.  This enables the
creation of coroutines via the &lt;tt class="docutils literal"&gt;&amp;#64;asyncio.coroutine&lt;/tt&gt; decorator; within a
coroutine, awaiting is performed with &lt;tt class="docutils literal"&gt;yield from&lt;/tt&gt;.  (Support for creating
coroutines in this way would later be deprecated in Python 3.8 and removed in
Python 3.11.)&lt;/p&gt;
&lt;p&gt;Most of the functionality added in this version is now categorized as the “low
level” part of &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt;.&lt;/p&gt;
&lt;p class="rubric"&gt;Python 3.5&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://peps.python.org/pep-0492"&gt;PEP 492&lt;/a&gt; implemented:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;It is now possible to define coroutines via &lt;tt class="docutils literal"&gt;async def&lt;/tt&gt; and await with
&lt;tt class="docutils literal"&gt;await&lt;/tt&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;In Python 3.5, &lt;tt class="docutils literal"&gt;yield&lt;/tt&gt; cannot be used inside the body of an &lt;tt class="docutils literal"&gt;async def&lt;/tt&gt;
coroutine function.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Asynchronous iteration with &lt;tt class="docutils literal"&gt;async for&lt;/tt&gt; is now possible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Asynchronous context managers are now supported via &lt;tt class="docutils literal"&gt;async with&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;__await__()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;__aiter__()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;__anext__()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;__aenter__()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;__aexit__()&lt;/tt&gt; special methods added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Originally, &lt;tt class="docutils literal"&gt;__aiter__()&lt;/tt&gt; methods were expected to be coroutines (or
anything else returning an awaitable) resolving to asynchronous iterators.
This was changed in 3.5.2 to have &lt;tt class="docutils literal"&gt;__aiter__()&lt;/tt&gt; instead return an
asynchronous iterator directly.  Returning an awaitable from &lt;tt class="docutils literal"&gt;__aiter__()&lt;/tt&gt;
produces a &lt;tt class="docutils literal"&gt;PendingDeprecationWarning&lt;/tt&gt; starting in 3.5.2, a
&lt;tt class="docutils literal"&gt;DeprecationWarning&lt;/tt&gt; starting in 3.6, and a &lt;tt class="docutils literal"&gt;RuntimeError&lt;/tt&gt; starting in
3.7.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Python 3.6&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;yield&lt;/tt&gt; can now be used in the body of an &lt;tt class="docutils literal"&gt;async def&lt;/tt&gt; coroutine function,
thereby enabling asynchronous generators (&lt;a class="reference external" href="https://peps.python.org/pep-0525"&gt;PEP 525&lt;/a&gt;).  (&lt;tt class="docutils literal"&gt;yield from&lt;/tt&gt;
remains prohibited, though.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;async for&lt;/tt&gt; can now be used in list, set, &amp;amp; dict comprehensions and in
generator expressions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;await&lt;/tt&gt; expressions can now be used in any comprehension&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Using &lt;tt class="docutils literal"&gt;async&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; as an identifier now generates a
&lt;tt class="docutils literal"&gt;DeprecationWarning&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Python 3.7&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;async&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; are now reserved keywords&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio.run()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio.create_task()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Python 3.8&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Running &lt;tt class="docutils literal"&gt;python &lt;span class="pre"&gt;-m&lt;/span&gt; asyncio&lt;/tt&gt; now starts an async REPL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;&amp;#64;asyncio.coroutine()&lt;/tt&gt; is now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Passing a &lt;tt class="docutils literal"&gt;loop&lt;/tt&gt; parameter is now deprecated for most of &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt;’s
high-level API&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio.CancelledError&lt;/tt&gt; now inherits directly from &lt;tt class="docutils literal"&gt;BaseException&lt;/tt&gt;
instead of &lt;tt class="docutils literal"&gt;Exception&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Python 3.9&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio.to_thread()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Python 3.10&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;aiter()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;anext()&lt;/tt&gt; functions added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;loop&lt;/tt&gt; parameter (deprecated in Python 3.8) is now removed from most of
&lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt;’s high-level API&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="rubric"&gt;Python 3.11&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio.TaskGroup&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;&amp;#64;asyncio.coroutine&lt;/tt&gt; (deprecated in Python 3.8) is now removed&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="alternative-async-implementations"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Alternative Async Implementations&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While all the code we’ve shown so far uses the Python standard library’s
&lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; module, it’s not required to use this to work with coroutines.
Alternative async library implementations exist that define their own event
loops and primitive operations.  The more notable implementations include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://github.com/python-trio/trio"&gt;trio&lt;/a&gt; seeks to enable &lt;em&gt;structured
concurrency&lt;/em&gt; [&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Structured_concurrency"&gt;wiki&lt;/a&gt;] in asynchronous code.  In trio, a collection of tasks
are run concurrently by grouping them together under a &lt;em&gt;nursery&lt;/em&gt; (also known
as a &lt;em&gt;task group&lt;/em&gt;); if one of the tasks in a nursery raises an error, all
the other tasks in the same nursery are automatically cancelled.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://github.com/dabeaz/curio"&gt;curio&lt;/a&gt; is an &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; alternative
featuring a more streamlined API and intended to be easier to reason about&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In general, different async implementations are incompatible, and features from
different implementations cannot be used in the same code unless you make
careful use of whatever compatibility facilities they may provide.&lt;/p&gt;
&lt;p&gt;In fact, just being able to use the same code unmodified regardless of whether
using implementation A or implementation B is tricky, as all implementations
use different primitives.  Libraries to help you with that include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://github.com/python-trio/sniffio"&gt;sniffio&lt;/a&gt; can be used to detect
which async library is in use&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://github.com/agronholm/anyio"&gt;anyio&lt;/a&gt; provides a common API (based on
trio) that can be used to run the same code under both asyncio and trio (and
previously curio, until it &amp;amp; anyio &lt;a class="reference external" href="https://github.com/agronholm/anyio/issues/185"&gt;parted ways&lt;/a&gt; in anyio 3.0)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Programming"></category><category term="Python"></category><category term="async"></category></entry><entry><title>Creating Multi-Value Enums in Python</title><link href="https://jwodder.github.io/kbits/posts/multi-value-enum/" rel="alternate"></link><published>2022-01-14T00:00:00-05:00</published><updated>2022-01-14T00:00:00-05:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2022-01-14:/kbits/posts/multi-value-enum/</id><summary type="html">&lt;p class="first last"&gt;How to create an enum in Python where each member has a “main” value and a
set of “extra” constant attributes&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Say you’re creating an enum type in Python and you want each enum member to
have one or more additional constant attributes alongside &lt;tt class="docutils literal"&gt;value&lt;/tt&gt;, but these
attributes can’t be easily derived from &lt;tt class="docutils literal"&gt;value&lt;/tt&gt; (and thus don’t make for good
&lt;tt class="docutils literal"&gt;&amp;#64;property&lt;/tt&gt;s).  The Python docs provide &lt;a class="reference external" href="https://docs.python.org/3.10/library/enum.html#planet"&gt;an example involving planets&lt;/a&gt;
similar to what you want, but on closer inspection, you see it won’t do — the
example code produces an enum whose members’ &lt;tt class="docutils literal"&gt;value&lt;/tt&gt;s are tuples of the
other attributes, whereas you want or need &lt;tt class="docutils literal"&gt;value&lt;/tt&gt; to be something else.  Is
there a way to define enum members with a combination of a “main” value and a
set of “extra” values?&lt;/p&gt;
&lt;p&gt;Yes.  Yes, there is.&lt;/p&gt;
&lt;p&gt;For a specific example, let’s say you want to define an enum for cardinal and
ordinal directions where the members’ &lt;tt class="docutils literal"&gt;value&lt;/tt&gt;s are human-readable names
used in some data source you have to parse and each member should additionally
have &lt;tt class="docutils literal"&gt;x&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;y&lt;/tt&gt; attributes giving the deltas to add to a coordinate’s
components in order to move a step in the respective direction.  That is, you
want the following to evaluate as shown:&lt;/p&gt;
&lt;pre class="doctest-block"&gt;
&amp;gt;&amp;gt;&amp;gt; Direction(&amp;quot;north-west&amp;quot;)
&amp;lt;Direction.NORTH_WEST: 'north-west'&amp;gt;
&amp;gt;&amp;gt;&amp;gt; Direction.NORTH_WEST.value
'north-west'
&amp;gt;&amp;gt;&amp;gt; Direction.NORTH_WEST.x
-1
&amp;gt;&amp;gt;&amp;gt; Direction.NORTH_WEST.y
1
&lt;/pre&gt;
&lt;p&gt;The solution is to define each enum member with a tuple of the &lt;tt class="docutils literal"&gt;value&lt;/tt&gt; and
extra attributes, and then write a &lt;tt class="docutils literal"&gt;__new__&lt;/tt&gt; method that assigns the elements
of the tuple (which are passed as arguments to &lt;tt class="docutils literal"&gt;__new__&lt;/tt&gt;) appropriately, like
so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;NORTH&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;north&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;NORTH_EAST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;north-east&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;EAST&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;east&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;SOUTH_EAST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;south-east&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;SOUTH&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;south&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;SOUTH_WEST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;south-west&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;WEST&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;west&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;NORTH_WEST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;north-west&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# Check that `value` and other attributes are what they're supposed to be:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;=}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;=}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;=}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="si"&gt;=}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# Member access by value uses only the &amp;quot;main&amp;quot; value:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'north'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;=}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Output from the above script:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
&amp;lt;Direction.NORTH: 'north'&amp;gt; d.name='NORTH' d.value='north' d.x=0 d.y=1
&amp;lt;Direction.NORTH_EAST: 'north-east'&amp;gt; d.name='NORTH_EAST' d.value='north-east' d.x=1 d.y=1
&amp;lt;Direction.EAST: 'east'&amp;gt; d.name='EAST' d.value='east' d.x=1 d.y=0
&amp;lt;Direction.SOUTH_EAST: 'south-east'&amp;gt; d.name='SOUTH_EAST' d.value='south-east' d.x=1 d.y=-1
&amp;lt;Direction.SOUTH: 'south'&amp;gt; d.name='SOUTH' d.value='south' d.x=0 d.y=-1
&amp;lt;Direction.SOUTH_WEST: 'south-west'&amp;gt; d.name='SOUTH_WEST' d.value='south-west' d.x=-1 d.y=-1
&amp;lt;Direction.WEST: 'west'&amp;gt; d.name='WEST' d.value='west' d.x=-1 d.y=0
&amp;lt;Direction.NORTH_WEST: 'north-west'&amp;gt; d.name='NORTH_WEST' d.value='north-west' d.x=-1 d.y=1
Direction('north')=&amp;lt;Direction.NORTH: 'north'&amp;gt;
&lt;/pre&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;If you’re inheriting a concrete non-&lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt; type in addition to &lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt;
(whether explicitly or via &lt;tt class="docutils literal"&gt;IntEnum&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;StrEnum&lt;/tt&gt;), you may need to
replace the &lt;tt class="docutils literal"&gt;obj = object.__new__(cls)&lt;/tt&gt; line in the &lt;tt class="docutils literal"&gt;__new__&lt;/tt&gt; method
with an invocation of the concrete type’s &lt;tt class="docutils literal"&gt;__new__&lt;/tt&gt;.  For example, if
inheriting from &lt;tt class="docutils literal"&gt;(str, Enum)&lt;/tt&gt; or Python 3.11’s &lt;tt class="docutils literal"&gt;StrEnum&lt;/tt&gt;, this line
should become &lt;tt class="docutils literal"&gt;obj = str.__new__(cls, value)&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now, if you’re type-checking with &lt;a class="reference external" href="http://www.mypy-lang.org"&gt;mypy&lt;/a&gt; (and you really should be), you’ll
likely hit some errors on the above code, even after adding annotations to
&lt;tt class="docutils literal"&gt;__new__&lt;/tt&gt;.  Specifically, as of mypy 0.931, there are two outstanding mypy
issues that affect the above snippet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://github.com/python/mypy/issues/1021"&gt;Issue #1021&lt;/a&gt; means that mypy ignores attribute assignments in &lt;tt class="docutils literal"&gt;__new__&lt;/tt&gt;,
so it won’t recognize &lt;tt class="docutils literal"&gt;x&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;y&lt;/tt&gt; as attributes of &lt;tt class="docutils literal"&gt;Direction&lt;/tt&gt;, leading
to &lt;tt class="docutils literal"&gt;print(f&amp;quot;… {d.x=} &lt;span class="pre"&gt;{d.y=}&amp;quot;)&lt;/span&gt;&lt;/tt&gt; being seen as erroneous.  There are two ways
to make mypy aware of the extra-value attributes: either add annotations for
them in the main body of the class, like so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;NORTH&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;north&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# [snip]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;NORTH_WEST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;north-west&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;    &lt;span class="c1"&gt;# Add these two lines:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;… or else move the extra-value assignments to an &lt;tt class="docutils literal"&gt;__init__&lt;/tt&gt; method, like
so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;NORTH&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;north&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# [snip]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;NORTH_WEST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;north-west&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The second mypy problem is &lt;a class="reference external" href="https://github.com/python/mypy/issues/10573"&gt;issue #10573&lt;/a&gt;: mypy is not aware of the &lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt;
class’s trickery with its constructor, so when it sees &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Direction('north')&lt;/span&gt;&lt;/tt&gt;
on the last line, having already seen a &lt;tt class="docutils literal"&gt;Direction.__new__&lt;/tt&gt; that takes
three arguments, it thinks there are two arguments missing from the
&lt;tt class="docutils literal"&gt;Direction()&lt;/tt&gt; call.  Unfortunately, at time of writing, there does not seem
to be a way around this other than just slapping a “&lt;tt class="docutils literal"&gt;# type:
&lt;span class="pre"&gt;ignore[call-arg]&lt;/span&gt;&lt;/tt&gt;” comment on each call to a multi-value enum type.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content><category term="Programming"></category><category term="Python"></category><category term="enum"></category><category term="mypy"></category></entry><entry><title>Skipping Pytest Tests Unless an Option is Given</title><link href="https://jwodder.github.io/kbits/posts/pytest-mark-off/" rel="alternate"></link><published>2021-12-05T00:00:00-05:00</published><updated>2021-12-05T00:00:00-05:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2021-12-05:/kbits/posts/pytest-mark-off/</id><summary type="html">&lt;p class="first last"&gt;When testing Python code with &lt;a class="reference external" href="https://docs.pytest.org"&gt;pytest&lt;/a&gt;, you may occasionally write tests
that you only want to run under special circumstances, such as long-running
tests that should only be run under continuous integration and not when
invoking &lt;tt class="docutils literal"&gt;pytest&lt;/tt&gt; locally.  The naïve way to accomplish this is to
decorate the tests in question with a pytest mark like
&lt;tt class="docutils literal"&gt;&amp;#64;pytest.mark.slow&lt;/tt&gt; and then specify &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-m&lt;/span&gt; &amp;quot;not slow&amp;quot;&lt;/tt&gt; when running
pytest locally, but then you have to remember to pass this option every
time, and if you hardcode it into your &lt;tt class="docutils literal"&gt;tox.ini&lt;/tt&gt; or pytest configuration,
you’ll need something else to remove it when testing under CI.
Fortunately, there are better ways to make pytest skip tests by default.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;When testing Python code with &lt;a class="reference external" href="https://docs.pytest.org"&gt;pytest&lt;/a&gt;, you may occasionally write tests that
you only want to run under special circumstances, such as long-running tests
that should only be run under continuous integration and not when invoking
&lt;tt class="docutils literal"&gt;pytest&lt;/tt&gt; locally.  The naïve way to accomplish this is to decorate the tests
in question with a pytest mark like &lt;tt class="docutils literal"&gt;&amp;#64;pytest.mark.slow&lt;/tt&gt; and then specify &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-m&lt;/span&gt;
&amp;quot;not slow&amp;quot;&lt;/tt&gt; when running pytest locally, but then you have to remember to pass
this option every time, and if you hardcode it into your &lt;tt class="docutils literal"&gt;tox.ini&lt;/tt&gt; or pytest
configuration, you’ll need something else to remove it when testing under CI.
Fortunately, there are better ways to make pytest skip tests by default.&lt;/p&gt;
&lt;p&gt;In this article, we will add a “&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--run-slow&lt;/span&gt;&lt;/tt&gt;” option to pytest and configure
selected “slow” tests to be skipped unless this option is given on the command
line.&lt;/p&gt;
&lt;div class="section" id="option-1-use-a-hook-to-attach-a-skip-marker-to-marked-tests"&gt;
&lt;h2&gt;Option 1: Use a Hook to Attach a &lt;tt class="docutils literal"&gt;skip&lt;/tt&gt; Marker to Marked Tests&lt;/h2&gt;
&lt;p&gt;One way to disable selected tests by default is to give them all some mark and
then use the &lt;tt class="docutils literal"&gt;pytest_collection_modifyitems&lt;/tt&gt; hook to add an additional
&lt;tt class="docutils literal"&gt;pytest.mark.skip&lt;/tt&gt; mark if a certain command-line option was not given.  We
do this by adding the following to our &lt;tt class="docutils literal"&gt;conftest.py&lt;/tt&gt; file:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pytest&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;pytest_addoption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addoption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;--run-slow&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;store_true&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Run slow tests&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;pytest_collection_modifyitems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getoption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--run-slow&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;skipper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mark&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Only run when --run-slow is given&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;slow&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;                &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_marker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skipper&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;and then decorate all of our slow tests with &lt;tt class="docutils literal"&gt;&amp;#64;pytest.mark.slow&lt;/tt&gt;, like so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pytest&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mark&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_something_slow&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now, when we run &lt;tt class="docutils literal"&gt;pytest&lt;/tt&gt;, the marked tests will be skipped unless the
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--run-slow&lt;/span&gt;&lt;/tt&gt; option is passed on the command line.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="option-2-use-pytest-mark-skipif"&gt;
&lt;h2&gt;Option 2: Use &lt;tt class="docutils literal"&gt;&amp;#64;pytest.mark.skipif&lt;/tt&gt;&lt;/h2&gt;
&lt;p&gt;Did you know?  The condition passed to &lt;tt class="docutils literal"&gt;&amp;#64;pytest.mark.skipif&lt;/tt&gt; doesn’t have to
be a Python boolean expression; it can instead be a &lt;a class="reference external" href="https://docs.pytest.org/en/6.2.x/historical-notes.html#string-conditions"&gt;condition string&lt;/a&gt;
containing a Python expression, and condition strings are evaluated in a
namespace that includes the pytest &lt;tt class="docutils literal"&gt;config&lt;/tt&gt; object.  This lets us write
&lt;tt class="docutils literal"&gt;skipif&lt;/tt&gt; decorators that skip tests based on whether or not certain
command-line options were given.&lt;/p&gt;
&lt;p&gt;We start out by defining a command-line option in &lt;tt class="docutils literal"&gt;conftest.py&lt;/tt&gt; that will be
used to tell pytest to run otherwise-skipped tests:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;pytest_addoption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addoption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;--run-slow&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;store_true&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Run slow tests&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We then decorate the tests we want to skip by default like so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pytest&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mark&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skipif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;not config.getoption('--run-slow')&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Only run when --run-slow is given&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_something_slow&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If there are multiple tests to apply this condition to, we can assign the
&lt;tt class="docutils literal"&gt;skipif&lt;/tt&gt; decorator to a variable that is then used to decorate each one, like
so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pytest&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;slow_test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mark&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skipif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;not config.getoption('--run-slow')&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Only run when --run-slow is given&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;slow_test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_something_slow&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;slow_test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_something_very_slow&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="first admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;You may see some old guides on the internet that instead write the
&lt;tt class="docutils literal"&gt;skipif&lt;/tt&gt; decorator with an actual boolean condition defined in terms of
&lt;tt class="docutils literal"&gt;pytest.config&lt;/tt&gt;, e.g.:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pytest&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# Outdated!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mark&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skipif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getoption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--run-slow&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Only run when --run-slow is given&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_something_slow&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;p class="last"&gt;However, this no longer works; the &lt;tt class="docutils literal"&gt;pytest.config&lt;/tt&gt; global variable was
removed from pytest in version 5.1.0.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="option-3-use-a-pre-existing-plugin"&gt;
&lt;h2&gt;Option 3: Use a Pre-Existing Plugin&lt;/h2&gt;
&lt;p&gt;As is the case for many, many things in Python, other people have already done
the job of generalizing the above and publishing it on PyPI.  I am aware of two
pytest plugin projects for skipping tests unless a command-line option is
given: &lt;a class="reference external" href="https://pypi.org/project/pytest-explicit/"&gt;pytest-explicit&lt;/a&gt; and &lt;a class="reference external" href="https://pypi.org/project/pytest-optional-tests/"&gt;pytest-optional-tests&lt;/a&gt;.  I have not used either,
but if they work as advertised, they should prove helpful.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Programming"></category><category term="Python"></category><category term="pytest"></category><category term="testing"></category></entry><entry><title>Notable Features Introduced in Each Python Version</title><link href="https://jwodder.github.io/kbits/posts/pyversion-features/" rel="alternate"></link><published>2021-07-11T00:00:00-04:00</published><updated>2023-09-28T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2021-07-11:/kbits/posts/pyversion-features/</id><summary type="html">&lt;p class="first last"&gt;Notable features introduced in each major release of Python, from Python
3.0 forwards&lt;/p&gt;
</summary><content type="html">&lt;p&gt;The following is a list of all of the notable or interesting (in my biased
opinion) features introduced in each major release of Python, starting with
Python 3.0.&lt;/p&gt;
&lt;div class="contents topic" id="contents"&gt;
&lt;p class="topic-title"&gt;Contents&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-0-2008-12-03-relative-to-python-2-6" id="toc-entry-1"&gt;Python 3.0 (2008-12-03), Relative to Python 2.6&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-1-2009-06-26" id="toc-entry-2"&gt;Python 3.1 (2009-06-26)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-2-2011-02-20" id="toc-entry-3"&gt;Python 3.2 (2011-02-20)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-3-2012-09-29" id="toc-entry-4"&gt;Python 3.3 (2012-09-29)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-4-2014-03-17" id="toc-entry-5"&gt;Python 3.4 (2014-03-17)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-5-2015-09-13" id="toc-entry-6"&gt;Python 3.5 (2015-09-13)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-6-2016-12-23" id="toc-entry-7"&gt;Python 3.6 (2016-12-23)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-7-2018-06-27" id="toc-entry-8"&gt;Python 3.7 (2018-06-27)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-8-2019-10-14" id="toc-entry-9"&gt;Python 3.8 (2019-10-14)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-9-2020-10-05" id="toc-entry-10"&gt;Python 3.9 (2020-10-05)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-10-2021-10-04" id="toc-entry-11"&gt;Python 3.10 (2021-10-04)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-11-2022-10-03" id="toc-entry-12"&gt;Python 3.11 (2022-10-03)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-3-12-2023-10-02" id="toc-entry-13"&gt;Python 3.12 (2023-10-02)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-0-2008-12-03-relative-to-python-2-6"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.0 (2008-12-03), Relative to Python 2.6&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3/whatsnew/3.0.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;print&lt;/tt&gt; statement replaced with a &lt;tt class="docutils literal"&gt;print()&lt;/tt&gt; function&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;exec&lt;/tt&gt; keyword replaced with an &lt;tt class="docutils literal"&gt;exec()&lt;/tt&gt; function, which does not take a
stream argument&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;dict.keys()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;dict.items()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;dict.values()&lt;/tt&gt; now return “views”
instead of lists&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;dict.iterkeys()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;dict.iteritems()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;dict.itervalues()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;map()&lt;/tt&gt; now returns an iterator, stops when the shortest iterable is
exhausted, and cannot take &lt;tt class="docutils literal"&gt;None&lt;/tt&gt; as a function&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;filter()&lt;/tt&gt; now returns an iterator&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Python 2’s &lt;tt class="docutils literal"&gt;xrange()&lt;/tt&gt; is Python 3’s &lt;tt class="docutils literal"&gt;range()&lt;/tt&gt;; Python 2’s &lt;tt class="docutils literal"&gt;range()&lt;/tt&gt; is
no more&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Python 2’s &lt;tt class="docutils literal"&gt;raw_input()&lt;/tt&gt; is Python 3’s &lt;tt class="docutils literal"&gt;input()&lt;/tt&gt;; Python 2’s &lt;tt class="docutils literal"&gt;input()&lt;/tt&gt;
is no more&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Python 2’s &lt;tt class="docutils literal"&gt;long&lt;/tt&gt; is Python 3’s &lt;tt class="docutils literal"&gt;int&lt;/tt&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;repr()&lt;/tt&gt; of a (long) integer no longer includes a trailing &lt;tt class="docutils literal"&gt;L&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Python 2’s &lt;tt class="docutils literal"&gt;unichr&lt;/tt&gt; is Python 3’s &lt;tt class="docutils literal"&gt;chr&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;zip()&lt;/tt&gt; now returns an iterator&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Order comparison operators now raise &lt;tt class="docutils literal"&gt;TypeError&lt;/tt&gt; when given operands of
different types&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sorted()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;list.sort()&lt;/tt&gt; no longer accept the &lt;tt class="docutils literal"&gt;cmp&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;cmp()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__cmp__()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Dividing two integers with &lt;tt class="docutils literal"&gt;/&lt;/tt&gt; now returns a float&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;stdin&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;stdout&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;stderr&lt;/tt&gt; are now text streams&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;maxint&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;exitfunc()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;exc_clear()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;exc_type&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;exc_value&lt;/tt&gt;,
and &lt;tt class="docutils literal"&gt;exc_traceback&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;itertools&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;imap()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;ifilter()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;izip()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ifilterfalse()&lt;/tt&gt; renamed to &lt;tt class="docutils literal"&gt;filterfalse()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;izip_longest()&lt;/tt&gt; renamed to &lt;tt class="docutils literal"&gt;zip_longest()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;math&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;ceil()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;floor()&lt;/tt&gt; now return integers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;array&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;array.read()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;array.write()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;c&lt;/tt&gt; typecode removed&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;operator&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;sequenceIncludes()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;isCallable()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;random&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;jumpahead()&lt;/tt&gt; API removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;os&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;tmpnam()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;tempnam()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;tmpfile()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;string&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;letters&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;lowercase&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;uppercase&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;__builtin__&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;builtins&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Octal literals now use the prefix &lt;tt class="docutils literal"&gt;0o&lt;/tt&gt; instead of just &lt;tt class="docutils literal"&gt;0&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Python 2’s &lt;tt class="docutils literal"&gt;str&lt;/tt&gt; is Python 3’s &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt;; Python 2’s &lt;tt class="docutils literal"&gt;unicode&lt;/tt&gt; is Python
3’s &lt;tt class="docutils literal"&gt;str&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;All string literals are now text/Unicode &lt;tt class="docutils literal"&gt;str&lt;/tt&gt;s&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;u&lt;/tt&gt; prefix for text string literals is no longer supported (later
reintroduced in Python 3.3)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Mixing byte strings and text strings now produces a &lt;tt class="docutils literal"&gt;TypeError&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;\uXXXX&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;\UXXXXXXXX&lt;/tt&gt; escapes in raw string literals are now
interpreted literally instead of being converted to Unicode characters&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;As a consequence of this, the &lt;tt class="docutils literal"&gt;ur&lt;/tt&gt; string prefix is no longer supported&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;basestring&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;repr()&lt;/tt&gt; of a string now longer escapes non-ASCII characters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The default Python source encoding is now UTF-8&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Non-ASCII letters are now allowed in identifiers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;StringIO&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;cStringIO&lt;/tt&gt; removed; use &lt;tt class="docutils literal"&gt;io.StringIO&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;io.BytesIO&lt;/tt&gt; instead&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Function arguments and return values can now be annotated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Functions now have an &lt;tt class="docutils literal"&gt;__annotations__&lt;/tt&gt; attribute&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Named parameters after &lt;tt class="docutils literal"&gt;*args&lt;/tt&gt; or a bare &lt;tt class="docutils literal"&gt;*&lt;/tt&gt; in a function signature are
now keyword-only&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Keyword arguments are allowed after the list of base classes in a class
definition&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New keyword: &lt;tt class="docutils literal"&gt;nonlocal&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Extended iterable unpacking: Statements like &lt;tt class="docutils literal"&gt;a, b, *rest = some_sequence&lt;/tt&gt;
are now supported&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Dictionary comprehensions added: &lt;tt class="docutils literal"&gt;{k: v for k, v in stuff}&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Set literals and set comprehensions added: &lt;tt class="docutils literal"&gt;{1, 2}&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;{x for x in
stuff}&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New builtin functions: &lt;tt class="docutils literal"&gt;ascii()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;next()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;intern()&lt;/tt&gt; moved to &lt;tt class="docutils literal"&gt;sys.intern()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Builtins &lt;tt class="docutils literal"&gt;apply()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;buffer()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;callable()&lt;/tt&gt; (later reintroduced in
Python 3.2), &lt;tt class="docutils literal"&gt;coerce()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;execfile()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;file&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;reduce()&lt;/tt&gt; moved to &lt;tt class="docutils literal"&gt;functools.reduce()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;reload()&lt;/tt&gt; moved to &lt;tt class="docutils literal"&gt;imp.reload()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;dict.has_key()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;round()&lt;/tt&gt;’s rounding strategy and return type changed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;True&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;False&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;None&lt;/tt&gt; are now reserved words&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The syntax for using a metaclass has changed from:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;to:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;C&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metaclass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Special method &lt;tt class="docutils literal"&gt;__prepare__&lt;/tt&gt; on metaclasses added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Module-global &lt;tt class="docutils literal"&gt;__metaclass__&lt;/tt&gt; variable no longer supported&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;List comprehensions of the form &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;[...&lt;/span&gt; for var in item1, item2, &lt;span class="pre"&gt;...]&lt;/span&gt;&lt;/tt&gt; must
now be written &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;[...&lt;/span&gt; for var in (item1, item2, &lt;span class="pre"&gt;...)]&lt;/span&gt;&lt;/tt&gt; instead.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The loop control variables of list comprehensions are no longer leaked into
the surrounding scope&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;...&lt;/tt&gt; (the ellipsis) can now be used as an expression anywhere, and it can
no longer be spelled &lt;tt class="docutils literal"&gt;. . .&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Tuple unpacking in function parameters no longer supported&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Calling &lt;tt class="docutils literal"&gt;repr()&lt;/tt&gt; via backticks no longer supported&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;&amp;lt;&amp;gt;&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Trailing &lt;tt class="docutils literal"&gt;l&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;L&lt;/tt&gt; on integer literals no longer supported&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;from module import *&lt;/tt&gt; is no longer allowed inside functions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;All module imports where the module name does not start with a period are now
treated as absolute imports&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Classic classes removed; all classes are now new-style&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The following modules are removed: &lt;tt class="docutils literal"&gt;audiodev&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Bastion/rexec&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;bsddb185&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;bsddb3&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Canvas&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;cfmfile&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;cl&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;commands&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;compiler&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;dircache&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;dl&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;fpformat&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;gopherlib&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;htmllib&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;ihooks&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;imageop&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;imputil&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;linuxaudiodev&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;md5&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;mhlib&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;mimetools&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;MimeWriter&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;mimify&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;multifile&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;mutex&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;new&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;popen2&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;posixfile&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;pure&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;rfc822&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;sets&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;sgmllib&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;sha&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;sre&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;statvfs&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;stringold&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;sunaudio&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;sv&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;test.testall&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;thread&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;timing&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;toaiff&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;user&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;UserDict&lt;/tt&gt;
(moved to &lt;tt class="docutils literal"&gt;collections&lt;/tt&gt;), &lt;tt class="docutils literal"&gt;UserList&lt;/tt&gt; (moved to &lt;tt class="docutils literal"&gt;collections&lt;/tt&gt;), and
&lt;tt class="docutils literal"&gt;UserString&lt;/tt&gt; (moved to &lt;tt class="docutils literal"&gt;collections&lt;/tt&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;All IRIX-specific, Mac-specific, and Solaris-specific modules removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;_winreg&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;winreg&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ConfigParser&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;configparser&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;copy_reg&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;copyreg&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Queue&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;queue&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;SocketServer&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;socketserver&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;cPickle&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;_pickle&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;cProfile&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;_profile&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;repr&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;reprlib&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;test.test_support&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;test.support&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The modules &lt;tt class="docutils literal"&gt;anydbm&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;dbhash&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;dbm&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;dumbdm&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;gdbm&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;whichdb&lt;/tt&gt; have been combined into a new &lt;tt class="docutils literal"&gt;dbm&lt;/tt&gt; module&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;HTMLParser&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;html.parser&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;htmlentitydefs&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;html.entities&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;httplib&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;http.client&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The modules &lt;tt class="docutils literal"&gt;BaseHTTPServer&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;CGIHTTPServer&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;SimpleHTTPServer&lt;/tt&gt;
have been combined into a new &lt;tt class="docutils literal"&gt;http.server&lt;/tt&gt; module&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Cookie&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;`http.cookies&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;cookielib&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;http.cookiejar&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;tkinter modules renamed as follows:&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="41%" /&gt;
&lt;col width="59%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Old Name&lt;/th&gt;
&lt;th class="head"&gt;New Name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;Dialog&lt;/td&gt;
&lt;td&gt;tkinter.dialog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;FileDialog&lt;/td&gt;
&lt;td&gt;tkinter.filedialog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;FixTk&lt;/td&gt;
&lt;td&gt;tkinter._fix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;ScrolledText&lt;/td&gt;
&lt;td&gt;tkinter.scrolledtext&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;SimpleDialog&lt;/td&gt;
&lt;td&gt;tkinter.simpledialog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Tix&lt;/td&gt;
&lt;td&gt;tkinter.tix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Tkconstants&lt;/td&gt;
&lt;td&gt;tkinter.constants&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Tkdnd&lt;/td&gt;
&lt;td&gt;tkinter.dnd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Tkinter&lt;/td&gt;
&lt;td&gt;tkinter.__init__&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;tkColorChooser&lt;/td&gt;
&lt;td&gt;tkinter.colorchooser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;tkCommonDialog&lt;/td&gt;
&lt;td&gt;tkinter.commondialog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;tkFileDialog&lt;/td&gt;
&lt;td&gt;tkinter.filedialog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;tkFont&lt;/td&gt;
&lt;td&gt;tkinter.font&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;tkMessageBox&lt;/td&gt;
&lt;td&gt;tkinter.messagebox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;tkSimpleDialog&lt;/td&gt;
&lt;td&gt;tkinter.simpledialog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;turtle&lt;/td&gt;
&lt;td&gt;tkinter.turtle&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;urllib2&lt;/tt&gt; module split into &lt;tt class="docutils literal"&gt;urllib.request&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;urllib.error&lt;/tt&gt; modules&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;urlparse&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;urllib.parse&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;urllib&lt;/tt&gt; module split into &lt;tt class="docutils literal"&gt;urllib.parse&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;urllib.request&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;urllib.error&lt;/tt&gt; modules&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;robotparser&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;urllib.robotparser&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;xmlrpclib&lt;/tt&gt; module renamed to &lt;tt class="docutils literal"&gt;xmlrpc.client&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The modules &lt;tt class="docutils literal"&gt;DocXMLRPCServer&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;SimpleXMLRPCServer&lt;/tt&gt; have been combined
into a new &lt;tt class="docutils literal"&gt;xmlrpc.server&lt;/tt&gt; module&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Exceptions must now inherit from &lt;tt class="docutils literal"&gt;BaseException&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;StandardError&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Exceptions no longer behave like sequences; use the &lt;tt class="docutils literal"&gt;args&lt;/tt&gt; attribute
instead&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;except exc, var&lt;/tt&gt; is now written &lt;tt class="docutils literal"&gt;except exc as var&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The variable used to catch an exception is now deleted when the &lt;tt class="docutils literal"&gt;except&lt;/tt&gt;
block is left&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;raise Exception, args&lt;/tt&gt; is now written &lt;tt class="docutils literal"&gt;raise Exception(args)&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Raising an exception inside an &lt;tt class="docutils literal"&gt;except&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;finally&lt;/tt&gt; block now causes
implicit exception chaining&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Explicit exception chaining can be done with &lt;tt class="docutils literal"&gt;raise SecondaryException()
from primary_exception&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;__getslice__()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;__setslice__()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;__delslice__()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Special method &lt;tt class="docutils literal"&gt;next()&lt;/tt&gt; renamed to &lt;tt class="docutils literal"&gt;__next__()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;__oct__()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__hex__()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Removed support for &lt;tt class="docutils literal"&gt;__members__&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__methods__&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Function attributes of the form &lt;tt class="docutils literal"&gt;func_X&lt;/tt&gt; renamed to &lt;tt class="docutils literal"&gt;__X__&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Special method &lt;tt class="docutils literal"&gt;__nonzero__()&lt;/tt&gt; renamed to &lt;tt class="docutils literal"&gt;__bool__()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;super()&lt;/tt&gt; can now be invoked without arguments inside an instance method&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-1-2009-06-26"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.1 (2009-06-26)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3/whatsnew/3.1.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Multiple context managers can now be used in a single &lt;tt class="docutils literal"&gt;with&lt;/tt&gt; statement&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Directories &amp;amp; zip archives containing a &lt;tt class="docutils literal"&gt;__main__.py&lt;/tt&gt; can now be executed
by passing their path to the interpreter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Packages containing a &lt;tt class="docutils literal"&gt;__main__&lt;/tt&gt; submodule can now be executed with
&lt;tt class="docutils literal"&gt;python &lt;span class="pre"&gt;-m&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;runpy&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;bytearray&lt;/tt&gt; method: &lt;tt class="docutils literal"&gt;maketrans()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;repr()&lt;/tt&gt;s of &lt;tt class="docutils literal"&gt;float&lt;/tt&gt;s are now shorter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;int&lt;/tt&gt; method: &lt;tt class="docutils literal"&gt;bit_length()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The fields in strings formatted with &lt;tt class="docutils literal"&gt;str.format()&lt;/tt&gt; can now omit numbering
in order to be automatically numbered, as in &lt;tt class="docutils literal"&gt;'Sir {} of
&lt;span class="pre"&gt;{}'.format('Gallahad',&lt;/span&gt; 'Camelot')&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The format specification mini-language now includes a thousands separator
specifier&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;round(x, n)&lt;/tt&gt; now returns an integer if &lt;tt class="docutils literal"&gt;x&lt;/tt&gt; is an integer&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New modules: &lt;tt class="docutils literal"&gt;importlib&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;tkinter.ttk&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;collections&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Counter&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;OrderedDict&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;namedtuple()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;rename&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;contextlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;nested()&lt;/tt&gt; is now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;decimal&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Decimal.from_float()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;io&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;SEEK_SET&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;SEEK_CUR&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;SEEK_END&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;itertools&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;combinations_with_replacement()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;compress()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;count()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;step&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;json&lt;/tt&gt; module: Decoders now accept an &lt;tt class="docutils literal"&gt;object_pairs_hook&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;logging&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;NullHandler&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;re&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;sub()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;subn()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;split()&lt;/tt&gt; now accept a &lt;tt class="docutils literal"&gt;flags&lt;/tt&gt;
parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;string&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;maketrans()&lt;/tt&gt; is now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-2-2011-02-20"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.2 (2011-02-20)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3/whatsnew/3.2.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;New modules: &lt;tt class="docutils literal"&gt;argparse&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;concurrent.futures&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;html&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;sysconfig&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;.pyc&lt;/tt&gt; files are now stored in &lt;tt class="docutils literal"&gt;__pycache__/&lt;/tt&gt; directories&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Modules now have a &lt;tt class="docutils literal"&gt;__cached__&lt;/tt&gt; attribute&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;str&lt;/tt&gt; method: &lt;tt class="docutils literal"&gt;format_map()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;str()&lt;/tt&gt; of a &lt;tt class="docutils literal"&gt;float&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;complex&lt;/tt&gt; is now the same as its &lt;tt class="docutils literal"&gt;repr()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;range&lt;/tt&gt; methods: &lt;tt class="docutils literal"&gt;index()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;count()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;callable()&lt;/tt&gt; function from Python 2 restored&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ResourceWarning&lt;/tt&gt; warning type added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;abc&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;abstractclassmethod()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;abstractstaticmethod()&lt;/tt&gt;
added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ast&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;literal_eval()&lt;/tt&gt; now supports &lt;tt class="docutils literal"&gt;set&lt;/tt&gt; &amp;amp; &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt; literals&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;collections&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Counter.subtract()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;OrderedDict.move_to_end()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;deque.count()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;deque.reverse()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;compileall&lt;/tt&gt; command-line interface: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-i&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-b&lt;/span&gt;&lt;/tt&gt; options added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;configparser&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ConfigParser&lt;/tt&gt; class replaced with &lt;tt class="docutils literal"&gt;SafeConfigParser&lt;/tt&gt;, which is now
customizable&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New API added based on the mapping protocol&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;contextlib&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ContextDecorator&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;nested()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;csv&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unix_dialect&lt;/tt&gt; dialect (dialect name &lt;tt class="docutils literal"&gt;&amp;quot;unix&amp;quot;&lt;/tt&gt;) added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;DictWriter.writeheader()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;timezone&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;timedelta&lt;/tt&gt; instances can now be multiplied by &lt;tt class="docutils literal"&gt;float&lt;/tt&gt;s and divided by
&lt;tt class="docutils literal"&gt;float&lt;/tt&gt;s &amp;amp; &lt;tt class="docutils literal"&gt;int&lt;/tt&gt;s&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;date.strftime()&lt;/tt&gt; now supports years from 1000 through 9999&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;decimal&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;Decimal&lt;/tt&gt; constructor now accepts &lt;tt class="docutils literal"&gt;float&lt;/tt&gt;s&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Decimal&lt;/tt&gt; instances can now be compared with &lt;tt class="docutils literal"&gt;float&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;fractions.Fraction&lt;/tt&gt; instances&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Context.clamp&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;email.parser&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;BytesFeedParser&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;BytesParser&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;message_from_bytes()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;message_from_binary_file()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;email.generator&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;BytesGenerator&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;fractions&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;Fraction&lt;/tt&gt; constructor now accepts &lt;tt class="docutils literal"&gt;float&lt;/tt&gt;s
and &lt;tt class="docutils literal"&gt;decimal.Decimal&lt;/tt&gt;s&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;functools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;cmp_to_key()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;lru_cache()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;total_ordering()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;gzip&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;compress()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;decompress()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;hashlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;algorithms_available&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;algorithms_guaranteed&lt;/tt&gt;
added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Various ABCs added to &lt;tt class="docutils literal"&gt;importlib.abc&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;inspect&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;getgeneratorstate()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;getattr_static()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;io&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;BytesIO.getbuffer()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;itertools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;accumulate()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;json&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;indent&lt;/tt&gt; parameter to &lt;tt class="docutils literal"&gt;dumps()&lt;/tt&gt; etc. can now be a
string&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;logging&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;basicConfig()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;style&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If a logging event occurs before any explicit configuration is set up, a
default configuration (available in &lt;tt class="docutils literal"&gt;lastResort&lt;/tt&gt;) is now enabled&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Python callables returning booleans can now be used as filters&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;logging.config&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;dictConfig()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;math&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;isfinite()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;expm1()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;erf()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;erfc()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;gamma()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;lgamma()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;os&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;fsencode()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;fsdecode()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;supports_bytes_environ&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;getenvb()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;environb&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;shutil&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;copytree()&lt;/tt&gt; now accepts &lt;tt class="docutils literal"&gt;ignore_dangling_symlinks&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;copy_function&lt;/tt&gt; parameters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;make_archive()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;unpack_archive()&lt;/tt&gt;, etc. added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;site&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;getsitepackage()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;getuserbase()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;getusersitepackages()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;smtplib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;SMTP.send_message()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ssl&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;SSLContext&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;match_hostname()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Server Name Indication (SNI) is now supported when linked against recent
versions of OpenSSL&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;string&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;maketrans()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;hash_info&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;tarfile&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;TarFile.add()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;filter&lt;/tt&gt; parameter, and
the &lt;tt class="docutils literal"&gt;exclude&lt;/tt&gt; parameter is now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;tempfile&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;TemporaryDirectory&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;threading&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Barrier&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unicodedata&lt;/tt&gt; updated to Unicode 6.0.0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;urllib.parse&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;urlparse()&lt;/tt&gt; now supports IPv6 addresses&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-3-2012-09-29"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.3 (2012-09-29)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3/whatsnew/3.3.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;New modules: &lt;tt class="docutils literal"&gt;faulthandler&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;ipaddress&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;lzma&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;unittest.mock&lt;/tt&gt;,
and &lt;tt class="docutils literal"&gt;venv&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Support for implicit namespace packages (directories without an
&lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt;) added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;All Unicode codepoints, from U+0000 to U+10FFFF, are now always supported;
there is no longer a distinction between “narrow” and “wide” builds&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Multiple exception types have been merged into &lt;tt class="docutils literal"&gt;OSError&lt;/tt&gt;, which now has
various subclasses for common error conditions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Delegating to a subgenerator/subiterator with &lt;tt class="docutils literal"&gt;yield from&lt;/tt&gt; is now possible&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Chained exception context can be suppressed with &lt;tt class="docutils literal"&gt;raise e from None&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;u&amp;quot;unicode&amp;quot;&lt;/tt&gt; syntax for Unicode strings from Python 2 is now supported
again&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Functions &amp;amp; classes now have a &lt;tt class="docutils literal"&gt;__qualname__&lt;/tt&gt; attribute&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;inspect&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;signature()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Signature&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Parameter&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;BoundArguments&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;implementation&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;types&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;SimpleNamespace&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;importlib&lt;/tt&gt; module: Various classes &amp;amp; functions added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Modules now have a &lt;tt class="docutils literal"&gt;__loader__&lt;/tt&gt; attribute&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;quot;\N{...}&amp;quot;&lt;/span&gt;&lt;/tt&gt; can now take name aliases&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unicodedata&lt;/tt&gt; updated to UCD 6.1.0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;list&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;bytearray&lt;/tt&gt; methods: &lt;tt class="docutils literal"&gt;copy()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;clear()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Raw bytes literals can now be written &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;rb&amp;quot;...&amp;quot;&lt;/span&gt;&lt;/tt&gt; in addition to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;br&amp;quot;...&amp;quot;&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;open()&lt;/tt&gt; now accepts an &lt;tt class="docutils literal"&gt;opener&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;print()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;flush&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Hash randomization with &lt;tt class="docutils literal"&gt;hash()&lt;/tt&gt; is now enabled by default&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;str&lt;/tt&gt; method: &lt;tt class="docutils literal"&gt;casefold()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;abc&lt;/tt&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;It is now possible to combine &lt;tt class="docutils literal"&gt;abstractmethod&lt;/tt&gt; with &lt;tt class="docutils literal"&gt;property&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;classmethod&lt;/tt&gt;, or &lt;tt class="docutils literal"&gt;staticmethod&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;abstractproperty&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;abstractclassmethod&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;abstractstaticmethod&lt;/tt&gt;
are now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ABCMeta.register()&lt;/tt&gt; can now be used as a class decorator&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;array&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;long long&lt;/tt&gt; type now supported&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;base64&lt;/tt&gt; module: Decoding functions now accept ASCII-only &lt;tt class="docutils literal"&gt;str&lt;/tt&gt;s&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;binascii&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;a2b_*&lt;/tt&gt; functions now accept ASCII-only &lt;tt class="docutils literal"&gt;str&lt;/tt&gt;s&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;bz2&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;open()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;BZ2File()&lt;/tt&gt; now accepts arbitrary file-like objects and implements most
of the &lt;tt class="docutils literal"&gt;io.BufferedIOBase&lt;/tt&gt; API&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;collections&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ChainMap&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;ABCs moved to &lt;tt class="docutils literal"&gt;collections.abc&lt;/tt&gt;; aliases are still present in
&lt;tt class="docutils literal"&gt;collections&lt;/tt&gt; itself, but importing them is deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Counter&lt;/tt&gt; now supports &lt;tt class="docutils literal"&gt;+&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;-&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;+=&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-=&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;|=&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;&amp;amp;=&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;contextlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;ExitStack&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; module: New &lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; methods: &lt;tt class="docutils literal"&gt;timestamp()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;strftime()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;astimezone()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;email&lt;/tt&gt; module: Policy framework added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;email.parser&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;BytesHeaderParser&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;email.utils&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;format_datetime()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;parsedate_to_datetime()&lt;/tt&gt;,
and &lt;tt class="docutils literal"&gt;localtime()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;functools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;lru_cache()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;typed&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;hmac&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;compare_digest()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;http.client&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;HTTPResponse.readinto()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;html.parser&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;HTMLParser&lt;/tt&gt; can now parse broken markup without
errors&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;html.entities&lt;/tt&gt;: &lt;tt class="docutils literal"&gt;html5&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;inspect&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;getclosurevars()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;getgeneratorlocals()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;io&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;x&lt;/tt&gt; mode added to &lt;tt class="docutils literal"&gt;open()&lt;/tt&gt; function&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;TextIOWrapper&lt;/tt&gt; constructor now accepts a &lt;tt class="docutils literal"&gt;write_through&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;itertools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;accumulate()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;func&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;logging&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;basicConfig()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;handlers&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;math&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;log2()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;multiprocessing&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;Process&lt;/tt&gt; constructor now accepts a &lt;tt class="docutils literal"&gt;daemon&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Process.sentinel&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;multiprocessing.connection&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;wait()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;multiprocessing.pool&lt;/tt&gt; module: New &lt;tt class="docutils literal"&gt;Pool&lt;/tt&gt; methods &lt;tt class="docutils literal"&gt;starmap()&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;starmap_async()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;os&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;fwalk()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;pipe2()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;sendfile()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;getpriority()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;setpriority()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;replace()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;get_terminal_size()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;getxattr()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;listxattr()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;removexattr()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;setxatter()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;sync()&lt;/tt&gt;, and others
added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Various functions now accept &lt;tt class="docutils literal"&gt;dir_fd&lt;/tt&gt; and/or &lt;tt class="docutils literal"&gt;follow_symlinks&lt;/tt&gt;
parameters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Various functions can now take file descriptors as path arguments&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;stat()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;fstat()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;lstat()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;utime()&lt;/tt&gt; now support
timestamps with nanosecond precision&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;re&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;str&lt;/tt&gt; regular expressions now support &lt;tt class="docutils literal"&gt;\uXXXX&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;\UXXXXXXXX&lt;/tt&gt; escapes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pipes.quote()&lt;/tt&gt; moved to &lt;tt class="docutils literal"&gt;shlex&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;shutil&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;disk_usage()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;chown()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;get_terminal_size()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Several functions now accept a &lt;tt class="docutils literal"&gt;symlink&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;stat&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;filemode()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;struct&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;size_t&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;ssize_t&lt;/tt&gt; now supported&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;subprocess&lt;/tt&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Command strings can now be bytes on POSIX&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;DEVNULL&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;thread_info&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;textwrap&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;indent()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;time&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;get_clock_info()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;monotonic()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;perf_counter()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;process_time()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;clock_getres()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;clock_gettime()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;clock_settime()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;CLOCK_*&lt;/tt&gt; constants added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;types&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;MappingProxyType&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;new_class()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;prepare_class()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;urllib.request&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;Request&lt;/tt&gt; constructor now accepts a
&lt;tt class="docutils literal"&gt;method&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;array&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;u&lt;/tt&gt; format is now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-4-2014-03-17"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.4 (2014-03-17)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3/whatsnew/3.4.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;New modules: &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;ensurepip&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;enum&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;pathlib&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;selectors&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;statistics&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;tracemalloc&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;codecs&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;encode()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;decode()&lt;/tt&gt; are now documented&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unicodedata&lt;/tt&gt; updated to UCD 6.3&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;min()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;max()&lt;/tt&gt; now accept a &lt;tt class="docutils literal"&gt;default&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New special method: &lt;tt class="docutils literal"&gt;__length_hint__()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;abc&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;ABC&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;get_cache_token()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;argparse&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;FileType&lt;/tt&gt; now accepts &lt;tt class="docutils literal"&gt;encoding&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;errors&lt;/tt&gt;
parameters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;base64&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Encoding &amp;amp; decoding functions now accept any bytes-like object&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;a85encode()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;a85decode()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;b85encode()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;b85decode()&lt;/tt&gt;
added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;contextlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;suppress()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;redirect_stdout()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;doctest&lt;/tt&gt; command-line interface: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-o&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-f&lt;/span&gt;&lt;/tt&gt; options added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;email&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;as_string()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;policy&lt;/tt&gt; argument&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;as_bytes()&lt;/tt&gt; method added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;EmailMessage&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;MIMEPart&lt;/tt&gt; added as part of new API&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;contextmanager&lt;/tt&gt; submodule added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;filecmp&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;clear_cache()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;DEFAULT_IGNORES&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;functools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;partialmethod()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;singledispatch()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;glob&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;escape()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;hashlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;pbkdf2_hmac()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;html&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;unescape()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;html.parser&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;HTMLParser&lt;/tt&gt; constructor now accepts a
&lt;tt class="docutils literal"&gt;convert_charrefs&lt;/tt&gt; parameter, and the &lt;tt class="docutils literal"&gt;strict&lt;/tt&gt; argument is now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;http.server&lt;/tt&gt; command-line interface: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--bind&lt;/span&gt;&lt;/tt&gt; option added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;imp.reload()&lt;/tt&gt; moved to &lt;tt class="docutils literal"&gt;importlib&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;importlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;InspectLoader.source_to_code()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;importlib.util&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;MAGIC_NUMBER&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;cache_from_source()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;source_from_cache()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;decode_source()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;importlib.machinery&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;ExtensionFileLoader.get_filename()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;runpy&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;python &lt;span class="pre"&gt;-m&lt;/span&gt;&lt;/tt&gt; can now be used with namespace packages&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;inspect&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Command-line interface added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unwrap()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ipaddress&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;is_global&lt;/tt&gt; property added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;json&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;dumps()&lt;/tt&gt; etc. will now automatically set &lt;tt class="docutils literal"&gt;separators&lt;/tt&gt;
to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;(&amp;quot;,&amp;quot;,&lt;/span&gt; &amp;quot;: &amp;quot;)&lt;/tt&gt; when &lt;tt class="docutils literal"&gt;indent&lt;/tt&gt; is non-&lt;tt class="docutils literal"&gt;None&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;multiprocessing&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Start methods &lt;tt class="docutils literal"&gt;spawn&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;forkserver&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Contexts added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;get_all_start_methods()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;get_start_method()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;set_start_method()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;get_context()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;operator&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;length_hint()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;os&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;cpu_count()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;open()&lt;/tt&gt; now supports the &lt;tt class="docutils literal"&gt;O_PATH&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;O_TMPFILE&lt;/tt&gt; flags&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pdb&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;print&lt;/tt&gt; command removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pickle&lt;/tt&gt; module: Protocol 4 added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;plistlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;load()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;dump()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;loads()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;dumps()&lt;/tt&gt;
added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pprint&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;PrettyPrinter&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;pformat()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;pprint()&lt;/tt&gt; now
accept a &lt;tt class="docutils literal"&gt;compact&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;re&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;fullmatch()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;regex.fullmatch()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;resource&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;prlimit()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;shutil&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;copyfile()&lt;/tt&gt; now raises a &lt;tt class="docutils literal"&gt;SameFileError&lt;/tt&gt; when the
source and destination are the same file&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ssl&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;create_default_context()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;get_default_verify_paths()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;SSLContext&lt;/tt&gt; methods: &lt;tt class="docutils literal"&gt;cert_store_stats()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;get_ca_certs()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;load_default_certs()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;stat&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;S_IFDOOR&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;S_IFPORT&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;S_IFWHT&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;struct&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;iter_unpack()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;Struct.iter_unpack()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;subprocess&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;check_output()&lt;/tt&gt; now accepts an &lt;tt class="docutils literal"&gt;input&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;getallocatedblocks()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__interactivehook__&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;tarfile&lt;/tt&gt; module: Command-line interface added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;textwrap&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;TextWrapper&lt;/tt&gt; constructor now accepts &lt;tt class="docutils literal"&gt;max_lines&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;placeholder&lt;/tt&gt; parameters&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;shorten()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;threading&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;main_thread()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;traceback&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;clear_frames()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;types&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;DynamicClassAttribute()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;urllib.request&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;data:&lt;/tt&gt; URLs now supported&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Request&lt;/tt&gt; objects are now reusable&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;urllib.error&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;HTTPError.headers&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;venv&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;EnvBuilder&lt;/tt&gt; constructor and &lt;tt class="docutils literal"&gt;create()&lt;/tt&gt; now accept a
&lt;tt class="docutils literal"&gt;with_pip&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;importlib&lt;/tt&gt; module: A number of methods &amp;amp; functions are deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;imp&lt;/tt&gt; module is now deprecated and will be removed in Python 3.12&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;formatter&lt;/tt&gt; module is now deprecated and will be removed in Python 3.10&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;U&lt;/tt&gt; mode of various “open” functions is now deprecated and will be
removed in Python 3.11&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-5-2015-09-13"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.5 (2015-09-13)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3/whatsnew/3.5.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Coroutine functions (&lt;tt class="docutils literal"&gt;async def&lt;/tt&gt;), awaitable objects (&lt;tt class="docutils literal"&gt;await&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;__await__()&lt;/tt&gt;), asynchronous iteration (&lt;tt class="docutils literal"&gt;async for&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;__aiter__()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;__anext__()&lt;/tt&gt;), and asynchronous context managers (&lt;tt class="docutils literal"&gt;async with&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;__aenter__()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;__aexit__()&lt;/tt&gt;) added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;&amp;#64;&lt;/tt&gt; operator (with &lt;tt class="docutils literal"&gt;__matmul__()&lt;/tt&gt; etc. special methods) for matrix
multiplication added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Multiple &lt;tt class="docutils literal"&gt;*&lt;/tt&gt; and/or &lt;tt class="docutils literal"&gt;**&lt;/tt&gt; unpackings can now be used in a single function
call&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Tuple, list, set, &amp;amp; dictionary displays may now contain &lt;tt class="docutils literal"&gt;*&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;**&lt;/tt&gt;
unpackings (as appropriate)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Percent-formatting of &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;bytearray&lt;/tt&gt; objects with &lt;tt class="docutils literal"&gt;%&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New modules: &lt;tt class="docutils literal"&gt;typing&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;zipapp&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;System calls are now retried when interrupted by a signal&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;from __future__ import generator_stop&lt;/tt&gt; added to cause &lt;tt class="docutils literal"&gt;StopIteration&lt;/tt&gt;
exceptions raised inside generators to be transformed into
&lt;tt class="docutils literal"&gt;RuntimeException&lt;/tt&gt;s, which becomes the default in Python 3.7&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Without the &lt;tt class="docutils literal"&gt;__future__&lt;/tt&gt; import, such exceptions generate
&lt;tt class="docutils literal"&gt;PendingDeprecationWarning&lt;/tt&gt;s.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;RecursionError&lt;/tt&gt; exception type (a subclass of &lt;tt class="docutils literal"&gt;RuntimeError&lt;/tt&gt;) added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;.pyo&lt;/tt&gt; files eliminated; optimized bytecode is now stored in &lt;tt class="docutils literal"&gt;.pyc&lt;/tt&gt; files
with &lt;tt class="docutils literal"&gt;opt-&lt;/tt&gt; tags in their name&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;&amp;quot;namereplace&amp;quot;&lt;/tt&gt; error handler added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Various additions &amp;amp; improvements to the &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; module&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;cmath&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;isclose()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;collections&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;deque&lt;/tt&gt; methods: &lt;tt class="docutils literal"&gt;index()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;insert()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;copy()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;deque&lt;/tt&gt; now supports &lt;tt class="docutils literal"&gt;+&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;*&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;collections.abc&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Generator&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Awaitable&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Coroutine&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;AsyncIterator&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;AsyncIterable&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;configparser&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;ConfigParser&lt;/tt&gt; can now take a dictionary of
converters, and subclasses can define additional converters as methods&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;contextlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;redirect_stderr()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;enum&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt; callable now accepts a &lt;tt class="docutils literal"&gt;start&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;glob&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;glob()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;iglob()`&lt;/span&gt; now support the &lt;span class="pre"&gt;``**&lt;/span&gt;&lt;/tt&gt; pattern&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;http&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;HTTPStatus&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;importlib.util&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;module_from_spec()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;inspect&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;BoundArguments.apply_defaults()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Signature.from_callable()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;signature()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;follow_wrapped&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;iscoroutine()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;iscoroutinefunction()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;isawaitable()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;getcoroutinelocals()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;getcoroutinestate()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;io&lt;/tt&gt; module: new &lt;tt class="docutils literal"&gt;BufferedIOBase&lt;/tt&gt; method: &lt;tt class="docutils literal"&gt;readinto1()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ipaddress&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;IPv4Network&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;IPv6Network&lt;/tt&gt; constructors now accept an
&lt;tt class="docutils literal"&gt;(address, netmask)&lt;/tt&gt; argument&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;IPv4Network&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;IPv6Network&lt;/tt&gt; attribute: &lt;tt class="docutils literal"&gt;reverse_pointer&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;json&lt;/tt&gt; module: JSON decoding errors now raise &lt;tt class="docutils literal"&gt;JSONDecodeError&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;json.tool&lt;/tt&gt; command-line interface: The input order of keys is now
preserved on output; the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--sort-keys&lt;/span&gt;&lt;/tt&gt; option will sort the keys instead&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;linecache&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;lazycache()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;locale&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;delocalize()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;logging&lt;/tt&gt; module: Logging methods now accept exception instances as
&lt;tt class="docutils literal"&gt;exc_info&lt;/tt&gt; arguments&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;math&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;isclose()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;gcd()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;inf&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;nan&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;fractions&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;gcd()&lt;/tt&gt; is now deprecated and will be removed in
Python 3.9&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;operator&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;matmul()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;imatmul()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;os&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;scandir()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;os.path&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;commonpath()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pathlib&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;Path&lt;/tt&gt; methods: &lt;tt class="docutils literal"&gt;samefile()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;expanduser()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;write_text()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;read_text()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;write_bytes()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;read_bytes()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Class method &lt;tt class="docutils literal"&gt;Path.home()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Path.mkdir()&lt;/tt&gt; now accepts an &lt;tt class="docutils literal"&gt;exist_ok&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;readline&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;append_history_file()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;selectors&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;DevpollSelector&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;shutil&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;move()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;copy_function&lt;/tt&gt; argument&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;signal&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;SIG*&lt;/tt&gt; constants have been converted to enums&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;socket&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;socket.sendfile()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ssl&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;SSLObject&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;subprocess&lt;/tt&gt;: &lt;tt class="docutils literal"&gt;run()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;set_coroutine_wrapper()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;get_coroutine_wrapper()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;is_finalizing()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;time&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;monotonic()&lt;/tt&gt; is now always available&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;timeit&lt;/tt&gt; command-line interface: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--unit&lt;/span&gt;&lt;/tt&gt; option added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;traceback&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;TracebackException&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;StackSummary&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;FrameSummary&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;walk_stack()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;walk_tb()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;types&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;CoroutineType&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;coroutine()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unicodedata&lt;/tt&gt; updated to Unicode 8.0.0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unittest&lt;/tt&gt; command-line interface: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--locals&lt;/span&gt;&lt;/tt&gt; option added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unittest.mock&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Mock.assert_not_called()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;urllib.request&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;HTTPPasswordMgrWithPriorAuth&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;platform&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;dist()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;linux_distribution()&lt;/tt&gt; are now
deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;html.parser&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;convert_charrefs&lt;/tt&gt; parameter to the
&lt;tt class="docutils literal"&gt;HTMLParser&lt;/tt&gt; constructor now defaults to &lt;tt class="docutils literal"&gt;True&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-6-2016-12-23"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.6 (2016-12-23)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3/whatsnew/3.6.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Formatted string literals (“f-strings”)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Variables can now be annotated by following the name of the variable with a
colon and the annotation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Underscores can now be used in numeric literals&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;await&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;yield&lt;/tt&gt; can now be used in the same function, thereby
enabling asynchronous generators&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;async for&lt;/tt&gt; can now be used in list, set, &amp;amp; dict comprehensions and in
generator expressions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;await&lt;/tt&gt; expressions can now be used in any comprehension&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Special methods &lt;tt class="docutils literal"&gt;__init_subclass__()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__set_name__()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;os.PathLike&lt;/tt&gt;, the &lt;tt class="docutils literal"&gt;__fspath__()&lt;/tt&gt; method, and &lt;tt class="docutils literal"&gt;os.fspath()&lt;/tt&gt; added&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Relevant file functions now accept &lt;tt class="docutils literal"&gt;os.PathLike&lt;/tt&gt; objects&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ModuleNotFoundError&lt;/tt&gt; exception type (a subclass of &lt;tt class="docutils literal"&gt;ImportError&lt;/tt&gt;) added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;fold&lt;/tt&gt; attribute added to &lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;time&lt;/tt&gt; for denoting the
second instance of a time duplicated due to DST&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;strftime()&lt;/tt&gt; method of &lt;tt class="docutils literal"&gt;date&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; now supports &lt;tt class="docutils literal"&gt;%G&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;%u&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;%V&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;datetime.astimezone()&lt;/tt&gt; can now be called on naïve instances&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The file system and console encodings on Windows are now both UTF-8&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;A class’s &lt;tt class="docutils literal"&gt;__dict__&lt;/tt&gt; now preserves the order in which the attributes were
defined&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;**kwargs&lt;/tt&gt; now preserves insertion order&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;dict&lt;/tt&gt;s are now implemented in such a way that they preserve insertion
order&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New module: &lt;tt class="docutils literal"&gt;secrets&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Various additions &amp;amp; improvements to the &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; module&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;cmath&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;tau&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;inf&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;nan&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;infj&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;nanj&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;collections.abc&lt;/tt&gt;: &lt;tt class="docutils literal"&gt;Collection&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Reversible&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;AsyncGenerator&lt;/tt&gt;
added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;enum&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Flag&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;IntFlag&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;json&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;load()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;loads()&lt;/tt&gt; now support binary input in
UTF-8, UTF-16, and UTF-32&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;math&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;tau&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;random&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;choices()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;re&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Modifier spans (e.g., as in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;'(?i)g(?-i:v)r'&lt;/span&gt;&lt;/tt&gt;) are now supported in
regular expressions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Match objects can now be indexed to access groups&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;statistics&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;harmonic_mean()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;smtpd&lt;/tt&gt; module is now deprecated and will be removed in Python 3.12&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;subprocess&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;encoding&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;errors&lt;/tt&gt; arguments added to &lt;tt class="docutils literal"&gt;Popen&lt;/tt&gt; and the wrappers
around it&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;args&lt;/tt&gt; parameter to &lt;tt class="docutils literal"&gt;Popen&lt;/tt&gt; and the wrappers around it can now be a
path-like object or sequence of path-like objects on POSIX systems&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;time&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;tm_gmtoff&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;tm_zone&lt;/tt&gt; attributes of
&lt;tt class="docutils literal"&gt;struct_time&lt;/tt&gt; are now available on all platforms&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;typing&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Generic type aliases like &lt;tt class="docutils literal"&gt;Dict[str, Tuple[S, T]]&lt;/tt&gt; are now supported&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;TYPE_CHECKING&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ClassVar&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;NewType()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;NamedTuple&lt;/tt&gt; now supports variable annotation syntax&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unittest.mock&lt;/tt&gt; module: New &lt;tt class="docutils literal"&gt;Mock&lt;/tt&gt; methods &lt;tt class="docutils literal"&gt;assert_called()&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;assert_called_once()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;venv&lt;/tt&gt; command-line interface: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--prompt&lt;/span&gt;&lt;/tt&gt; option added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Using &lt;tt class="docutils literal"&gt;async&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; as a name will now generate a
&lt;tt class="docutils literal"&gt;DeprecationWarning&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;StopIteration&lt;/tt&gt; exceptions raised inside generators now generate
&lt;tt class="docutils literal"&gt;DeprecationWarnings&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Invalid escape sequences now generate a &lt;tt class="docutils literal"&gt;DeprecationWarning&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;asynchat&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;asyncore&lt;/tt&gt; modules are now deprecated and will be
removed in Python 3.12&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;pyvenv&lt;/tt&gt; script for creating venvs is now deprecated and will be
removed in Python 3.8&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unicodedata&lt;/tt&gt; updated to Unicode 9.0.0&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-7-2018-06-27"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.7 (2018-06-27)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3/whatsnew/3.7.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;from __future__ import annotations&lt;/tt&gt; added to enable postponed evaluation
of annotations&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;dict&lt;/tt&gt;s are now guaranteed to preserve insertion order&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;async&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; are now reserved keywords&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New modules: &lt;tt class="docutils literal"&gt;contextvars&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;dataclasses&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;importlib.resources&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New builtin function: &lt;tt class="docutils literal"&gt;breakpoint()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The interpreter now coerces ASCII locales to UTF-8 under certain
circumstances on non-Windows OSes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;__aiter__()&lt;/tt&gt; methods can no longer be asynchronous&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;__getattr__()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__dir__()&lt;/tt&gt; can now be defined on modules&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;time&lt;/tt&gt; module: variants of the timer functions added that return a number
of nanoseconds as an integer&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Special methods &lt;tt class="docutils literal"&gt;__class_getitem__()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__mro_entries__()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Python Development Mode added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;str&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;bytearray&lt;/tt&gt; method: &lt;tt class="docutils literal"&gt;isascii()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;argparse&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;ArgumentParser.parser_intermixed_args()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Various additions &amp;amp; improvements to the &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; module&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio.run()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;collections&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;defaults&lt;/tt&gt; argument added to &lt;tt class="docutils literal"&gt;namedtuple()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;contextlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;nullcontext()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;asynccontextmanager()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;AsyncExitStack&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;datetime.fromisoformat()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;&amp;quot;%z&amp;quot;&lt;/tt&gt; format of the &lt;tt class="docutils literal"&gt;strptime()&lt;/tt&gt; methods now accepts timezone
offsets containing colons as well as a timezone specifier of “&lt;tt class="docutils literal"&gt;Z&lt;/tt&gt;”.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;enum&lt;/tt&gt; module: Support for the &lt;tt class="docutils literal"&gt;_ignore_&lt;/tt&gt; class property added to
&lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;functools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;singledispatch()&lt;/tt&gt; now recognizes type annotations&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;http.server&lt;/tt&gt; command-line interface: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--directory&lt;/span&gt;&lt;/tt&gt; option added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ipaddress&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;subnet_of()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;supernet_of()&lt;/tt&gt; methods added to
&lt;tt class="docutils literal"&gt;IPv4Network&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;IPv6Network&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;locale&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;format()&lt;/tt&gt; is now deprecated and will be removed in
Python 3.12&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;math&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;remainder()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pathlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Path.is_mount()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;queue&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;SimpleQueue&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;subprocess&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;capture_output&lt;/tt&gt; argument added to &lt;tt class="docutils literal"&gt;run()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;text&lt;/tt&gt; argument added to &lt;tt class="docutils literal"&gt;run()&lt;/tt&gt; and the &lt;tt class="docutils literal"&gt;Popen&lt;/tt&gt; constructor&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Removed the &lt;tt class="docutils literal"&gt;fpectl&lt;/tt&gt; module&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;StopIteration&lt;/tt&gt; exceptions raised inside coroutines and generators are now
transformed into &lt;tt class="docutils literal"&gt;RuntimeException&lt;/tt&gt;s&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unicodedata&lt;/tt&gt; updated to Unicode 11&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-8-2019-10-14"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.8 (2019-10-14)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3/whatsnew/3.8.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Assignment expressions: &lt;tt class="docutils literal"&gt;:=&lt;/tt&gt; (the “walrus operator”) can now be used to
assign a value to a variable in the middle of an expression, e.g.:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'\d+'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Function parameters can now be made positional-only by placing a &lt;tt class="docutils literal"&gt;/&lt;/tt&gt; after
them in the argument list&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;One can now write &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;f&amp;quot;{var=}&amp;quot;&lt;/span&gt;&lt;/tt&gt; to get &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;f&amp;quot;{var}={repr(var)}&amp;quot;&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;continue&lt;/tt&gt; is now allowed in &lt;tt class="docutils literal"&gt;finally:&lt;/tt&gt; clauses&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;int&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;bool&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;fractions.Fraction&lt;/tt&gt; method:
&lt;tt class="docutils literal"&gt;as_integer_ratio()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;\N{name}&lt;/tt&gt; escapes are now allowed in regular expressions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;dict&lt;/tt&gt;s and dictviews can now be passed to &lt;tt class="docutils literal"&gt;reversed()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Generalized iterable unpacking in &lt;tt class="docutils literal"&gt;yield&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;return&lt;/tt&gt; statements no
longer requires parentheses; e.g., one can now write &lt;tt class="docutils literal"&gt;return foo, *bar&lt;/tt&gt;
instead of having to do &lt;tt class="docutils literal"&gt;return (foo, *bar)&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Missing commas between tuples in a list now generate a &lt;tt class="docutils literal"&gt;SyntaxWarning&lt;/tt&gt; with
a suggestion as to what went wrong&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;For integer arguments, the three-argument form of &lt;tt class="docutils literal"&gt;pow()&lt;/tt&gt; can now take a
negative exponent when the base is coprime to the modulus, in which case the
modular multiplicative inverse (or a power thereof) is calculated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New modules: &lt;tt class="docutils literal"&gt;importlib.metadata&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;multiprocessing.shared_memory&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Running &lt;tt class="docutils literal"&gt;python &lt;span class="pre"&gt;-m&lt;/span&gt; asyncio&lt;/tt&gt; now starts an async REPL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;CancelledError&lt;/tt&gt; now inherits directly from &lt;tt class="docutils literal"&gt;BaseException&lt;/tt&gt; instead of
&lt;tt class="docutils literal"&gt;Exception&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;coroutine()&lt;/tt&gt; is now deprecated and will be removed in Python 3.11&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Passing a &lt;tt class="docutils literal"&gt;loop&lt;/tt&gt; parameter is now deprecated for most of &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt;’s
high-level API; it will be removed entirely in Python 3.10&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Explicitly passing coroutines to &lt;tt class="docutils literal"&gt;wait()&lt;/tt&gt; is now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; module: New &lt;tt class="docutils literal"&gt;date&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; method:
&lt;tt class="docutils literal"&gt;fromisocalendar()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;functools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;cached_property()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;singledispatchmethod()&lt;/tt&gt;
added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;io&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;open_code()&lt;/tt&gt; (the verified open hook) added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;itertools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;accumulate()&lt;/tt&gt; now accepts an &lt;tt class="docutils literal"&gt;initial&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;json.tool&lt;/tt&gt; command-line interface: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--json-lines&lt;/span&gt;&lt;/tt&gt; option added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;math&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;comb()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;dist()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;hypot()&lt;/tt&gt; can now take multiple arguments&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;isqrt()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;perm()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;prod()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pathlib&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Path.link_to()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Path.rename()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;Path.replace()&lt;/tt&gt; now return the new path&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Path.unlink()&lt;/tt&gt; now accepts a &lt;tt class="docutils literal"&gt;missing_ok&lt;/tt&gt; argument&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pickle&lt;/tt&gt; module: Protocol 5 (with support for out-of-band buffers) added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;platform&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;dist()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;linux_distribution()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;shlex&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;join()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;statistics&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;NormalDist&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;fmean()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;geometric_mean()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;multimode()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;quantiles()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;subprocess&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;args&lt;/tt&gt; parameter to &lt;tt class="docutils literal"&gt;Popen&lt;/tt&gt; and the wrappers
around it can now be a path-like object or sequence of path-like objects on
Windows systems in addition to POSIX&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;audit()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;addaudithook()&lt;/tt&gt; (for audit hooks) added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pycache_prefix&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unraisablehook()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__unraisablehook__&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;typing&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;TypedDict&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Literal&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Final&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;final()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;Protocol&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;SupportsIndex&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;get_origin()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;get_args()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unicodedata&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Updated to Unicode 12.1.0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;is_normalized()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unittest.mock&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;AsyncMock&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;call&lt;/tt&gt; objects now have &lt;tt class="docutils literal"&gt;args&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;kwargs&lt;/tt&gt; properties&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;zipfile&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Path&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Removed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;macpath&lt;/tt&gt; module (deprecated since Python 3.7)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;time.clock()&lt;/tt&gt; (deprecated since Python 3.3)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;the &lt;tt class="docutils literal"&gt;pyvenv&lt;/tt&gt; script for creating venvs (Use &lt;tt class="docutils literal"&gt;pythonX.Y &lt;span class="pre"&gt;-m&lt;/span&gt; venv&lt;/tt&gt;
instead)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys.set_coroutine_wrapper()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;sys.get_coroutine_wrapper()&lt;/tt&gt;
(deprecated since Python 3.7)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Using &lt;tt class="docutils literal"&gt;is&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;is not&lt;/tt&gt; with strings, numbers, and certain other literals
now produces a &lt;tt class="docutils literal"&gt;SyntaxWarning&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-9-2020-10-05"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.9 (2020-10-05)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3/whatsnew/3.9.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;dict&lt;/tt&gt;s can now be merged &amp;amp; updated using the &lt;tt class="docutils literal"&gt;|&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;|=&lt;/tt&gt; operators&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Any valid expression can now be used as a decorator&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;str&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;bytearray&lt;/tt&gt; methods: &lt;tt class="docutils literal"&gt;removeprefix()&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;removesuffix()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Built-in collection types like &lt;tt class="docutils literal"&gt;list&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;dict&lt;/tt&gt; can now be used as
generic types; e.g., &lt;tt class="docutils literal"&gt;List[str]&lt;/tt&gt; can now be written &lt;tt class="docutils literal"&gt;list[str]&lt;/tt&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;This also applies to collections ABCs; e.g., &lt;tt class="docutils literal"&gt;typing.Sequence[str]&lt;/tt&gt; can
now be written &lt;tt class="docutils literal"&gt;collections.abc.Sequence[str]&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Importing the old &lt;tt class="docutils literal"&gt;List&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Sequence&lt;/tt&gt;, etc. types from &lt;tt class="docutils literal"&gt;typing&lt;/tt&gt; is now
deprecated but does not generate &lt;tt class="docutils literal"&gt;DeprecationWarnings&lt;/tt&gt;s at this time.
The deprecated names will be removed from &lt;tt class="docutils literal"&gt;typing&lt;/tt&gt; in the first Python
release five years after 3.9.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New modules: &lt;tt class="docutils literal"&gt;graphlib&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;zoneinfo&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;to_thread()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;functools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;cache()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;importlib.resources&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;files()&lt;/tt&gt; added (introduced in
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; v1.1.0)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Aligned &lt;tt class="docutils literal"&gt;importlib.metadata&lt;/tt&gt; with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-metadata&lt;/span&gt;&lt;/tt&gt; v1.6.1&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ipaddress&lt;/tt&gt; module now supports IPv6 scoped addresses&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;math&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;gcd()&lt;/tt&gt; can now take multiple arguments&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;lcm()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;nextafter()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;ulp()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pathlib&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Path.readlink()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;PurePath.is_relative_to()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;PurePath.with_stem()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;random&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;randbytes()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;typing&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Annotated&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;binhex&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;parser&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;symbol&lt;/tt&gt; modules are now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Using &lt;tt class="docutils literal"&gt;NotImplemented&lt;/tt&gt; in a boolean context is now deprecated and will
produce a &lt;tt class="docutils literal"&gt;TypeError&lt;/tt&gt; in a future version of Python&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Removed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;fractions.gcd()&lt;/tt&gt; (deprecated since Python 3.5)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;encoding&lt;/tt&gt; parameter of &lt;tt class="docutils literal"&gt;json.loads()&lt;/tt&gt; (deprecated &amp;amp; ignored since
Python 3.1)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio.Task.current_task()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;asyncio.Task.all_tasks()&lt;/tt&gt;
(deprecated since Python 3.7); use &lt;tt class="docutils literal"&gt;asyncio.current_task()&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;asyncio.all_tasks()&lt;/tt&gt; instead&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;with (await asyncio.lock):&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;with (yield from asyncio.lock):&lt;/tt&gt;
statements are no longer supported; use &lt;tt class="docutils literal"&gt;async with lock&lt;/tt&gt; instead.
Likewise for &lt;tt class="docutils literal"&gt;asyncio.Condition&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;asyncio.Semaphore&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;lib2to3&lt;/tt&gt; now emits a &lt;tt class="docutils literal"&gt;PendingDeprecationWarning&lt;/tt&gt; and will be removed in
Python 3.13&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unicodedata&lt;/tt&gt; updated to Unicode 13.0.0&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-10-2021-10-04"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.10 (2021-10-04)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3.10/whatsnew/3.10.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Pattern matching!&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Bad request&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Not allowed&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Something's wrong with the Internet&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Context managers in &lt;tt class="docutils literal"&gt;with&lt;/tt&gt; statements can now be enclosed in parentheses,
e.g.:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CtxManager1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;CtxManager2&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Assignment expressions can now be used unparenthesized within set literals,
set comprehensions, and sequence indexes (but not slices)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Numeric literals immediately followed by keywords (e.g., &lt;tt class="docutils literal"&gt;0in x&lt;/tt&gt;) now
generate a deprecation warning.  Future Python versions will change this to a
syntax warning and then a syntax error.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Common syntax errors now have better error messages&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;AttributeError&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;NameError&lt;/tt&gt; error messages now include suggestions
as to what you might have meant&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Union[X, Y]&lt;/tt&gt; can now be written &lt;tt class="docutils literal"&gt;X | Y&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Dictionary views returned by &lt;tt class="docutils literal"&gt;dict.keys()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;dict.values()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;dict.items()&lt;/tt&gt; now have &lt;tt class="docutils literal"&gt;mapping&lt;/tt&gt; attributes wrapping the original
&lt;tt class="docutils literal"&gt;dict&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The second argument of &lt;tt class="docutils literal"&gt;isinstance()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;issubclass()&lt;/tt&gt; can now be a
&lt;tt class="docutils literal"&gt;Union&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;int&lt;/tt&gt; method: &lt;tt class="docutils literal"&gt;bit_count()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;open()&lt;/tt&gt; and friends can now be passed &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;encoding=&amp;quot;locale&amp;quot;&lt;/span&gt;&lt;/tt&gt; in order to
explicitly use the current locale’s encoding&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;zip()&lt;/tt&gt; now has a &lt;tt class="docutils literal"&gt;strict&lt;/tt&gt; parameter for requiring that all input
iterables have the same length&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New builtin functions: &lt;tt class="docutils literal"&gt;aiter()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;anext()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;EncodingWarning&lt;/tt&gt; warning type added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;loop&lt;/tt&gt; parameter (deprecated in Python 3.8) is now removed from most of
&lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt;’s high-level API&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;base64&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;b32hexencode()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;b32hexdecode()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;bisect&lt;/tt&gt; module: The functions now accept a &lt;tt class="docutils literal"&gt;key&lt;/tt&gt; argument&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;codecs&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;unregister()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Collections ABCs can no longer be imported from &lt;tt class="docutils literal"&gt;collections&lt;/tt&gt;; import them
from &lt;tt class="docutils literal"&gt;collections.abc&lt;/tt&gt; instead&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;collections&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Counter.total()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;contextlib&lt;/tt&gt;: &lt;tt class="docutils literal"&gt;aclosing()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;dataclasses&lt;/tt&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;dataclass&lt;/tt&gt; decorator now accepts a &lt;tt class="docutils literal"&gt;slots&lt;/tt&gt; argument&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Fields can now be made keyword-only&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;distutils&lt;/tt&gt; is now deprecated and will be removed in Python 3.12&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;glob&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;glob()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;iglob()&lt;/tt&gt; now accept &lt;tt class="docutils literal"&gt;root_dir&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;dir_fd&lt;/tt&gt; arguments&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Aligned &lt;tt class="docutils literal"&gt;importlib.metadata&lt;/tt&gt; with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-metadata&lt;/span&gt;&lt;/tt&gt; v4.6&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;entry_points()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;package_distributions()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;inspect&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;get_annotations()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;io&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;text_encoding()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;itertools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;pairwise()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;os.path.realpath()&lt;/tt&gt; now has a &lt;tt class="docutils literal"&gt;strict&lt;/tt&gt; parameter for erroring when a
path doesn’t exist or a symlink loop is encountered&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pathlib&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Slice and negative indexing support added to &lt;tt class="docutils literal"&gt;Path.parents&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Path.hardlink_to()&lt;/tt&gt; added, superseding &lt;tt class="docutils literal"&gt;Path.link_to()&lt;/tt&gt;, which is now
deprecated and will be removed in Python 3.12&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Path.stat()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;Path.chmod()&lt;/tt&gt; now have a &lt;tt class="docutils literal"&gt;follow_symlinks&lt;/tt&gt;
argument&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;platform&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;freedesktop_os_release()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;statistics&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;covariance()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;correlation()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;linear_regression()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;orig_argv&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;stdlib_module_names&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;traceback&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;format_exception()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;format_exception_only()&lt;/tt&gt;,
and &lt;tt class="docutils literal"&gt;print_exception()&lt;/tt&gt; can now take just an exception argument as a
positional-only parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;types&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;EllipsisType&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;NoneType&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;NotImplementedType&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;typing&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Concatenate&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;ParamSpec&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;TypeAlias&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;TypeGuard&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;is_typeddict()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Removed the &lt;tt class="docutils literal"&gt;formatter&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;parser&lt;/tt&gt; modules (deprecated in Python 3.4
and 3.9, respectively)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-11-2022-10-03"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.11 (2022-10-03)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3.11/whatsnew/3.11.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Exception groups&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ExceptionGroup&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;BaseExceptionGroup&lt;/tt&gt; exception types added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;try: ... except* &lt;span class="pre"&gt;...:&lt;/span&gt; ...&lt;/tt&gt; syntax (note asterisk) for matching exception
groups&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Traceback messages now highlight the exact expression that caused the error&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Starred expressions can now be used in &lt;tt class="docutils literal"&gt;for&lt;/tt&gt; statements (e.g., &lt;tt class="docutils literal"&gt;for x in
*lst1, *lst2:&lt;/tt&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;This was enabled by the grammar rewrite in Python 3.9 but was not noticed
or documented until 3.11.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Octal escapes in string &amp;amp; bytes literals with values greater than 0o377
(e.g., &lt;tt class="docutils literal"&gt;\477&lt;/tt&gt;) now generate a &lt;tt class="docutils literal"&gt;DeprecationWarning&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The various “open” functions no longer accept the &lt;tt class="docutils literal"&gt;U&lt;/tt&gt; mode&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;object&lt;/tt&gt; method: &lt;tt class="docutils literal"&gt;__getstate__()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New &lt;tt class="docutils literal"&gt;BaseException&lt;/tt&gt; method: &lt;tt class="docutils literal"&gt;add_note()&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Chaining &lt;tt class="docutils literal"&gt;&amp;#64;classmethod&lt;/tt&gt; decorators and using them to wrap other decorators
(such as &lt;tt class="docutils literal"&gt;&amp;#64;property&lt;/tt&gt;) is now deprecated and will be removed in Python 3.13&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Format specification mini-language: A &lt;tt class="docutils literal"&gt;z&lt;/tt&gt; option can now be used with
floating-point types in order to coerce negative zero to “regular” zero after
rounding.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New modules: &lt;tt class="docutils literal"&gt;tomllib&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;wsgiref.types&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;&amp;#64;coroutine&lt;/tt&gt; (deprecated since 3.8) and
&lt;tt class="docutils literal"&gt;asyncio.coroutines.CoroWrapper&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Barrier&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Runner&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;TaskGroup&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;timeout()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;binascii&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;a2b_hqx()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;b2a_hqx()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;rlecode_hqx()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;rledecode_hqx()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;binhex&lt;/tt&gt; module removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;contextlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;chdir()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;UTC&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;fromisoformat()&lt;/tt&gt; methods now accept most ISO 8601 strings&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;enum&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;EnumCheck&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;FlagBoundary&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;ReprEnum&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;StrEnum&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;&amp;#64;global_enum()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;#64;member()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;#64;nonmember()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;#64;property&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;show_flag_values()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;&amp;#64;verify&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;EnumMeta&lt;/tt&gt; renamed to &lt;tt class="docutils literal"&gt;EnumType&lt;/tt&gt;; the old name is currently as an alias&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;functools&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;singledispatch&lt;/tt&gt; now supports union types&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;hashlib&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;file_digest()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;inspect&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;getmembers_static()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;ismethodwrapper()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;formatargspec()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;getargspec()&lt;/tt&gt; removed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Frame-related functions now return objects instead of tuples (though the
new objects are backwards-compatible with the tuple interface)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;locale&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;getdefaultlocale()&lt;/tt&gt; is now deprecated and will be removed in Python 3.13&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;getencoding()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;logging&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;getLevelNamesMapping()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;createSocket()&lt;/tt&gt; method added to &lt;tt class="docutils literal"&gt;logging.handlers.SysLogHandler&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;math&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;cbrt()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;exp2()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;operator&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;call()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pathlib&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;glob()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;rglob()&lt;/tt&gt; methods now return only
directories if given a pattern ending with the pathname separator&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;re&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;(?&amp;gt;...)&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;*+&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;++&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;?+&lt;/span&gt;&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;{m,n}+&lt;/tt&gt; can now be used in
regular expressions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;NOFLAG&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;string&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;get_identifiers()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;is_valid()&lt;/tt&gt; methods added to
&lt;tt class="docutils literal"&gt;string.Template&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;exception()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;typing&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;LiteralString&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Never&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Self&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;TypeVarTuple&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Unpack&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;assert_never()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;assert_type()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;clear_overloads()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;get_overloads()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;#64;dataclass_transform&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;reveal_type()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Text&lt;/tt&gt; is now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Individual fields in a &lt;tt class="docutils literal"&gt;TypedDict&lt;/tt&gt; may now be annotated as &lt;tt class="docutils literal"&gt;Required&lt;/tt&gt;
or &lt;tt class="docutils literal"&gt;NotRequired&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The keyword-argument syntax for constructing &lt;tt class="docutils literal"&gt;TypedDict&lt;/tt&gt; types is now
deprecated and will be removed in Python 3.13&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unicodedata&lt;/tt&gt; updated to Unicode 14.0.0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;zipfile&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;metadata_encoding&lt;/tt&gt; argument added to &lt;tt class="docutils literal"&gt;ZipFile&lt;/tt&gt; constructor&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ZipFile.mkdir()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;stem&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;suffix&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;suffixes&lt;/tt&gt; attributes added to &lt;tt class="docutils literal"&gt;zipfile.Path&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The following modules are now deprecated and are planned to be removed in
Python 3.13: &lt;tt class="docutils literal"&gt;aifc&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;audioop&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;cgi&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;cgitb&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;chunk&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;crypt&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;imghdr&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;mailcap&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;msilib&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;nis&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;nntplib&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;ossaudiodev&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;pipes&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;sndhdr&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;spwd&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;sunau&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;telnetlib&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;uu&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;xdrlib&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python-3-12-2023-10-02"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python 3.12 (2023-10-02)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Release notes: &lt;a class="reference external" href="https://docs.python.org/3.12/whatsnew/3.12.html"&gt;[link]&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;New syntax for type-annotating generic classes, generic functions, and type
aliases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Generic class:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Old syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;typing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;T_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;T_str&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;covariant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ClassA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T_str&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;method1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T_str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="c1"&gt;# No Generic or TypeVar&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ClassA&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;method1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Generic function:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Old syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;typing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;T&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="c1"&gt;# No TypeVar&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Type alias:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Old syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;typing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypeAlias&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;IntOrStr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TypeAlias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;IntOrStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Generic type alias:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Old syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;typing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypeAlias&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypeVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;T&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;ListOrSet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TypeAlias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="c1"&gt;# No TypeVar&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ListOrSet&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Variadic type alias:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Old syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;typing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypeAlias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TypeVarTuple&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;Ts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypeVarTuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Ts&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;IntEtc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TypeAlias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;IntEtc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Ts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Type alias with a parameter spec:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Old syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;collections.abc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;typing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ParamSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TypeAlias&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ParamSpec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;P&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;IntMaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TypeAlias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;New syntax:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;collections.abc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="n"&gt;IntMaker&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Types of individual fields in a &lt;tt class="docutils literal"&gt;**kwargs&lt;/tt&gt; function parameter can now be
annotated with &lt;tt class="docutils literal"&gt;typing.Unpack&lt;/tt&gt; applied to a &lt;tt class="docutils literal"&gt;TypedDict&lt;/tt&gt;, like so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;typing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Unpack&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Unpack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# kwargs[&amp;quot;name&amp;quot;] must be passed a `str`, and kwargs[&amp;quot;year&amp;quot;] must be&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# passed an `int`.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;{..}&lt;/span&gt;&lt;/tt&gt; placeholders inside f-strings may now contain any valid Python
expression&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Quotes from the enclosing string may now be reused:&lt;/p&gt;
&lt;pre class="code pycon literal-block"&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;songs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Take me back to Eden'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Alkaline'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Ascensionism'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;This is the playlist: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;, &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;songs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Expressions inside f-strings may now span multiple lines and contain inline
comments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Expressions inside f-strings may now contain backslashes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The buffer protocol is now accessible in Python code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Special methods &lt;tt class="docutils literal"&gt;__buffer__()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;__release_buffer__()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;collections.abc&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Buffer&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;inspect&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;BufferFlags&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Source code containing NUL bytes now results in a &lt;tt class="docutils literal"&gt;SyntaxError&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Invalid escape sequences now generate a &lt;tt class="docutils literal"&gt;SyntaxWarning&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Octal escapes in string &amp;amp; bytes literals with values greater than 0o377
(e.g., &lt;tt class="docutils literal"&gt;\477&lt;/tt&gt;) now generate a &lt;tt class="docutils literal"&gt;SyntaxWarning&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Applying &lt;tt class="docutils literal"&gt;~&lt;/tt&gt; (bitwise inversion) to a &lt;tt class="docutils literal"&gt;bool&lt;/tt&gt; is now deprecated and will
become an error in Python 3.14.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Removed modules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asynchat&lt;/tt&gt; (deprecated in Python 3.6)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncore&lt;/tt&gt; (deprecated in Python 3.6)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;distutils&lt;/tt&gt; (deprecated in Python 3.10)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;imp&lt;/tt&gt; (deprecated in Python 3.4)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;smtpd&lt;/tt&gt; (deprecated in Python 3.6)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;array&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;array&lt;/tt&gt; class is now subscriptable and thus properly
generic&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ast&lt;/tt&gt; module: Accessing or using any of &lt;tt class="docutils literal"&gt;Bytes&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Ellipsis&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;NameConstant&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Num&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;Str&lt;/tt&gt; now generates a
&lt;tt class="docutils literal"&gt;DeprecationWarning&lt;/tt&gt;.  They are planned to be removed in Python 3.14.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;as_completed()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;wait()&lt;/tt&gt; now accept generators yielding tasks&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;create_eager_task_factory()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;eager_task_factory()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;run()&lt;/tt&gt; now takes an optional &lt;tt class="docutils literal"&gt;loop_factory&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;calendar&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Day&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;Month&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;collections.abc&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;ByteString&lt;/tt&gt; is now deprecated and will be
removed in Python 3.14&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;configparser&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;ConfigParser.readfp()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;ParsingError.filename&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;SafeConfigParser&lt;/tt&gt; removed (deprecated in
Python 3.2)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;datetime.utcnow()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;datetime.utctimestamp()&lt;/tt&gt;
are now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;fraction&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;Fraction&lt;/tt&gt; instances now support float-style
formatting&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;importlib.abc&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;ResourceReader&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Traversable&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;TraversableResources&lt;/tt&gt; are now deprecated and will be removed in Python
3.14&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;importlib.resources&lt;/tt&gt;: &lt;tt class="docutils literal"&gt;as_file()&lt;/tt&gt; now supports resource directories&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;inspect&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;getasyncgenlocals()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;getasyncgenstate()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;markcoroutinefunction()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;itertools&lt;/tt&gt;: &lt;tt class="docutils literal"&gt;batched()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;locale&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;format()&lt;/tt&gt; removed (deprecated in Python 3.7)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;math&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;nextafter()&lt;/tt&gt; now takes an optional &lt;tt class="docutils literal"&gt;steps&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sumprod()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;os&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;DirEntry.is_junction()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;listdrives()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;listmounts()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;listvolumes()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;pidfd_open()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;setns()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;unshare()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Calling &lt;tt class="docutils literal"&gt;fork()&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;forkpty()&lt;/tt&gt; in a multithreaded program now
generates a &lt;tt class="docutils literal"&gt;DeprecationWarning&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;os.path&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;isjunction()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;splitroot()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pathlib&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Path classes can now be subclassed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;PurePath.with_segments()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Path.is_junction()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;Path.walk()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;PurePath.match()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Path.glob()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;Path.rglob()&lt;/tt&gt; now take an
optional &lt;tt class="docutils literal"&gt;case_sensitive&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;PurePath.relative_to()&lt;/tt&gt; now takes an optional &lt;tt class="docutils literal"&gt;walk_up&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;pkgutil&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;find_loader()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;get_loader()&lt;/tt&gt; are now deprecated
and will be removed in Python 3.14&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;random&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;binomialvariate()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;lambd&lt;/tt&gt; argument to &lt;tt class="docutils literal"&gt;expovariate()&lt;/tt&gt; now defaults to &lt;tt class="docutils literal"&gt;1.0&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;shutil&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;rmtree()&lt;/tt&gt; now takes an optional &lt;tt class="docutils literal"&gt;onexc&lt;/tt&gt; parameter.  The &lt;tt class="docutils literal"&gt;onerror&lt;/tt&gt;
parameter is deprecated and will be removed in Python 3.14.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unpack_archive()&lt;/tt&gt; now takes an optional &lt;tt class="docutils literal"&gt;filter&lt;/tt&gt; parameter for
limiting what gets extracted from tar archives&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sqlite3&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Command-line interface added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;connect()&lt;/tt&gt; now takes an optional &lt;tt class="docutils literal"&gt;autocommit&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Connection.autocommit&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;Connection.getconfig()&lt;/tt&gt;, and
&lt;tt class="docutils literal"&gt;Connection.setconfig()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The default adapters and converters are now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ssl&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;match_hostname()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;wrap_socket()&lt;/tt&gt; removed
(deprecated in Python 3.7)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;statistics&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;correlation()&lt;/tt&gt; now takes an optional &lt;tt class="docutils literal"&gt;method&lt;/tt&gt;
parameter that can be either &lt;tt class="docutils literal"&gt;&amp;quot;linear&amp;quot;&lt;/tt&gt; (the default) or &lt;tt class="docutils literal"&gt;&amp;quot;ranked&amp;quot;&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;activate_stack_trampoline()&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;deactivate_stack_trampoline()&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;is_stack_trampoline_active()&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;last_exc&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;last_type&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;last_value&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;last_traceback&lt;/tt&gt; are now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;sys.monitoring&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;tarfile&lt;/tt&gt; module: The &lt;tt class="docutils literal"&gt;TarFile.extract()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;TarFile.extractall()&lt;/tt&gt;
methods now take an optional &lt;tt class="docutils literal"&gt;filter&lt;/tt&gt; parameter for limiting what
gets extracted in order to avoid security issues.  Calling one of these
methods without setting a filter will generate a &lt;tt class="docutils literal"&gt;DeprecationWarning&lt;/tt&gt; until
Python 3.14, in which the default filter will become &lt;tt class="docutils literal"&gt;&amp;quot;data&amp;quot;&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;tempfile&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;NamedTemporaryFile&lt;/tt&gt; now takes an optional &lt;tt class="docutils literal"&gt;delete_on_close&lt;/tt&gt; parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;mkdtemp()&lt;/tt&gt; now always returns an absolute path&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;types&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;get_original_bases()&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;typing&lt;/tt&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;override&lt;/tt&gt; added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;dataclass_transform()&lt;/tt&gt; now takes an optional &lt;tt class="docutils literal"&gt;frozen_default&lt;/tt&gt;
parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;Hashable&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;Sized&lt;/tt&gt; are now deprecated&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unicodedata&lt;/tt&gt; updated to Unicode 15.0.0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;unittest&lt;/tt&gt; command-line interface: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--durations&lt;/span&gt;&lt;/tt&gt; option added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;uuid&lt;/tt&gt; module: Command-line interface added&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;venv&lt;/tt&gt; module: &lt;tt class="docutils literal"&gt;setuptools&lt;/tt&gt; is no longer automatically installed in
virtual environments&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Programming"></category><category term="Python"></category><category term="history"></category></entry><entry><title>Using Package Data in Python Projects with Setuptools</title><link href="https://jwodder.github.io/kbits/posts/pypkg-data/" rel="alternate"></link><published>2020-12-29T00:00:00-05:00</published><updated>2022-06-10T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2020-12-29:/kbits/posts/pypkg-data/</id><summary type="html">&lt;p class="first last"&gt;When creating a Python project, you may want to include a number of
non-Python files in the project that the code can then access at runtime,
such as templates, images, and data.  These files are called &lt;em&gt;package
data&lt;/em&gt;, and this article describes how to include them in &amp;amp; access them from
your project.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;When creating a Python project, you may want to include a number of non-Python
files in the project that the code can then access at runtime, such as
templates, images, and data.  These files are called &lt;em&gt;package data&lt;/em&gt; &lt;a class="footnote-reference" href="#f1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;, and
they are included in &amp;amp; accessed from your project as follows.&lt;/p&gt;
&lt;div class="contents topic" id="contents"&gt;
&lt;p class="topic-title"&gt;Contents&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#including-package-data-in-projects" id="toc-entry-1"&gt;Including Package Data in Projects&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#including-package-data-via-manifest-in" id="toc-entry-2"&gt;Including Package Data via &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#including-package-data-via-setup-py-setup-cfg" id="toc-entry-3"&gt;Including Package Data via &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#excluding-package-data-via-setup-py-setup-cfg" id="toc-entry-4"&gt;Excluding Package Data via &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#including-package-data-via-setuptools-plugins" id="toc-entry-5"&gt;Including Package Data via Setuptools Plugins&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#accessing-package-data-at-runtime" id="toc-entry-6"&gt;Accessing Package Data at Runtime&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#installing-importing-importlib-resources" id="toc-entry-7"&gt;Installing &amp;amp; Importing &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#the-importlib-resources-api" id="toc-entry-8"&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; API&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#footnotes" id="toc-entry-9"&gt;Footnotes&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="including-package-data-in-projects"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Including Package Data in Projects&lt;/a&gt;&lt;/h2&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;The following section only pertains to projects built with setuptools.
Users of flit, Poetry, and other tools must consult their respective
backend’s documentation to see how to include package data.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The first requirement for being able to include package data in your &lt;a class="reference external" href="https://docs.python.org/3/tutorial/modules.html#packages"&gt;package&lt;/a&gt;
&lt;a class="footnote-reference" href="#f2" id="footnote-reference-2"&gt;[2]&lt;/a&gt; is for the files to be located somewhere inside the actual package
directory.  If your project is a single-file &lt;tt class="docutils literal"&gt;.py&lt;/tt&gt; module, you must convert
it to a directory/package layout before you can store package data in it.&lt;/p&gt;
&lt;p&gt;Once your package data is inside the package, you must tell setuptools to
include the files in both the project’s wheel (so that the files will be
installed when your package is installed) and sdist (so that the files can be
included in the wheel when building from an sdist).  There are two different
major ways to do this: a blanket “include all” method that uses a
&lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; file and a fine-grained method that configures one package &amp;amp;
subpackage at time via the &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt; file.&lt;/p&gt;
&lt;div class="admonition important"&gt;
&lt;p class="first admonition-title"&gt;Important&lt;/p&gt;
&lt;p class="last"&gt;In addition to the configurations described here, you also need to ensure
that all folders within your package that contain package data (even if
they contain no Python source code) are listed in the &lt;tt class="docutils literal"&gt;packages&lt;/tt&gt; option
in &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;.  This can be done automatically by using the
&lt;tt class="docutils literal"&gt;setuptools.find_namespace_packages()&lt;/tt&gt; function instead of
&lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt;.  If you don’t do this, setuptools will emit a
warning message starting in version 62.3.0, and later versions will cease
to include such packages in your distribution at all.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="including-package-data-via-manifest-in"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Including Package Data via &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are two steps to this method:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Create or edit your project’s &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; file with the proper commands
to tell setuptools to include all of your package data file in the project’s
sdists.  See &lt;a class="reference external" href="https://packaging.python.org/guides/using-manifest-in/"&gt;the Python Packaging User Guide&lt;/a&gt; for information on how to
do this.&lt;/p&gt;
&lt;p&gt;In the simplest case — in which you want all non-Python files in your
package to be treated as package data — you can simply include your entire
package in your sdist with the &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; command “&lt;tt class="docutils literal"&gt;graft
packagename&lt;/tt&gt;” (or “&lt;tt class="docutils literal"&gt;graft src&lt;/tt&gt;” if you’re using a &lt;a class="reference external" href="https://hynek.me/articles/testing-packaging/"&gt;&lt;tt class="docutils literal"&gt;src/&lt;/tt&gt; layout&lt;/a&gt;).  If
you use this command, you should also follow it with “&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;global-exclude&lt;/span&gt;
*.py[cod]&lt;/tt&gt;” so that compiled Python bytecode files are not included in the
sdist.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;In your &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;, pass &lt;tt class="docutils literal"&gt;include_package_data=True&lt;/tt&gt; to the &lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt;
function.   If you are placing your project configuration in &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;
instead, set &lt;tt class="docutils literal"&gt;include_package_data = True&lt;/tt&gt; in the &lt;tt class="docutils literal"&gt;[options]&lt;/tt&gt; section of
&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Doing this tells setuptools that any non-Python files found inside your
package that are included in the sdist should also be included in the wheel.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="including-package-data-via-setup-py-setup-cfg"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Including Package Data via &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This method allows you to specify package data file patterns on a per-package
basis through the &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; argument to &lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt;.  &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt;
must be a &lt;tt class="docutils literal"&gt;dict&lt;/tt&gt; mapping package or subpackage names (or the empty string, to
specify all packages &amp;amp; subpackages) to lists of glob patterns indicating which
files within those packages to include in the sdist and wheel.&lt;/p&gt;
&lt;p&gt;A sample &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; looks like this:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;package_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# If any package or subpackage contains *.txt or *.rst files, include&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# them:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;*.rst&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# Include any *.msg files found in the &amp;quot;hello&amp;quot; package (but not in its&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# subpackages):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.msg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# Include any *.csv files found in the &amp;quot;hello.utils&amp;quot; package:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;hello.utils&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.csv&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# Include any *.dat files found in the &amp;quot;data&amp;quot; subdirectory of the&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# &amp;quot;mypkg&amp;quot; package:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;mypkg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data/*.dat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you are placing your project configuration in &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;, you must
instead specify &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; via an &lt;tt class="docutils literal"&gt;[options.package_data]&lt;/tt&gt; section in
which the keys are the package &amp;amp; subpackage names — using &lt;tt class="docutils literal"&gt;*&lt;/tt&gt; instead of the
empty string to signify all packages — and the values are comma-separated glob
patterns.  The above &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt; sample translates to &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt; as
follows:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[options.package_data]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# If any package or subpackage contains *.txt or *.rst files, include them:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;*.txt, *.rst&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# Include any *.msg files found in the &amp;quot;hello&amp;quot; package (but not in its&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# subpackages):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;*.msg&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# Include any *.csv files found in the &amp;quot;hello.utils&amp;quot; package:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;hello.utils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;*.csv&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# Include any *.dat files found in the &amp;quot;data&amp;quot; subdirectory of the &amp;quot;mypkg&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# package:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;mypkg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;data/*.dat&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note that glob patterns only select files located directly within the given
package (or in the given subdirectory of the package, if the pattern includes a
directory path); e.g., &lt;tt class="docutils literal"&gt;&amp;quot;hello&amp;quot;: &lt;span class="pre"&gt;[&amp;quot;*.msg&amp;quot;]&lt;/span&gt;&lt;/tt&gt; selects &lt;tt class="docutils literal"&gt;*.msg&lt;/tt&gt; files in the
&lt;tt class="docutils literal"&gt;hello&lt;/tt&gt; package but not in any of its subpackages.  To select files in
subpackages, you must either include an entry for each subpackage or else use
the empty string key (or asterisk key in &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;) to specify a pattern
for all packages &amp;amp; subpackages.&lt;/p&gt;
&lt;p&gt;If a pattern contains any directory components, the forward slash (&lt;tt class="docutils literal"&gt;/&lt;/tt&gt;) must
be used as the directory separator, even on Windows.&lt;/p&gt;
&lt;p&gt;If a package data file is located in a directory that does not have an
&lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt; file (say, a &lt;tt class="docutils literal"&gt;data/&lt;/tt&gt; directory inside
&lt;tt class="docutils literal"&gt;package.subpackage&lt;/tt&gt;), that directory does not count as a package, and the
file must be listed in &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; in the form &lt;tt class="docutils literal"&gt;&amp;quot;package.subpackage&amp;quot;:
[&amp;quot;data/PATTERN&amp;quot;]&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="first admonition-title"&gt;Warning&lt;/p&gt;
&lt;p class="last"&gt;If you use both &lt;tt class="docutils literal"&gt;include_package_data&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt;, files
specified with &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; will not be automatically included in
sdists; you must instead list them in your &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="excluding-package-data-via-setup-py-setup-cfg"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Excluding Package Data via &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;exclude_package_data&lt;/tt&gt; argument to &lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt; can be used in conjunction
with either of the above methods to prevent one or more files from being
treated as package data.  &lt;tt class="docutils literal"&gt;exclude_package_data&lt;/tt&gt; takes a &lt;tt class="docutils literal"&gt;dict&lt;/tt&gt; with the
same structure as &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt;, and any matched files are excluded from
wheels.  Matched files are also excluded from sdists if they are not already
matched by the project’s &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;In a &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;exclude_package_data&lt;/tt&gt; becomes an
&lt;tt class="docutils literal"&gt;[options.exclude_package_data]&lt;/tt&gt; section whose contents have the same
structure as &lt;tt class="docutils literal"&gt;[options.package_data]&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="including-package-data-via-setuptools-plugins"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Including Package Data via Setuptools Plugins&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As an alternative to the above methods, you can use a plugin for setuptools
that automatically recognizes &amp;amp; includes package data in sdists &amp;amp; wheels,
usually based on what files in the project directory are under version control.
One example of such a plugin is &lt;a class="reference external" href="https://github.com/pypa/setuptools_scm"&gt;setuptools_scm&lt;/a&gt;, which automatically finds all
files under version control in a Git or Mercurial repository and augments the
project’s &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; (if any) with the found files.  This eliminates the
need to write a &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; manually (unless there are files under version
control that you want to exclude from sdists or wheels), though you still need
to set &lt;tt class="docutils literal"&gt;include_package_data&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;True&lt;/tt&gt; for files in your package directory
to be included in wheels.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="accessing-package-data-at-runtime"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Accessing Package Data at Runtime&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There have been multiple ways to access package data over the years, from
&lt;a class="reference external" href="https://setuptools.readthedocs.io/en/latest/pkg_resources.html#resourcemanager-api"&gt;&lt;tt class="docutils literal"&gt;pkg_resources&lt;/tt&gt;’ &lt;tt class="docutils literal"&gt;ResourceManager&lt;/tt&gt; API&lt;/a&gt; to &lt;a class="reference external" href="https://docs.python.org/3/library/pkgutil.html#pkgutil.get_data"&gt;&lt;tt class="docutils literal"&gt;pkgutil.get_data()&lt;/tt&gt;&lt;/a&gt;, but the most
recent and currently-recommended way is with the &lt;a class="reference external" href="http://importlib-resources.readthedocs.io"&gt;importlib-resources&lt;/a&gt;
package.&lt;/p&gt;
&lt;div class="section" id="installing-importing-importlib-resources"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Installing &amp;amp; Importing &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are two versions of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://pypi.org/project/importlib-resources/"&gt;The one on PyPI&lt;/a&gt; that is installed with &lt;tt class="docutils literal"&gt;pip install
&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; and imported with &lt;tt class="docutils literal"&gt;import importlib_resources&lt;/tt&gt; (note
underscore)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://docs.python.org/3/library/importlib.html#module-importlib.resources"&gt;The one in the Python standard library&lt;/a&gt; starting with Python 3.7 that is
imported with &lt;tt class="docutils literal"&gt;import importlib.resources&lt;/tt&gt; (note period)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Development of the PyPI version tends to be ahead of whatever’s in the latest
Python version.  In particular, the new &lt;tt class="docutils literal"&gt;files()&lt;/tt&gt;-based API described here
was only introduced in version 1.1.0 of the PyPI project and was only added to
the Python standard library in Python 3.9.  In order to be guaranteed a version
of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; that supports this API, you should add the following
to your project’s &lt;tt class="docutils literal"&gt;install_requires&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
importlib-resources&amp;gt;=1.1.0; python_version &amp;lt; '3.9'
&lt;/pre&gt;
&lt;p&gt;and import &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; in your code as follows:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version_info&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# importlib.resources either doesn't exist or lacks the files()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# function, so use the PyPI version:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;importlib_resources&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# importlib.resources has files(), so use that:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;importlib.resources&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;importlib_resources&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="the-importlib-resources-api"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; API&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To access a package data file in your project, start by calling
&lt;tt class="docutils literal"&gt;importlib_resources.files()&lt;/tt&gt; on the name of your package:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;pkg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;importlib_resources&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;packagename&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# The argument can optionally refer to a subpackage in the form&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# &amp;quot;packagename.subpackage&amp;quot;.&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This gives you a &lt;a class="reference external" href="https://github.com/python/importlib_resources/blob/eb0554035b499e4a5349dcc56a2bda51835f4fde/importlib_resources/abc.py#L61"&gt;Traversable&lt;/a&gt; object that acts like a limited &lt;tt class="docutils literal"&gt;pathlib.Path&lt;/tt&gt;
object for traversing package data files.  To refer to a &lt;tt class="docutils literal"&gt;data.csv&lt;/tt&gt; file in a
&lt;tt class="docutils literal"&gt;data/&lt;/tt&gt; directory in your package, write:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;pkg_data_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;data&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;data.csv&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;So now that we’ve got a reference to the package data file, how do we get
anything out of it?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;To open the file for reading, call the &lt;tt class="docutils literal"&gt;open()&lt;/tt&gt; method:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pkg_data_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# Do things with fp&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;To get the file’s contents as &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt;, call the &lt;tt class="docutils literal"&gt;read_bytes()&lt;/tt&gt; method:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pkg_data_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_bytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;To get the file’s contents as a &lt;tt class="docutils literal"&gt;str&lt;/tt&gt;, call the &lt;tt class="docutils literal"&gt;read_text()&lt;/tt&gt; method,
optionally with an &lt;tt class="docutils literal"&gt;encoding&lt;/tt&gt; argument:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pkg_data_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;To get the path to the file, call &lt;tt class="docutils literal"&gt;importlib_resources.as_file()&lt;/tt&gt; on it and
use the return value as a context manager:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;importlib_resources&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkg_data_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# Do things with the pathlib.Path object that is `path`&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The use of context managers allows &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; to support
packages stored in zipfiles; when a path is requested for a package data file
in a zipfile, the library can extract the file to a temporary location at the
start of the &lt;tt class="docutils literal"&gt;with&lt;/tt&gt; block and remove it at the end of the block.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;To iterate through a directory (either a package or a non-package directory),
use the &lt;tt class="docutils literal"&gt;iterdir()&lt;/tt&gt; method.  You can test whether a resource is a directory
or a file with the &lt;tt class="docutils literal"&gt;is_dir()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;is_file()&lt;/tt&gt; methods, and you can get a
resource’s basename via the &lt;tt class="docutils literal"&gt;name&lt;/tt&gt; property:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkg&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;data&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iterdir&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_dir&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;DIR&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;FILE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="footnotes"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Footnotes&lt;/a&gt;&lt;/h2&gt;
&lt;table class="docutils footnote" frame="void" id="f1" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Specifically, package data files are files that are stored in a Python
project’s package directory next to the Python source files.  An
alternative to package data is &lt;em&gt;data files&lt;/em&gt;, which are files installed
elsewhere on the file system.  This article only deals with the
former.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="f2" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Throughout this article, the term “package” is used in the sense of a
directory of &lt;tt class="docutils literal"&gt;.py&lt;/tt&gt; files and other packages (a.k.a. an “&lt;a class="reference external" href="https://packaging.python.org/glossary/#term-Import-Package"&gt;import
package&lt;/a&gt;”), not in the sense of a “&lt;a class="reference external" href="https://packaging.python.org/glossary/#term-Distribution-Package"&gt;distribution package&lt;/a&gt;” (i.e., an
sdist or wheel).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</content><category term="Programming"></category><category term="Python"></category><category term="Python packaging"></category><category term="setuptools"></category></entry><entry><title>Common Python Packaging Mistakes</title><link href="https://jwodder.github.io/kbits/posts/pypkg-mistakes/" rel="alternate"></link><published>2020-08-22T00:00:00-04:00</published><updated>2021-03-22T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2020-08-22:/kbits/posts/pypkg-mistakes/</id><summary type="html">&lt;p class="first last"&gt;An overview of common mistakes made in creating &amp;amp; building a Python package
and how to avoid them&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I think we can all agree that packaging a Python project is harder than it
should be.  With numerous guides &amp;amp; tutorials out there, people still make
mistakes.  Some of these mistakes break a project, some just make it less
attractive, and some even cause a project to step on the toes of other
projects.&lt;/p&gt;
&lt;p&gt;As the admin of the wheel-analysis and -browsing site &lt;a class="reference external" href="https://www.wheelodex.org"&gt;Wheelodex&lt;/a&gt;, I see a
number of poorly-built wheels each morning as I peruse the day’s new entries.
This eventually motivated me to create &lt;a class="reference external" href="https://github.com/jwodder/check-wheel-contents"&gt;check-wheel-contents&lt;/a&gt; — a program for
scanning a wheel for many of the below problems plus several others — in an
attempt to get people to clean up their wheels, yet still the poorly-packaged
projects persist.&lt;/p&gt;
&lt;p&gt;In yet another attempt to get people to fix their broken packages, here now are
some of the more frequent types of mistakes I see — along with advice on how to
avoid &amp;amp; correct them — in no particular order.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;Unless otherwise specified, references to packaging configurations assume
that the project is using setuptools and that configuration is being placed
in &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt; instead of &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;.  Consult the appropriate
documentation if your project is structured differently.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="contents topic" id="contents"&gt;
&lt;p class="topic-title"&gt;Contents&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#avoiding-general-mistakes" id="toc-entry-1"&gt;Avoiding General Mistakes&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#look-at-your-built-distributions" id="toc-entry-2"&gt;Look at Your Built Distributions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#installations-are-not-namespaced" id="toc-entry-3"&gt;Installations are Not Namespaced&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#top-level-tests-directory-in-wheel" id="toc-entry-4"&gt;Top-Level &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; Directory in Wheel&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#top-level-readme-or-license-file-in-wheel" id="toc-entry-5"&gt;Top-Level &lt;tt class="docutils literal"&gt;README&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;LICENSE&lt;/tt&gt; File in Wheel&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#project-description-doesn-t-render" id="toc-entry-6"&gt;Project Description Doesn’t Render&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#project-description-not-included" id="toc-entry-7"&gt;Project Description Not Included&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#python-package-not-included-in-wheel" id="toc-entry-8"&gt;Python Package Not Included in Wheel&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#subpackages-not-included-in-wheel" id="toc-entry-9"&gt;Subpackages Not Included in Wheel&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#package-data-not-included-in-wheel" id="toc-entry-10"&gt;Package Data Not Included in Wheel&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#pyc-files-included-in-wheel" id="toc-entry-11"&gt;&lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt; Files Included in Wheel&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#rebuilding-wheels-without-deleting-build" id="toc-entry-12"&gt;Rebuilding Wheels without Deleting &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#pinning-project-requirements-to-exact-versions" id="toc-entry-13"&gt;Pinning Project Requirements to Exact Versions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#conclusion" id="toc-entry-14"&gt;Conclusion&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#footnotes" id="toc-entry-15"&gt;Footnotes&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="avoiding-general-mistakes"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Avoiding General Mistakes&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, some general advice that will help you avoid (or at least detect) the
vast majority of packaging errors.&lt;/p&gt;
&lt;div class="section" id="look-at-your-built-distributions"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Look at Your Built Distributions&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Before you upload your sdist and wheel (especially if it’s your first release
for the project in question), actually take a look at what files are inside and
make sure that everything you want to include is in there.  An sdist is either
a tarball (&lt;tt class="docutils literal"&gt;*.tar.gz&lt;/tt&gt;) or a zipfile (&lt;tt class="docutils literal"&gt;*.zip&lt;/tt&gt;), so its contents can be
listed with one of these two commands:&lt;/p&gt;
&lt;pre class="code shell literal-block"&gt;
&lt;span class="c1"&gt;# Tarball
&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;tar&lt;span class="w"&gt; &lt;/span&gt;ztf&lt;span class="w"&gt; &lt;/span&gt;projectname-version.tar.gz&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# Zipfile
&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;zipinfo&lt;span class="w"&gt; &lt;/span&gt;projectname-version.zip
&lt;/pre&gt;
&lt;p&gt;At time of writing, the exact layout of an sdist has yet to be standardized,
but if you’re building with a recent version of setuptools, the contents are
structured as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Everything in the sdist is inside a top-level directory named
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;{projectname}-{version}/&lt;/span&gt;&lt;/tt&gt;.  This directory contains a copy of your package
code, the project’s &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;pyproject.toml&lt;/tt&gt; file, and various other
files from your project directory; see &lt;a class="reference external" href="https://packaging.python.org/guides/using-manifest-in/"&gt;here&lt;/a&gt; for more
information on what gets included by default.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;There exists a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PKG-INFO&lt;/span&gt;&lt;/tt&gt; file containing the project metadata.  For
historical reasons, this does not include project dependencies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Next to your Python package, there is a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;{projectname}.egg-info/&lt;/span&gt;&lt;/tt&gt; directory
containing more metadata, including a copy of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PKG-INFO&lt;/span&gt;&lt;/tt&gt;, a &lt;tt class="docutils literal"&gt;SOURCES.txt&lt;/tt&gt;
file listing the files in the sdist, and a &lt;tt class="docutils literal"&gt;requires.txt&lt;/tt&gt; file listing your
project’s dependencies.  Other files may be present depending on what
features your project uses.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your sdist is missing some files from your project directory or contains
some files that you don’t want in there, then (assuming you’re building your
project with setuptools), you can adjust what gets included via &lt;a class="reference external" href="https://packaging.python.org/guides/using-manifest-in/"&gt;a &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; file&lt;/a&gt; and rebuild.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;Exactly what files should and should not be included in an sdist is, for
the most part, largely a matter of opinion, but your sdist needs to include
your Python code and anything from your project directory that’s needed to
built a complete wheel.  The files that setuptools includes by default
should generally be left in there, and most people will recommend also
including tests and documentation.  Things that should generally be left
out include &lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt; files, repository metadata like &lt;tt class="docutils literal"&gt;.gitignore&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;.hgtags&lt;/tt&gt;, and (except in special circumstances) anything that you
wouldn’t commit to version control.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Wheels (&lt;tt class="docutils literal"&gt;*.whl&lt;/tt&gt;), meanwhile, are just zipfiles with a funny extension, so you
can list their contents with &lt;tt class="docutils literal"&gt;zipinfo&lt;/tt&gt;.  The basic layout of a wheel is as
follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Your Python package is located at the root of the wheel, rather than inside
a directory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;There exists a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;{projectname}-{version}.dist-info/&lt;/span&gt;&lt;/tt&gt; directory containing
metadata: a &lt;tt class="docutils literal"&gt;METADATA&lt;/tt&gt; file describing the project (similar to an sdist’s
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PKG-INFO&lt;/span&gt;&lt;/tt&gt;, but including dependencies), a &lt;tt class="docutils literal"&gt;WHEEL&lt;/tt&gt; file describing the
wheel version and tags, and a &lt;tt class="docutils literal"&gt;RECORD&lt;/tt&gt; file listing the files in the wheel
and their hashes.  Licenses included in the wheel with the &lt;tt class="docutils literal"&gt;license_files&lt;/tt&gt;
setting also end up in this directory.  Other files may also be present
depending on what features your project uses and the versions of setuptools
and wheel used to build the wheel.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If your project includes any files that are installed outside of
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;site-packages&lt;/span&gt;&lt;/tt&gt; — headers, scripts, data files (not to be confused with
package data), etc. — they are stored in a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;{projectname}-{version}.data/&lt;/span&gt;&lt;/tt&gt;
directory.  Files in this directory are organized into subdirectories named
after the distutils scheme keys (&lt;tt class="docutils literal"&gt;purelib&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;platlib&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;headers&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;scripts&lt;/tt&gt;, or &lt;tt class="docutils literal"&gt;data&lt;/tt&gt;) that map to the files’ install locations.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;Aside from the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;*.dist-info/&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;*.data/&lt;/tt&gt; directories, a wheel should
only contain Python packages &amp;amp; modules, consisting of code and data files.
Files like your project’s &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;pyproject.toml&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;,
etc. do not belong in a wheel.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Controlling what gets included in a wheel is more involved than for an sdist
(when using setuptools, at least); consult documentation elsewhere on how to do
this.&lt;/p&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="first admonition-title"&gt;Warning&lt;/p&gt;
&lt;p class="last"&gt;Do NOT try to fix your sdists or wheels by manually adding, removing, or
editing the files inside, as this is likely to make the sdist/wheel
invalid.  Instead, change your project configuration and create new built
distributions until you get what you want — &lt;a class="reference internal" href="#rebuild-noclean"&gt;and be sure to delete the &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt; directory in
between builds!&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="installations-are-not-namespaced"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Installations are Not Namespaced&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A key thing to understand about how Python packages are installed is that
(almost) all of the files in a wheel are simply placed directly in
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;site-packages/&lt;/span&gt;&lt;/tt&gt;; the only subdirectories present will be the directories
that are already in the wheel.  This means that, if your wheel has a &lt;tt class="docutils literal"&gt;foo/&lt;/tt&gt;
directory at the top level containing &lt;tt class="docutils literal"&gt;bar.py&lt;/tt&gt;, then &lt;tt class="docutils literal"&gt;bar.py&lt;/tt&gt; will be
installed to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;site-packages/foo/bar.py&lt;/span&gt;&lt;/tt&gt;; nothing is added to the path to
separate it from other packages’ &lt;tt class="docutils literal"&gt;foo/bar.py&lt;/tt&gt; files.  Properly namespacing
your files must be done by putting everything under a directory (normally your
top-level Python package) with a name the same as or similar to the name of
your project — which is the standard practice anyway.  Where problems arise is
when a top-level file or directory in a wheel has a name that other projects
are also likely to use, in which case files end up overwritten with the wrong
content and bugs result.&lt;/p&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://github.com/pypa/pip/issues/4625"&gt;pip issue #4625&lt;/a&gt; for pip’s
attempts at handling file collisions whenever they arise.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="top-level-tests-directory-in-wheel"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Top-Level &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; Directory in Wheel&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first (and probably most common) Python packaging mistake occurs when you
put your tests in a &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; directory at the root of your project (outside
of your Python package) and then include this directory in your project’s
wheels.  The &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; directory then ends up placed at the top-level of your
wheel’s filesystem, and, &lt;a class="reference internal" href="#installations-are-not-namespaced"&gt;as stated above&lt;/a&gt;, this means that it will be installed at
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;site-packages/tests/&lt;/span&gt;&lt;/tt&gt;.  The problem comes from the fact that “&lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt;” is
a name that &lt;em&gt;everybody&lt;/em&gt; uses for their tests and too many other projects also
include a top-level &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; directory in their wheels.  As a result,
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;site-packages/tests/&lt;/span&gt;&lt;/tt&gt; becomes a mish-mash of code from different packages,
some files even overwriting each other, and if someone tries to run those
tests, chaos will ensue.  (And if you don’t expect people to be running your
tests from your installed project, why are you including tests in the wheel in
the first place?)&lt;/p&gt;
&lt;p&gt;The most common reason why &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; ends up included in wheels is because the
project’s author used &lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt; in their &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt; but didn’t use
the function’s &lt;tt class="docutils literal"&gt;exclude&lt;/tt&gt; argument.  &lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt; works by searching
for directories in the project root (or in the directory passed as the
&lt;tt class="docutils literal"&gt;where&lt;/tt&gt; argument) that contain an &lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt; file, and then it searches
those directories for any subdirectories that also contain an &lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt;
file, and so on until it runs out of directories with &lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt; files.
Sometimes, people put an &lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt; file in &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; (Whether this is
necessary depends on the test framework being used), and so &lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt;
with the default arguments picks it up and adds it to the project’s list of
packages, resulting in it being included in the wheel.&lt;/p&gt;
&lt;p&gt;To avoid this, you have five options:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Remove the &lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt; files from your &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; directory and its
subdirectories.  Whether this is doable depends on your test framework.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Use &lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt;’s &lt;tt class="docutils literal"&gt;exclude&lt;/tt&gt; argument to exclude &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; and its
subdirectories like so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;find_packages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exclude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tests&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;tests.*&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note that we list both &lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;tests&amp;quot;&lt;/span&gt;&lt;/code&gt; and &lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;tests.*&amp;quot;&lt;/span&gt;&lt;/code&gt;.  Listing just
&lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;tests&amp;quot;&lt;/span&gt;&lt;/code&gt; would exclude &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; but not its subdirectories, so we
need to also list &lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;tests.*&amp;quot;&lt;/span&gt;&lt;/code&gt; in order to exclude everything.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Use &lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt;’s &lt;tt class="docutils literal"&gt;include&lt;/tt&gt; argument to include only your Python
package and its subpackages like so:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;find_packages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;packagename&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;packagename.*&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;As with &lt;tt class="docutils literal"&gt;exclude&lt;/tt&gt;, we list both the package name and the package name
followed by “&lt;tt class="docutils literal"&gt;.*&lt;/tt&gt;” so that all subpackages of the package will be matched
&amp;amp; included.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Move your &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; directory inside your Python package directory so it’s
no longer at the top level.&lt;/p&gt;
&lt;/li&gt;
&lt;li id="src"&gt;&lt;p class="first"&gt;Switch your project to a &lt;tt class="docutils literal"&gt;src/&lt;/tt&gt; layout, where your Python package
directory is located inside a directory named &lt;tt class="docutils literal"&gt;src/&lt;/tt&gt; and everything else —
including &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; — is outside of &lt;tt class="docutils literal"&gt;src/&lt;/tt&gt;.  With this layout, simply
write your &lt;tt class="docutils literal"&gt;packages&lt;/tt&gt; line as &lt;code class="py python"&gt;&lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;find_packages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;src&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/code&gt;, and
&lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt; will only look at what’s in &lt;tt class="docutils literal"&gt;src/&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Note that you will also need to add &lt;code class="py python"&gt;&lt;span class="n"&gt;package_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;src&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt; to your
&lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt; arguments in order for setuptools to grok your layout.  More
information about the &lt;tt class="docutils literal"&gt;src/&lt;/tt&gt; layout can be found &lt;a class="reference external" href="https://blog.ionelmc.ro/2014/05/25/python-packaging/#the-structure"&gt;here&lt;/a&gt; and &lt;a class="reference external" href="https://hynek.me/articles/testing-packaging/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The second most common reason why &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; ends up in wheels is that the
project author used the &lt;tt class="docutils literal"&gt;exclude&lt;/tt&gt; argument to &lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt; but listed
only &lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;tests&amp;quot;&lt;/span&gt;&lt;/code&gt; and not &lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;tests.*&amp;quot;&lt;/span&gt;&lt;/code&gt;, and so the subdirectories of
&lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; (inside an otherwise-empty &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; directory) ended up in the
wheel.  Both &lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;tests&amp;quot;&lt;/span&gt;&lt;/code&gt; and &lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;tests.*&amp;quot;&lt;/span&gt;&lt;/code&gt; need to be included in the
&lt;tt class="docutils literal"&gt;exclude&lt;/tt&gt; list in order to exclude the entire &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt; hierarchy.&lt;/p&gt;
&lt;p&gt;Besides &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt;, it is also a problem to include a top-level directory named
&lt;tt class="docutils literal"&gt;test/&lt;/tt&gt; (singular), &lt;tt class="docutils literal"&gt;docs/&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;examples/&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;data/&lt;/tt&gt;, or similar, as such
directories are also often included in wheels despite the clashes that will
result.&lt;/p&gt;
&lt;p&gt;Do note that, when it comes to sdists, it’s perfectly fine to have a &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt;
etc. directory at the base of your project, as sdists themselves are not
installed, they’re just used to build wheels, which are what actually get
installed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="top-level-readme-or-license-file-in-wheel"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Top-Level &lt;tt class="docutils literal"&gt;README&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;LICENSE&lt;/tt&gt; File in Wheel&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Similarly to the above mistake involving &lt;tt class="docutils literal"&gt;tests/&lt;/tt&gt;, it is also a bad idea to
include your project’s &lt;tt class="docutils literal"&gt;README.rst&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;README.md&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;LICENSE&lt;/tt&gt; file (or
&lt;tt class="docutils literal"&gt;CHANGELOG&lt;/tt&gt; or really anything that’s not a Python module or &lt;tt class="docutils literal"&gt;*.pth&lt;/tt&gt; file)
at the root of your wheel, as it will collide with the &lt;tt class="docutils literal"&gt;README&lt;/tt&gt;s and
&lt;tt class="docutils literal"&gt;LICENSE&lt;/tt&gt;s of other projects that do the same thing.&lt;/p&gt;
&lt;p&gt;This mistake is particularly common among projects built using &lt;a class="reference external" href="https://python-poetry.org"&gt;Poetry&lt;/a&gt;, where simple usage of the &lt;tt class="docutils literal"&gt;include&lt;/tt&gt; option
adds files directly into both the sdist and wheel.  To include a file in only
the sdist, one needs to change the &lt;tt class="docutils literal"&gt;include&lt;/tt&gt; option from this form:&lt;/p&gt;
&lt;pre class="code toml literal-block"&gt;
&lt;span class="k"&gt;[tool.poetry]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;CHANGELOG.md&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;to this form:&lt;/p&gt;
&lt;pre class="code toml literal-block"&gt;
&lt;span class="k"&gt;[tool.poetry]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;CHANGELOG.md&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sdist&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you do want to include your &lt;tt class="docutils literal"&gt;README&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;LICENSE&lt;/tt&gt; in your wheel, the
correct way is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;For &lt;tt class="docutils literal"&gt;README&lt;/tt&gt;, the file’s contents should already be used as the project’s
(long) description, in which case the contents are already included in the
project metadata, which is stored in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PKG-INFO&lt;/span&gt;&lt;/tt&gt; (for sdists) or
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;*.dist-info/METADATA&lt;/span&gt;&lt;/tt&gt; (for wheels), and thus there is no need to include
the &lt;tt class="docutils literal"&gt;README&lt;/tt&gt; as a separate file.  If you need to be able to retrieve the
&lt;tt class="docutils literal"&gt;README&lt;/tt&gt;’s contents at runtime, this can be done by using
&lt;a class="reference external" href="https://docs.python.org/3/library/importlib.metadata.html"&gt;&lt;tt class="docutils literal"&gt;importlib.metadata&lt;/tt&gt;&lt;/a&gt; or similar to fetch the project’s description.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Licenses and related files belong inside a wheel’s &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;*.dist-info&lt;/span&gt;&lt;/tt&gt; directory.
If using setuptools with wheel 0.32 or higher, licenses can be placed there
by passing them to the &lt;tt class="docutils literal"&gt;[metadata]license_files&lt;/tt&gt; option in &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;;
&lt;a class="reference external" href="https://wheel.readthedocs.io/en/stable/user_guide.html#including-license-files-in-the-generated-wheel-file"&gt;see the wheel documentation for more information&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At time of writing, Poetry does not support adding license files to a wheel’s
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;*.dist-info&lt;/span&gt;&lt;/tt&gt; directory, but &lt;a class="reference external" href="https://github.com/python-poetry/poetry/pull/1367"&gt;PR #1367&lt;/a&gt; would change that.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="project-description-doesn-t-render"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Project Description Doesn’t Render&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Python Package Index (PyPI) supports project (long) descriptions written in
three possible formats: &lt;a class="reference external" href="https://docutils.sourceforge.io/rst.html"&gt;reStructuredText&lt;/a&gt; (the default if no format is
specified), Markdown (either &lt;a class="reference external" href="https://github.github.com/gfm/"&gt;GitHub Flavored Markdown&lt;/a&gt; or &lt;a class="reference external" href="https://commonmark.org"&gt;CommonMark&lt;/a&gt;), and
plain text.  Markdown and plain text are lenient formats; anything you write in
them is valid.  However, documents written in reStructuredText can be
malformed, producing errors &amp;amp; warning messages when rendered.  When a project
with a malformed reStructuredText description (either because it uses
reStructuredText incorrectly or because it’s actually Markdown that wasn’t
declared as Markdown) is uploaded to PyPI, PyPI does one of the following two
things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;If the project does not declare a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Content-Type&lt;/span&gt;&lt;/tt&gt; for its malformed
description, PyPI will fall back to displaying the source of the description
as though it were plain text.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If the project explicitly declares the malformed description’s
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Content-Type&lt;/span&gt;&lt;/tt&gt; as reStructuredText (i.e., as the MIME type &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;text/x-rst&lt;/span&gt;&lt;/tt&gt;),
PyPI will reject the upload.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Neither situation is desirable, but at least the latter gives you the chance to
correct your project description before it’s released on PyPI, while the former
situation means your project’s PyPI page shows an ugly, unprofessional-looking
description until you make a new release.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;When using setuptools, you may find that your project’s long description
has been mangled somewhat, with a bunch of “Field: Value” entries added to
the bottom and various information missing from the listing on the left
side of the PyPI project page.  This happens whenever you include a newline
in your project’s summary/short description, thereby triggering &lt;a class="reference external" href="https://github.com/pypa/setuptools/issues/1390"&gt;setuptools
bug #1390&lt;/a&gt;.  Always make sure that no newlines end up passed to the
&lt;tt class="docutils literal"&gt;description&lt;/tt&gt; argument of &lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt;!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;There are two things you can do to avoid uploading a project with a malformed
description to PyPI:&lt;/p&gt;
&lt;ul id="set-content-type"&gt;
&lt;li&gt;&lt;p class="first"&gt;Set your description’s &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Content-Type&lt;/span&gt;&lt;/tt&gt; appropriately.  If you’re using
reStructuredText, this will cause PyPI to reject any uploads with malformed
project descriptions.  If you’re not using reStructuredText, setting the
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Content-Type&lt;/span&gt;&lt;/tt&gt; is necessary in order for your description to be rendered
properly.&lt;/p&gt;
&lt;p&gt;The content types for the supported formats are as follows:&lt;/p&gt;
&lt;table class="docutils field-list" frame="void" rules="none"&gt;
&lt;col class="field-name" /&gt;
&lt;col class="field-body" /&gt;
&lt;tbody valign="top"&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;reStructuredText:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;text/x-rst&lt;/span&gt;&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Markdown (GitHub Flavored Markdown):&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;text/markdown&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;text/markdown; variant=GFM&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Markdown (CommonMark):&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;text/markdown; variant=CommonMark&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Plain text:&lt;/th&gt;&lt;td class="field-body"&gt;&lt;tt class="docutils literal"&gt;text/plain&lt;/tt&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If your project is built using setuptools, you set the description’s
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Content-Type&lt;/span&gt;&lt;/tt&gt; by setting the &lt;tt class="docutils literal"&gt;long_description_content_type&lt;/tt&gt; argument to
&lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt; to the appropriate value from the above table.  Note that this
requires setuptools 36.4.0 or higher in order to work (or 38.3.0 or higher if
you’re setting it in &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Run the &lt;tt class="docutils literal"&gt;twine check&lt;/tt&gt; command from &lt;a class="reference external" href="https://twine.readthedocs.io"&gt;twine&lt;/a&gt; on your sdist and wheel before
uploading them.  This command checks whether your project description can be
rendered on PyPI before you actually upload it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="project-description-not-included"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Project Description Not Included&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It’s just embarrassing when this happens.  A project without a long description
just looks completely pointless; how am I supposed to know what it does or how
to use it?  Sadly, too many projects on PyPI lack long descriptions.  Did the
developer not care enough to write even a README?  Did the developer forget to
use the README as the long description or not know they had to?&lt;/p&gt;
&lt;p&gt;If your project’s got a README — and really, a project that doesn’t have one
isn’t ready to be released — and it’s written in reStructuredText, Markdown, or
plain text (a safe bet), you can (and should) use it as your project’s long
description by adding the following or similar to your &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;README.extension&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;long_description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;long_description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;long_description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If your project isn’t in reStructuredText, you’ll also need to set
&lt;tt class="docutils literal"&gt;long_description_content_type&lt;/tt&gt; to the appropriate value in &lt;a class="reference internal" href="#set-content-type"&gt;the table above&lt;/a&gt; so that the description renders properly on PyPI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="python-package-not-included-in-wheel"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Python Package Not Included in Wheel&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If not having a description is embarrassing, not having any code in your wheel
is crippling.  With a wheel like this, when people install your project, they
get nothing!  That’s certainly not what you want, is it?&lt;/p&gt;
&lt;p&gt;Possible reasons why this can happen include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;You’re using &lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt; to autolocate your project’s packages, but
you failed to add an &lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt; file to the top-level package (and
possibly also some subpackages).  Solution: Add that &lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;If your intention is to leave out the &lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt; file in order to
create a namespace package, you’ll need to use &lt;a class="reference external" href="https://setuptools.readthedocs.io/en/latest/setuptools.html#find-namespace-packages"&gt;&lt;tt class="docutils literal"&gt;find_namespace_packages()&lt;/tt&gt;&lt;/a&gt;
instead.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Your project’s code is a single Python module (as opposed to a directory of
modules) and you’re using the &lt;tt class="docutils literal"&gt;packages&lt;/tt&gt; argument to &lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt; and/or
&lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt; in an attempt to declare the module to setuptools.  This
is wrong.  When your project is a single Python module, instead of the
&lt;tt class="docutils literal"&gt;packages&lt;/tt&gt; argument, you need to use the &lt;tt class="docutils literal"&gt;py_modules&lt;/tt&gt; argument.  Set
&lt;tt class="docutils literal"&gt;py_modules&lt;/tt&gt; to a list of strings where each string is the name of a
top-level Python module &lt;em&gt;without&lt;/em&gt; the “&lt;tt class="docutils literal"&gt;.py&lt;/tt&gt;” extension.  (Usually, you’ll
just have one module to list here.)  You can’t use &lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt; for
this.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="pkg-test"&gt;If your project includes any tests (which it should), you can implicitly test
that your wheel contains your project code by testing against the installed
version of your project instead of the copy in your repository.  To do this,
&lt;tt class="docutils literal"&gt;pip&lt;/tt&gt;-install your package (ideally in a virtualenv, and not in
development/editable mode!) before running the tests and ensure that the
directory containing the repository copy of your code is not in &lt;tt class="docutils literal"&gt;sys.path&lt;/tt&gt;
when the tests run.  &lt;a class="reference external" href="https://tox.readthedocs.io"&gt;Tox&lt;/a&gt; can help with the first part.  The second part
depends in part on your test framework, but you can guarantee your tests aren’t
picking up the local copy by switching to a &lt;tt class="docutils literal"&gt;src/&lt;/tt&gt; layout (&lt;a class="reference internal" href="#src"&gt;see above&lt;/a&gt;).  With these two things in place, your tests will be forced to import
your package from &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;site-packages&lt;/span&gt;&lt;/tt&gt;, where it’s in a form determined by the
contents of the project’s wheel.  If your wheel is missing code and your tests
try to import that code, you’ll get an error when the tests run, and you’ll
know that you need to fix something.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="subpackages-not-included-in-wheel"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Subpackages Not Included in Wheel&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Sometimes, a project’s top-level package directory and the files within get
included in a wheel, but the subdirectories and their contents get left out.
Admittedly, I don’t know how common this is, as you can’t determine whether a
wheel is missing subpackages just by looking at its contents unless you also
know what’s in the project’s repository.  However, it’s an easy thing to mess
up, and various packaging articles I’ve read frequently make reference to this
problem, so it can’t be that uncommon.&lt;/p&gt;
&lt;p&gt;There are two major reasons why one or more of your Python package’s
subpackages might be omitted from wheels:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;You’re passing a list of packages to the &lt;tt class="docutils literal"&gt;packages&lt;/tt&gt; argument to &lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt;
and the list fails to include every package &amp;amp; subpackage in your project.  If
your project’s top-level package is named “&lt;tt class="docutils literal"&gt;foo&lt;/tt&gt;” and it contains two
subdirectories named “&lt;tt class="docutils literal"&gt;bar&lt;/tt&gt;” and “&lt;tt class="docutils literal"&gt;baz&lt;/tt&gt;” that contain (directly or
indirectly) Python source files, then &lt;tt class="docutils literal"&gt;bar&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;baz&lt;/tt&gt; are subpackages of
&lt;tt class="docutils literal"&gt;foo&lt;/tt&gt;, and they all need to be included in the packages list:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;foo.bar&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;foo.baz&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If &lt;tt class="docutils literal"&gt;baz&lt;/tt&gt; contains another directory named “&lt;tt class="docutils literal"&gt;glarch&lt;/tt&gt;” that contains more
Python source files, then &lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;foo.baz.glarch&amp;quot;&lt;/span&gt;&lt;/code&gt; needs to be included in the
list as well, and so on.&lt;/p&gt;
&lt;p&gt;Note that directories that only contain data files and no Python source files
do not count as packages and should not be passed to the &lt;tt class="docutils literal"&gt;packages&lt;/tt&gt;
argument.  They are instead &lt;em&gt;package data&lt;/em&gt; directories; &lt;a class="reference internal" href="#package-data"&gt;see below&lt;/a&gt; for advice on dealing with them.&lt;/p&gt;
&lt;p&gt;Of course, a simple alternative to listing every package explicitly is to
just use the &lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt; function, which brings us to cause #2 …&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;You’re using &lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt; to autolocate your project’s packages, but
you failed to add an &lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt; file to one or more subpackages.
&lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt; only counts something as a package if it contains an
&lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt; file, so you need to include that file in any subdirectory of
your Python package that contains Python source files or contains a directory
that contains Python source files.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As with omitting the package entirely from the wheel, &lt;a class="reference internal" href="#pkg-test"&gt;proper testing practices&lt;/a&gt; can let you know when this happens in advance of a release.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="package-data-not-included-in-wheel"&gt;
&lt;span id="package-data"&gt;&lt;/span&gt;&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Package Data Not Included in Wheel&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Sometimes, you want to include non-Python data or resource files inside a
Python package so that they can be used at runtime, but sometimes those files
fail to end up in the final wheel.  Like the omission of subpackages, it’s hard
to know just how common this is, but even experienced Python programmers have
made mistakes with package data configurations on occasion.  This also happens
to be yet another situation where &lt;a class="reference internal" href="#pkg-test"&gt;testing the installed version of your code&lt;/a&gt; will help you out.&lt;/p&gt;
&lt;p&gt;Setuptools provides two ways to specify package data.  The first way is to
configure &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; so that the desired package data files are included
in the sdist and then pass &lt;code class="py python"&gt;&lt;span class="n"&gt;include_package_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/code&gt; to &lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt; so
that all files inside the Python package that are included in the sdist are
also included in the wheel.  Pretty much the only way to make a mistake here is
by not matching all of the files you want with &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; commands;
&lt;a class="reference external" href="https://packaging.python.org/guides/using-manifest-in/"&gt;consult this reference&lt;/a&gt; if you run into problems.&lt;/p&gt;
&lt;p&gt;The second way to specify package data is with the &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; argument to
&lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt;.  This argument takes a &lt;tt class="docutils literal"&gt;dict&lt;/tt&gt; mapping package &amp;amp; subpackage names
to lists of glob patterns defining what package data files to include in sdists
&amp;amp; wheels.  The biggest gotcha with this method is the fact that each glob
pattern is only applied to the corresponding package and not any of its
subpackages.  This means that, with a &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; like this:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;package_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;*.txt&lt;/tt&gt; files in &lt;tt class="docutils literal"&gt;package&lt;/tt&gt; will be recognized as package data and included
in the sdist &amp;amp; wheel, but &lt;tt class="docutils literal"&gt;*.txt&lt;/tt&gt; files in &lt;tt class="docutils literal"&gt;package.subpackage&lt;/tt&gt; will not.
To include &lt;tt class="docutils literal"&gt;*.txt&lt;/tt&gt; files in &lt;tt class="docutils literal"&gt;package.subpackage&lt;/tt&gt;, you’ll need to either add
a &lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;package.subpackage&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/code&gt; entry to &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; or else
include all &lt;tt class="docutils literal"&gt;*.txt&lt;/tt&gt; files in all packages &amp;amp; subpackages by using the empty
string as a key: &lt;code class="py python"&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;No matter which method you choose, be sure to exclude &lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt; files from
consideration as package data; &lt;a class="reference internal" href="#pyc"&gt;see the next section&lt;/a&gt; for why.&lt;/p&gt;
&lt;p&gt;Note that if you combine the two ways to specify package data by setting
&lt;code class="py python"&gt;&lt;span class="n"&gt;include_package_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/code&gt; while also using &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt;, then the
files matched by &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; will not be included in the sdist unless
they’re already included by &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt;.  Getting this wrong can cause
wheels built from an sdist to lack package data files.&lt;/p&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files"&gt;“Including Data Files” in the setuptools documentation&lt;/a&gt; for more
information.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pyc-files-included-in-wheel"&gt;
&lt;span id="pyc"&gt;&lt;/span&gt;&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;&lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt; Files Included in Wheel&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a Python source file is imported into a Python process, a &lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt; file
containing compiled bytecode is created and (in Python 3) stored in a
&lt;tt class="docutils literal"&gt;__pycache__/&lt;/tt&gt; directory so that future imports of the same file will be
faster.  These &lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt; files use a format that is specific to the OS, Python
implementation, and Python version, and so it is pointless to share them.  They
do not belong in wheels (especially considering that pip already generates a
host-appropriate set of &lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt; files when it installs a wheel), and yet too
often people distribute wheels with &lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt; files in them.&lt;/p&gt;
&lt;p&gt;Probably the most common reason why &lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt; files end up in wheels is that
the project’s &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; file contains “&lt;tt class="docutils literal"&gt;graft packagename&lt;/tt&gt;”, “&lt;tt class="docutils literal"&gt;graft
src&lt;/tt&gt;”, or a similar line and &lt;code class="py python"&gt;&lt;span class="n"&gt;include_package_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/code&gt; is passed to
&lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt;.  With this configuration, all files in the Python package
directory when the wheel is built are added to the wheel.  To prevent &lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt;
files from being added, “&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;global-exclude&lt;/span&gt; *.pyc&lt;/tt&gt;” or similar needs to be added
to the &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt;, ideally at the end of the file.&lt;/p&gt;
&lt;p&gt;Alternatively, if the project specifies its package data with the
&lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; argument, including a &lt;tt class="docutils literal"&gt;&amp;quot;*&amp;quot;&lt;/tt&gt; pattern in the &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt;
mapping is liable to cause &lt;tt class="docutils literal"&gt;*.pyc&lt;/tt&gt; files to be included in the wheel.  They
should be excluded from package data by setting &lt;tt class="docutils literal"&gt;exclude_package_data&lt;/tt&gt; to a
&lt;tt class="docutils literal"&gt;dict&lt;/tt&gt; that maps the appropriate keys to &lt;code class="py python"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.pyc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="rebuilding-wheels-without-deleting-build"&gt;
&lt;span id="rebuild-noclean"&gt;&lt;/span&gt;&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Rebuilding Wheels without Deleting &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You should have noticed when building your project’s wheels that, in addition
to creating a &lt;tt class="docutils literal"&gt;dist/&lt;/tt&gt; directory containing the output wheel, setuptools also
creates a &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt; directory containing a couple directories and a copy of
your code.  This &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt; directory is an intermediate stage in the process
of assembling a wheel; you should exclude it from version control and feel free
to delete it at any time.  In fact, it’s a good idea to delete it before
running the command to create a wheel, &lt;em&gt;especially&lt;/em&gt; if you’ve moved or renamed
any files or directories in your code since the last time you built a wheel.&lt;/p&gt;
&lt;p&gt;Consider the following scenario:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;You build a wheel for your project, and you leave the &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt; directory
lying around afterwards.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;You move, rename, and/or delete some files in your Python package, perhaps
even renaming the package itself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;You build the wheel again — and when you do so, setuptools copies your new
package tree into &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt;.  Files that existed the last time the wheel was
built overwrite their old copies in &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt; successfully, but any old
paths that have since been removed remain in &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;As a result, your wheel ends up containing a mixture of your new and old
code.  In the case where you renamed your package, the wheel will contain
both the pre-rename package and the post-rename package next to each other in
their entirety, so you wheel has double the code with half of it under the
wrong name.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is clearly not desirable.  The solution is to always delete the &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt;
directory before building a wheel, such as by cleaning your repository with
&lt;tt class="docutils literal"&gt;git clean&lt;/tt&gt; or similar, or by running &lt;tt class="docutils literal"&gt;python setup.py clean &lt;span class="pre"&gt;--all&lt;/span&gt;&lt;/tt&gt; &lt;a class="footnote-reference" href="#footnote-1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;An even worse situation occurs if your &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt; uses
&lt;tt class="docutils literal"&gt;find_namespace_packages()&lt;/tt&gt; without any arguments.  In this case, if you
rebuild your package without first deleting the &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt; directory,
&lt;tt class="docutils literal"&gt;find_namespace_packages()&lt;/tt&gt; will notice the &lt;tt class="docutils literal"&gt;.py&lt;/tt&gt; files in &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt; and
assume that &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt; is a namespace package, and so it’ll include &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt;
in your wheels — which means that &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt; gets copied into &lt;tt class="docutils literal"&gt;build/&lt;/tt&gt;,
resulting in multiple package hierarchies in your wheels, with the problem
compounding the more times you build your project without deleting the
&lt;tt class="docutils literal"&gt;build/&lt;/tt&gt; directory.  This particular problem can be mitigated by using the
&lt;tt class="docutils literal"&gt;where&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;exclude&lt;/tt&gt;, and/or &lt;tt class="docutils literal"&gt;include&lt;/tt&gt; arguments to
&lt;tt class="docutils literal"&gt;find_namespace_packages()&lt;/tt&gt;, which have the same meaning as for
&lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pinning-project-requirements-to-exact-versions"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Pinning Project Requirements to Exact Versions&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are a number of projects on PyPI where the dependencies are all of the
form “&lt;tt class="docutils literal"&gt;foo == 1.2.3&lt;/tt&gt;”, as opposed to “&lt;tt class="docutils literal"&gt;foo &amp;gt;= 1.2.3&lt;/tt&gt;”, “&lt;tt class="docutils literal"&gt;foo &amp;gt;= 1.2, &amp;lt;
2&lt;/tt&gt;”, or just “&lt;tt class="docutils literal"&gt;foo&lt;/tt&gt;”.  This is called &lt;em&gt;pinning&lt;/em&gt; requirements.  This makes
sense when you’re developing a Python application that will be the primary
project in its environment (in which case you often won’t be uploading it to
PyPI), but it doesn’t make sense when you’re distributing a library for others
to use alongside other arbitrary libraries.  For one thing, your library is
almost certainly going to work just as well with version 1.2.4 of foo &lt;a class="footnote-reference" href="#footnote-2" id="footnote-reference-2"&gt;[2]&lt;/a&gt;, so
why leave it out?  For another thing, if someone wants to use your library with
its pinned &lt;tt class="docutils literal"&gt;foo&lt;/tt&gt; requirement alongside other libraries, sooner or later
they’ll run into a situation where they’re installing both it and another
project that requires a different version of &lt;tt class="docutils literal"&gt;foo&lt;/tt&gt; (maybe even differing by
one micro version!), and then problems ensue &lt;a class="footnote-reference" href="#footnote-3" id="footnote-reference-3"&gt;[3]&lt;/a&gt;.  True, clashes between
version dependencies in disparate projects can’t be avoided 100%, but they can
be made to occur far less often if projects require generous version ranges
instead of specific versions.&lt;/p&gt;
&lt;p&gt;A general way to construct a decent version range for a requirement is to first
determine the lowest version of the dependency that has all of the features you
need and then use this version as the requirement’s lower bound.  If the
dependency follows or approximates &lt;a class="reference external" href="https://semver.org"&gt;semantic versioning&lt;/a&gt;,
use the next major version (or the next minor version, if pre-v1) as the
(exclusive) upper bound.  If the dependency uses something like calendar
versioning instead, things are less clear, but my preference is to leave out
the upper bound and afterwards keep abreast of any future changes to the
dependency.  If any versions of the dependency inside the requirement’s bounds
have known bugs that interfere with your project’s behavior, feel free to
exclude them by adding specifiers of the form &lt;tt class="docutils literal"&gt;!= X.Y.Z&lt;/tt&gt; to the version
range.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Conclusion&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m very disappointed in all of you for making these mistakes so often, and I
hope this article makes at least one Python package less broken.  (I’d prefer
it if all broken packages were less broken, but I know not to get my hopes up.)&lt;/p&gt;
&lt;p&gt;Admittedly, most of these mistakes are due to users not using or understanding
setuptools properly (aside from a Poetry anti-pattern that sneaked in at #2).
Though flit and Poetry may promise to fix setuptools’ usability issues, people
keep on using setuptools, and it keeps on outsmarting them.  Hopefully sites
like the &lt;a class="reference external" href="https://packaging.python.org"&gt;Python Packaging User Guide&lt;/a&gt; eventually expand &amp;amp; become mature
enough in the near future to cover — if not all the edge cases — at least the
best practices that avoid them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="footnotes"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Footnotes&lt;/a&gt;&lt;/h2&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-1" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Setuptools is currently trying to get people to move away from
&lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt; commands, so &lt;tt class="docutils literal"&gt;setup.py clean&lt;/tt&gt; will be discouraged — and
probably deprecated — at some indeterminate point in the future.  Until
that happens, though, don’t feel bad about using it if you need to.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-2" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-2"&gt;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Unless &lt;tt class="docutils literal"&gt;foo&lt;/tt&gt; is an unpredictable, compatibility-breaking mess, in
which case you should probably reconsider depending on it.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="footnote-3" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#footnote-reference-3"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Currently, pip handles conflicting version requirements with a warning
and picking one requirement to follow, but pip’s new dependency resolver
due out in October 2020 (already available if you pass the right flag to
pip) will react to such situations by searching for older versions of
the installation candidates with non-conflicting requirements, and if it
can’t find any, it errors out without installing anything.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</content><category term="Programming"></category><category term="Python"></category><category term="Python packaging"></category><category term="setuptools"></category><category term="best practices"></category><category term="advice"></category></entry><entry><title>Setting Default Option Values from Config Files with Click</title><link href="https://jwodder.github.io/kbits/posts/click-config/" rel="alternate"></link><published>2020-07-17T00:00:00-04:00</published><updated>2020-07-17T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2020-07-17:/kbits/posts/click-config/</id><summary type="html">&lt;p class="first last"&gt;How to set up a Click program to read default option values from a config
file&lt;/p&gt;
</summary><content type="html">&lt;p&gt;When developing a command-line application in Python with &lt;a class="reference external" href="https://palletsprojects.com/p/click/"&gt;Click&lt;/a&gt;, you may find
yourself wanting to use a configuration file to set the parameters’ default
values at runtime and to be able to specify such a file with a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--config&lt;/span&gt;&lt;/tt&gt;
option.  There are various libraries of varying quality that provide such
functionality in different ways; however, implementing such functionality on
one’s own is simple enough (as this document will show), and knowing the
basics will help you develop more advanced implementations when the libraries
out there don’t meet your needs.&lt;/p&gt;
&lt;p&gt;All code in this document has been tested against Click version 7.1.2.&lt;/p&gt;
&lt;div class="section" id="default-map"&gt;
&lt;h2&gt;&lt;tt class="docutils literal"&gt;default_map&lt;/tt&gt;&lt;/h2&gt;
&lt;p&gt;The key feature of Click that will allow us to set parameter values from a
configuration file is the &lt;tt class="docutils literal"&gt;default_map&lt;/tt&gt; attribute of &lt;tt class="docutils literal"&gt;click.Context&lt;/tt&gt;,
documented at &lt;a class="reference external" href="https://click.palletsprojects.com/en/7.x/commands/#overriding-defaults"&gt;[1]&lt;/a&gt;.  Any values set in this &lt;code class="py python"&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;/code&gt; before parameters are
processed will become the parameters’ new default values.  Any extra keys that
do not correspond to defined parameters are ignored.&lt;/p&gt;
&lt;p&gt;Moreover, Click will map values in &lt;tt class="docutils literal"&gt;default_map&lt;/tt&gt; through the parameters’
normal type conversion &amp;amp; validation routines.  This means that, if you have an
option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt; defined with &lt;code class="py python"&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;/code&gt;, you can set
&lt;code class="py python"&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;5&amp;quot;&lt;/span&gt;&lt;/code&gt;, and the value will be converted to an
&lt;code class="py python"&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;/code&gt; by the time it’s passed to the command callback.  This even works for
boolean flags: a value set for a boolean flag option will be processed by the
&lt;a class="reference external" href="https://click.palletsprojects.com/en/7.x/parameters/#parameter-types"&gt;&lt;tt class="docutils literal"&gt;click.BOOL&lt;/tt&gt;&lt;/a&gt; type, which maps boolean-like strings to &lt;code class="py python"&gt;&lt;span class="nb"&gt;bool&lt;/span&gt;&lt;/code&gt; values.  This
eases your workload when reading from a configuration file type like INI where
values don’t come with type information; just pass the values straight to
Click, and it’ll do the conversion for you the same as it does for values on
the command line.&lt;/p&gt;
&lt;p&gt;Areas to be careful in include parameters defined with &lt;code class="py python"&gt;&lt;span class="n"&gt;multiple&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;/code&gt;.
The default value for such parameters (whether declared with &lt;code class="py python"&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;/code&gt; in
the parameter’s decorator or set in &lt;tt class="docutils literal"&gt;default_map&lt;/tt&gt;) must be a list or tuple;
setting such a default to a string will cause the string to be interpreted as a
list of single-character strings.  Also requiring special attention are options
defined with &lt;tt class="docutils literal"&gt;nargs&lt;/tt&gt; or with a tuple of types; correct handling for all of
these is left as an exercise for the reader.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="implementing-a-config-option"&gt;
&lt;h2&gt;Implementing a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--config&lt;/span&gt;&lt;/tt&gt; option&lt;/h2&gt;
&lt;p&gt;In order to define a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--config&lt;/span&gt; FILE&lt;/tt&gt; option that reads from &lt;tt class="docutils literal"&gt;FILE&lt;/tt&gt; and sets
other parameters’ default values, the option first of all needs to be &lt;a class="reference external" href="https://click.palletsprojects.com/en/7.x/options/#callbacks-and-eager-options"&gt;eager&lt;/a&gt; so
that it can modify &lt;tt class="docutils literal"&gt;ctx.default_map&lt;/tt&gt; before the other options read it, and it
needs to be defined with a callback that does the actual work.  Everything else
after that is straightforward.&lt;/p&gt;
&lt;p&gt;Here is a sample Python script with a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--config&lt;/span&gt;&lt;/tt&gt; option that reads from a
given config file (or from &lt;tt class="docutils literal"&gt;config.ini&lt;/tt&gt; in the current directory if no config
file is given).  The config file must be an INI file, and the values for the
options are read from the &lt;tt class="docutils literal"&gt;[options]&lt;/tt&gt; section.  The command callback simply
dumps out its arguments so you can see what’s being passed to it.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nn"&gt;configparser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ConfigParser&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;click&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_CFG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'config.ini'&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConfigParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'options'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s1"&gt;'-c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'--config'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;type&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir_okay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;default&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_CFG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;callback&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;is_eager&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;expose_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;help&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Read option defaults from the specified INI file'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;show_default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--integer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--flag/--no-flag'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--str'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--choice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Choice&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'red'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'green'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'blue'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If we run this script with no options when &lt;tt class="docutils literal"&gt;config.ini&lt;/tt&gt; does not exist or is
empty, we get the parameters’ built-in default values:&lt;/p&gt;
&lt;pre class="code console literal-block"&gt;
&lt;span class="gp"&gt;$ &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;config01.py&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;{
    &amp;quot;choice&amp;quot;: null,
    &amp;quot;flag&amp;quot;: false,
    &amp;quot;integer&amp;quot;: 42,
    &amp;quot;str&amp;quot;: &amp;quot;foo&amp;quot;
}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;That’s boring!  Try populating &lt;tt class="docutils literal"&gt;example.ini&lt;/tt&gt; with the below text:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[options]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;integer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;23&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;flag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;bar&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;choice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;green&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;… and then run with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--config&lt;/span&gt; example.ini&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code console literal-block"&gt;
&lt;span class="gp"&gt;$ &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;config01.py&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;example.ini&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;{
    &amp;quot;choice&amp;quot;: &amp;quot;green&amp;quot;,
    &amp;quot;flag&amp;quot;: true,
    &amp;quot;integer&amp;quot;: 23,
    &amp;quot;str&amp;quot;: &amp;quot;bar&amp;quot;
}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note that the values set for the &lt;tt class="docutils literal"&gt;flag&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;integer&lt;/tt&gt; options have been
converted to their appropriate types.&lt;/p&gt;
&lt;p&gt;Of course, options set in the config file are overridden by command-line
options, no matter where the options occur in relation to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--config&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code console literal-block"&gt;
&lt;span class="gp"&gt;$ &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;config01.py&lt;span class="w"&gt; &lt;/span&gt;--integer&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;example.ini&lt;span class="w"&gt; &lt;/span&gt;--str&lt;span class="w"&gt; &lt;/span&gt;glarch&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;{
    &amp;quot;choice&amp;quot;: &amp;quot;green&amp;quot;,
    &amp;quot;flag&amp;quot;: true,
    &amp;quot;integer&amp;quot;: 17,
    &amp;quot;str&amp;quot;: &amp;quot;glarch&amp;quot;
}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;What if a value in the config file is invalid?  Try saving the following text
to &lt;tt class="docutils literal"&gt;bad.ini&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[options]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;choice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mauve&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The script will then error when passed this config file:&lt;/p&gt;
&lt;pre class="code console literal-block"&gt;
&lt;span class="gp"&gt;$ &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;config01.py&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;bad.ini&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;Usage: config01.py [OPTIONS]
Try 'config01.py --help' for help.

Error: Invalid value for '--choice': invalid choice: mauve. (choose from red, green, blue)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Not the best possible error message (It doesn’t tell us the bad value was in
the config file), but it’s better than a stack trace.&lt;/p&gt;
&lt;p&gt;Note that, with this code, parameters in the config file must be named using
the same name &amp;amp; spelling as the parameter’s corresponding argument to the
command callback.  For example, the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--integer&lt;/span&gt;&lt;/tt&gt; option must be written
&lt;tt class="docutils literal"&gt;integer&lt;/tt&gt;, not &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--integer&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-i&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;i&lt;/tt&gt;; any entries in the config
file with an invalid spelling will be ignored.  For options with medial hyphens
on the command line, like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--log-level&lt;/span&gt;&lt;/tt&gt;, the hyphens must become underscores
in the configuration file, like &lt;tt class="docutils literal"&gt;log_level&lt;/tt&gt;.  If you want to support the
spelling &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;log-level&lt;/span&gt;&lt;/tt&gt; as well, insert the following line after &lt;code class="py python"&gt;&lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;ConfigParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/code&gt; to make the &lt;tt class="docutils literal"&gt;ConfigParser&lt;/tt&gt; object convert hyphens in option
names to underscores:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;optionxform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="configuring-command-groups"&gt;
&lt;h2&gt;Configuring command groups&lt;/h2&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;default_map&lt;/tt&gt; supports passing values to subcommands in command groups in a
very simple way: if the main command has a subcommand named “&lt;tt class="docutils literal"&gt;foo&lt;/tt&gt;”, then
&lt;code class="py python"&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/code&gt; can be set to a &lt;code class="py python"&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;/code&gt; of parameter names &amp;amp;
values for &lt;tt class="docutils literal"&gt;foo&lt;/tt&gt;.  For example, the following assignment:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;color&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;red&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;high&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;speed&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;low&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;baz&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;            &lt;span class="s2"&gt;&amp;quot;time&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;late&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;sets the default value for the main command’s &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--color&lt;/span&gt;&lt;/tt&gt; option to &lt;tt class="docutils literal"&gt;red&lt;/tt&gt;,
the default value of the &lt;tt class="docutils literal"&gt;foo&lt;/tt&gt; subcommand’s &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--speed&lt;/span&gt;&lt;/tt&gt;  option to &lt;tt class="docutils literal"&gt;high&lt;/tt&gt;,
the default value of the &lt;tt class="docutils literal"&gt;bar&lt;/tt&gt; subcommand’s &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--speed&lt;/span&gt;&lt;/tt&gt; option to &lt;tt class="docutils literal"&gt;low&lt;/tt&gt;,
and the default value of the &lt;tt class="docutils literal"&gt;bar baz&lt;/tt&gt; sub-subcommand’s &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--time&lt;/span&gt;&lt;/tt&gt; option to
&lt;tt class="docutils literal"&gt;late&lt;/tt&gt;.  As you can see, this comes with one major drawback: a command can’t
have a subcommand with the same name as one of its parameters.&lt;/p&gt;
&lt;p&gt;Here is a sample Python script with command groups that reads configuration
from an INI file.  Settings in the &lt;tt class="docutils literal"&gt;[options]&lt;/tt&gt; section are applied to the
top-level command, settings in the &lt;tt class="docutils literal"&gt;[options.CMD]&lt;/tt&gt; section are applied to the
subcommand &lt;tt class="docutils literal"&gt;CMD&lt;/tt&gt;, settings in &lt;tt class="docutils literal"&gt;[options.CMD1.CMD2]&lt;/tt&gt; are applied to the
&lt;tt class="docutils literal"&gt;CMD2&lt;/tt&gt; sub-subcommand of the &lt;tt class="docutils literal"&gt;CMD1&lt;/tt&gt; subcommand, and so forth.  As above,
each command prints out the parameters it receives.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nn"&gt;configparser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ConfigParser&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;click&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_CFG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'config.ini'&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConfigParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sect&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sections&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;command_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;command_path&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'options'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;            &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;defaults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default_map&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cmdname&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;command_path&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;            &lt;span class="n"&gt;defaults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;defaults&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmdname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;defaults&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sect&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoke_without_command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s1"&gt;'-c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'--config'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;type&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir_okay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;default&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_CFG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;callback&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;is_eager&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;expose_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;help&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Read option defaults from the specified INI file'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;show_default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--integer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--flag/--no-flag'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--str'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--choice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Choice&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'red'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'green'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'blue'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'* main'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--speed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Choice&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'low'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'medium'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'high'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ludicrous'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'medium'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'* foo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoke_without_command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--speed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Choice&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'low'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'medium'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'high'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ludicrous'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'medium'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'* bar'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;bar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'--time'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;click&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Choice&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'early'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'late'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'exact'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'early'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'* baz'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Set &lt;tt class="docutils literal"&gt;config.ini&lt;/tt&gt; to the following:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[options]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;integer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;23&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;flag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;bar&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;choice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;green&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;[options.foo]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;speed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;[options.bar]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;speed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;[options.bar.baz]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;late&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;… and then invoke some commands to see the results:&lt;/p&gt;
&lt;pre class="code console literal-block"&gt;
&lt;span class="gp"&gt;$ &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;config02.py&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;* main
{
    &amp;quot;choice&amp;quot;: &amp;quot;green&amp;quot;,
    &amp;quot;flag&amp;quot;: true,
    &amp;quot;integer&amp;quot;: 23,
    &amp;quot;str&amp;quot;: &amp;quot;bar&amp;quot;
}
&lt;/span&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;config02.py&lt;span class="w"&gt; &lt;/span&gt;foo&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;* main
{
    &amp;quot;choice&amp;quot;: &amp;quot;green&amp;quot;,
    &amp;quot;flag&amp;quot;: true,
    &amp;quot;integer&amp;quot;: 23,
    &amp;quot;str&amp;quot;: &amp;quot;bar&amp;quot;
}
* foo
{
    &amp;quot;speed&amp;quot;: &amp;quot;high&amp;quot;
}
&lt;/span&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;config02.py&lt;span class="w"&gt; &lt;/span&gt;bar&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;* main
{
    &amp;quot;choice&amp;quot;: &amp;quot;green&amp;quot;,
    &amp;quot;flag&amp;quot;: true,
    &amp;quot;integer&amp;quot;: 23,
    &amp;quot;str&amp;quot;: &amp;quot;bar&amp;quot;
}
* bar
{
    &amp;quot;speed&amp;quot;: &amp;quot;low&amp;quot;
}
&lt;/span&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;config02.py&lt;span class="w"&gt; &lt;/span&gt;bar&lt;span class="w"&gt; &lt;/span&gt;baz&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;* main
{
    &amp;quot;choice&amp;quot;: &amp;quot;green&amp;quot;,
    &amp;quot;flag&amp;quot;: true,
    &amp;quot;integer&amp;quot;: 23,
    &amp;quot;str&amp;quot;: &amp;quot;bar&amp;quot;
}
* bar
{
    &amp;quot;speed&amp;quot;: &amp;quot;low&amp;quot;
}
* baz
{
    &amp;quot;time&amp;quot;: &amp;quot;late&amp;quot;
}
&lt;/span&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;python3&lt;span class="w"&gt; &lt;/span&gt;config02.py&lt;span class="w"&gt; &lt;/span&gt;--choice&lt;span class="w"&gt; &lt;/span&gt;red&lt;span class="w"&gt; &lt;/span&gt;foo&lt;span class="w"&gt; &lt;/span&gt;--speed&lt;span class="w"&gt; &lt;/span&gt;medium&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;* main
{
    &amp;quot;choice&amp;quot;: &amp;quot;red&amp;quot;,
    &amp;quot;flag&amp;quot;: true,
    &amp;quot;integer&amp;quot;: 23,
    &amp;quot;str&amp;quot;: &amp;quot;bar&amp;quot;
}
* foo
{
    &amp;quot;speed&amp;quot;: &amp;quot;medium&amp;quot;
}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
</content><category term="Programming"></category><category term="Python"></category><category term="Click"></category><category term="configuration file"></category><category term="command-line parsing"></category></entry></feed>