<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Knowledge Bits</title><link href="https://jwodder.github.io/kbits/" rel="alternate"></link><link href="https://jwodder.github.io/kbits/feeds/posts.atom.xml" rel="self"></link><id>https://jwodder.github.io/kbits/</id><updated>2026-05-22T00:00:00-04:00</updated><subtitle>References I wish I'd already found</subtitle><entry><title>Retrieving Logs for a Single Service Run from systemd</title><link href="https://jwodder.github.io/kbits/posts/systemd-logs/" rel="alternate"></link><published>2026-05-10T00:00:00-04:00</published><updated>2026-05-10T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2026-05-10:/kbits/posts/systemd-logs/</id><summary type="html">&lt;p class="first last"&gt;How to get the command output for a single run of a systemd service from
the systemd journal&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;a class="reference external" href="https://systemd.io"&gt;systemd&lt;/a&gt; is the init system and service manager (and a
bunch of other things) used by many major Linux distributions.  As a service
manager, it provides the ability to run programs (called &lt;em&gt;services&lt;/em&gt;) in the
background with features like restarting failed programs or running programs on
a schedule.  By default (i.e., unless a service’s unit file says to send it
somewhere else), the output from these programs is stored in a &lt;a class="reference external" href="https://www.freedesktop.org/software/systemd/man/latest/systemd-journald.service.html"&gt;journal&lt;/a&gt; that
can be viewed with the &lt;a class="reference external" href="https://www.freedesktop.org/software/systemd/man/latest/journalctl.html"&gt;&lt;tt class="docutils literal"&gt;journalctl(1)&lt;/tt&gt;&lt;/a&gt; command.  However, basic &lt;tt class="docutils literal"&gt;journalctl(1)&lt;/tt&gt;
invocations have the potential to swamp you with logs; sometimes you just want
to see the output from a single run of a service or see a history of when a
service was started &amp;amp; stopped.  Here’s how you do that.&lt;/p&gt;
&lt;p&gt;This article is based on systemd 255 on Ubuntu Noble 24.04.  There may be some
corner cases I have missed that make what I say here not 100% accurate.&lt;/p&gt;
&lt;div class="section" id="basic-journalctl-1-usage"&gt;
&lt;h2&gt;Basic &lt;tt class="docutils literal"&gt;journalctl(1)&lt;/tt&gt; Usage&lt;/h2&gt;
&lt;p&gt;By default, a given user only has permission to read journal entries for their
own per-user systemd service manager.  In order to read the system journal or
other users’ journals, you must be &lt;tt class="docutils literal"&gt;root&lt;/tt&gt; (possibly via &lt;tt class="docutils literal"&gt;sudo&lt;/tt&gt;) or belong
to the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;systemd-journal&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;adm&lt;/tt&gt;, or &lt;tt class="docutils literal"&gt;wheel&lt;/tt&gt; group.&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;Journal entries do not last forever; you only have so much disk space,
after all.  Depending on configuration, the journal service will delete old
entries if they reach a certain age or if the total size of the journal
reaches a certain limit.  You therefore might not be able to retrieve
information from the journal about things that happened too long ago.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can get a basic view of all the journal entries for a service by running
&lt;tt class="docutils literal"&gt;journalctl &lt;span class="pre"&gt;-u&lt;/span&gt; $service&lt;/tt&gt;, where &lt;tt class="docutils literal"&gt;$service&lt;/tt&gt; is the name of the service with
or without the “&lt;tt class="docutils literal"&gt;.service&lt;/tt&gt;” suffix.  Add the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--user&lt;/span&gt;&lt;/tt&gt; option if the service
belongs to your per-user manager.  The entries shown can be limited with the
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-n&lt;/span&gt;&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--lines&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--since&lt;/span&gt;&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--until&lt;/span&gt;&lt;/tt&gt; options, among others; see the
&lt;a class="reference external" href="https://www.freedesktop.org/software/systemd/man/latest/journalctl.html"&gt;&lt;tt class="docutils literal"&gt;journalctl(1)&lt;/tt&gt;&lt;/a&gt; manpage for more information.&lt;/p&gt;
&lt;p&gt;By default, the output from &lt;tt class="docutils literal"&gt;journalctl&lt;/tt&gt; is a chronological sequence of both
systemd-generated messages (things like “Starting myservice.service”) and
service-generated messages (such as standard output from the service commands).
Each line consists of a timestamp, a hostname, a command name, a PID, and the
actual message.  The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-o&lt;/span&gt;&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--output&lt;/span&gt;&lt;/tt&gt; option can be used to adjust the
output format, though most formats only differ in how the timestamp is
displayed.&lt;/p&gt;
&lt;p&gt;Internally, each entry in systemd’s journal consists of a number of key-value
pairs called &lt;em&gt;fields&lt;/em&gt; that include data on the logged message, when it was
emitted, and where it came from.  Most of the fields are documented in
&lt;a class="reference external" href="https://www.freedesktop.org/software/systemd/man/latest/systemd.journal-fields.html"&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;systemd.journal-fields(7)&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;, and you can output all fields of journal entries by
passing &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-o&lt;/span&gt; json&lt;/tt&gt; (or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-o&lt;/span&gt; &lt;span class="pre"&gt;json-pretty&lt;/span&gt;&lt;/tt&gt; or another supported JSON format) or
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-o&lt;/span&gt; verbose&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;journalctl&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;journalctl&lt;/tt&gt; entries can be filtered based on field values by passing the
command one or more &lt;em&gt;match arguments&lt;/em&gt; of the form &lt;tt class="docutils literal"&gt;FIELDNAME=VALUE&lt;/tt&gt;.  Note
that only exact string matches on values are supported; you cannot ask
&lt;tt class="docutils literal"&gt;journalctl&lt;/tt&gt; to filter, say, by a regex or by whether a field is set/unset;
for that, postprocessing the output with &lt;a class="reference external" href="https://jqlang.org"&gt;&lt;tt class="docutils literal"&gt;jq(1)&lt;/tt&gt;&lt;/a&gt; or another program is necessary.
Multiple match arguments for the same field name are ORed together, while match
arguments for different fields are ANDed.  Using &lt;tt class="docutils literal"&gt;+&lt;/tt&gt; as an argument causes
the preceding match arguments to be ORed as a group against the following match
arguments.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="systemd-vs-service-entries"&gt;
&lt;h2&gt;Systemd vs. Service Entries&lt;/h2&gt;
&lt;p&gt;When working with a service’s journal logs, there are two main types of entries
that we usually want to discern between: entries emitted by systemd itself
about the service — usually messages of the form “Starting myservice.service”,
“Stopped myservice.service”, etc. — and entries that contain output from the
service’s actual command(s).&lt;/p&gt;
&lt;p&gt;Entries from systemd itself about a service are distinguished by having the
&lt;tt class="docutils literal"&gt;INVOCATION_ID&lt;/tt&gt; field (or &lt;tt class="docutils literal"&gt;USER_INVOCATION_ID&lt;/tt&gt; for user services) set but
not &lt;tt class="docutils literal"&gt;_SYSTEMD_INVOCATION_ID&lt;/tt&gt;; the &lt;tt class="docutils literal"&gt;SYSLOG_IDENTIFIER&lt;/tt&gt; field will also have
a value of “&lt;tt class="docutils literal"&gt;systemd&lt;/tt&gt;”.  The &lt;tt class="docutils literal"&gt;UNIT&lt;/tt&gt; field (or &lt;tt class="docutils literal"&gt;USER_UNIT&lt;/tt&gt; for user
services) will also be set to the name of the service in question (including
template arguments and the “&lt;tt class="docutils literal"&gt;.service&lt;/tt&gt;” suffix).&lt;/p&gt;
&lt;div class="admonition caution"&gt;
&lt;p class="first admonition-title"&gt;Caution!&lt;/p&gt;
&lt;p class="last"&gt;Field names without leading underscores are not “trusted” journal fields,
and thus any program that writes directly to the journal can create an
entry with &lt;tt class="docutils literal"&gt;INVOCATION_ID&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;SYSLOG_IDENTIFIER&lt;/tt&gt;, or &lt;tt class="docutils literal"&gt;UNIT&lt;/tt&gt; set to
whatever it wants.  In order to exclude any potential deceptive entries
when using &lt;tt class="docutils literal"&gt;journalctl&lt;/tt&gt; to filter by one or more of these fields, include
&lt;tt class="docutils literal"&gt;_PID=1&lt;/tt&gt; as a match argument so that you only see entries from
&lt;tt class="docutils literal"&gt;systemd&lt;/tt&gt; itself.  Note that this only works when querying the system
manager; for user managers, there does not seem to be a foolproof way to
say “only show entries generated by the manager.”&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Entries for actual output from a service’s commands (including child commands)
are distinguished by having the &lt;tt class="docutils literal"&gt;_SYSTEMD_INVOCATION_ID&lt;/tt&gt; field set, but not
&lt;tt class="docutils literal"&gt;INVOCATION_ID&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;USER_INVOCATION_ID&lt;/tt&gt;.  The &lt;tt class="docutils literal"&gt;_SYSTEMD_UNIT&lt;/tt&gt; field (or
&lt;tt class="docutils literal"&gt;_SYSTEMD_USER_UNIT&lt;/tt&gt; for user services) will also be set to the name of the
service in question (including template arguments and the “&lt;tt class="docutils literal"&gt;.service&lt;/tt&gt;”
suffix).&lt;/p&gt;
&lt;p&gt;Note that the latter kind of entries don’t just cover the service’s stdout &amp;amp;
stderr; if the service command logged anything via syslog or wrote to the
journal directly, that’s in here, too.  You can separate out these sources by
filtering on the &lt;tt class="docutils literal"&gt;_TRANSPORT&lt;/tt&gt; field, which has a value of “&lt;tt class="docutils literal"&gt;stdout&lt;/tt&gt;” for
the command’s standard output &amp;amp; standard error (and for input to
&lt;a class="reference external" href="https://www.freedesktop.org/software/systemd/man/latest/systemd-cat.html"&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;systemd-cat(1)&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;), “&lt;tt class="docutils literal"&gt;syslog&lt;/tt&gt;” for syslog messages, and “&lt;tt class="docutils literal"&gt;journal&lt;/tt&gt;” for
messages written directly to the journal with the &lt;a class="reference external" href="https://www.freedesktop.org/software/systemd/man/latest/sd_journal_print.html"&gt;&lt;tt class="docutils literal"&gt;sd_journal_print(3)&lt;/tt&gt;&lt;/a&gt; APIs.&lt;/p&gt;
&lt;p&gt;You may be wondering about the value of the &lt;tt class="docutils literal"&gt;SYSLOG_IDENTIFIER&lt;/tt&gt; mentioned
above when it comes to command output entries.  As far as I can determine, when
&lt;tt class="docutils literal"&gt;_TRANSPORT&lt;/tt&gt; is “&lt;tt class="docutils literal"&gt;stdout&lt;/tt&gt;” or “&lt;tt class="docutils literal"&gt;journal&lt;/tt&gt;”, &lt;tt class="docutils literal"&gt;SYSLOG_IDENTIFIER&lt;/tt&gt; is
usually the filename of the executable that produced the message, except for
messages produced with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;systemd-cat&lt;/span&gt;&lt;/tt&gt;, which use the identifier specified on
the command line with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--identifier&lt;/span&gt;&lt;/tt&gt;, leaving the field unset if the option
is not given.  For &lt;tt class="docutils literal"&gt;_TRANSPORT=syslog&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;SYSLOG_IDENTIFIER&lt;/tt&gt; is the program
name by default, but programs that write to syslog are free to use any string
they want as their identifier.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="invocation-ids"&gt;
&lt;h2&gt;Invocation IDs&lt;/h2&gt;
&lt;p&gt;As you may have noticed above, journal entries related to a service run all
have an invocation ID associated with them.  Each invocation ID is a random
32-character hexadecimal string that identifies a specific &lt;em&gt;runtime cycle&lt;/em&gt; of a
service (the period between when the service changes from “inactive” to
“active”/”activating” and when it becomes inactive again).  An invocation ID is
the key information needed to get the logs for a single service run from
&lt;tt class="docutils literal"&gt;journalctl&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;If you want to view the logs for the most-recently started run of a service,
begin by getting that run’s invocation ID via:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
systemctl show --no-pager -P InvocationID $service
&lt;/pre&gt;
&lt;p&gt;Replace &lt;tt class="docutils literal"&gt;$service&lt;/tt&gt; with the name of the service in question (with or without
the “&lt;tt class="docutils literal"&gt;.service&lt;/tt&gt;” suffix).  If querying a user session unit, add &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--user&lt;/span&gt;&lt;/tt&gt; to
the command.  If the service has stopped and not been restarted, this command
will nevertheless output the invocation ID for the most recent (stopped) run.
If the given service does not exist or was never started, the command will
output a blank line.&lt;/p&gt;
&lt;p&gt;If the run you want logs for is not the most recent, you’ll need to determine
the run’s invocation ID by looking back through the journal for the service.
If you just know the approximate time at which the desired run occurred, you
can browse the “Starting $service.service” and “Stopped $service.service”
systemd messages with their timestamps &amp;amp; corresponding invocation IDs by using
&lt;a class="reference external" href="https://jqlang.org"&gt;&lt;tt class="docutils literal"&gt;jq(1)&lt;/tt&gt;&lt;/a&gt; and the following shell command:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
journalctl -o json -t systemd -u $service | jq -r '&amp;quot;[\(.__REALTIME_TIMESTAMP|tonumber / 1000000 | todate)] [\(.INVOCATION_ID)] \(.MESSAGE)&amp;quot;'
&lt;/pre&gt;
&lt;p&gt;Replace &lt;tt class="docutils literal"&gt;$service&lt;/tt&gt; with the name of the service in question (with or without
the “&lt;tt class="docutils literal"&gt;.service&lt;/tt&gt;” suffix).  If querying a user session unit, add &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--user&lt;/span&gt;&lt;/tt&gt; to
the &lt;tt class="docutils literal"&gt;journalctl&lt;/tt&gt; command and change &lt;tt class="docutils literal"&gt;.INVOCATION_ID&lt;/tt&gt; in the &lt;tt class="docutils literal"&gt;jq&lt;/tt&gt; command
to &lt;tt class="docutils literal"&gt;.USER_INVOCATION_ID&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;This will give you output like the following, letting you map timestamp ranges
to invocation IDs:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[2026-04-22T13:41:35Z] [439e459b1db44a97974eae5c133f4543] Starting apache2.service - The Apache HTTP Server...
[2026-04-22T13:41:36Z] [439e459b1db44a97974eae5c133f4543] Started apache2.service - The Apache HTTP Server.
[2026-04-23T00:00:00Z] [439e459b1db44a97974eae5c133f4543] Reloading apache2.service - The Apache HTTP Server...
[2026-04-23T00:00:00Z] [439e459b1db44a97974eae5c133f4543] Reloaded apache2.service - The Apache HTTP Server.
[2026-04-24T00:00:00Z] [439e459b1db44a97974eae5c133f4543] Reloading apache2.service - The Apache HTTP Server...
[2026-04-24T00:00:00Z] [439e459b1db44a97974eae5c133f4543] Reloaded apache2.service - The Apache HTTP Server.
[2026-04-26T00:00:00Z] [439e459b1db44a97974eae5c133f4543] Reloading apache2.service - The Apache HTTP Server...
[2026-04-26T00:00:01Z] [439e459b1db44a97974eae5c133f4543] Reloaded apache2.service - The Apache HTTP Server.
[2026-04-27T00:00:01Z] [439e459b1db44a97974eae5c133f4543] Reloading apache2.service - The Apache HTTP Server...
[2026-04-27T00:00:01Z] [439e459b1db44a97974eae5c133f4543] Reloaded apache2.service - The Apache HTTP Server.
[2026-05-07T16:19:39Z] [439e459b1db44a97974eae5c133f4543] Stopping apache2.service - The Apache HTTP Server...
[2026-05-07T16:19:40Z] [439e459b1db44a97974eae5c133f4543] apache2.service: Deactivated successfully.
[2026-05-07T16:19:40Z] [439e459b1db44a97974eae5c133f4543] Stopped apache2.service - The Apache HTTP Server.
[2026-05-07T16:19:40Z] [439e459b1db44a97974eae5c133f4543] apache2.service: Consumed 8min 45.667s CPU time, 111.8M memory peak, 22.5M memory swap peak.
[2026-05-07T16:19:40Z] [c80c7d5e0453447ea57bf833b3ead2cf] Starting apache2.service - The Apache HTTP Server...
[2026-05-07T16:19:40Z] [c80c7d5e0453447ea57bf833b3ead2cf] Started apache2.service - The Apache HTTP Server.
[2026-05-08T00:00:00Z] [c80c7d5e0453447ea57bf833b3ead2cf] Reloading apache2.service - The Apache HTTP Server...
[2026-05-08T00:00:01Z] [c80c7d5e0453447ea57bf833b3ead2cf] Reloaded apache2.service - The Apache HTTP Server.
[2026-05-09T00:00:01Z] [c80c7d5e0453447ea57bf833b3ead2cf] Reloading apache2.service - The Apache HTTP Server...
[2026-05-09T00:00:01Z] [c80c7d5e0453447ea57bf833b3ead2cf] Reloaded apache2.service - The Apache HTTP Server.
[2026-05-10T00:00:00Z] [c80c7d5e0453447ea57bf833b3ead2cf] Reloading apache2.service - The Apache HTTP Server...
[2026-05-10T00:00:00Z] [c80c7d5e0453447ea57bf833b3ead2cf] Reloaded apache2.service - The Apache HTTP Server.
&lt;/pre&gt;
&lt;p&gt;If you don’t know the run’s timestamp but you can recognize the target run from
the command output, you can view all log messages prefixed with their
invocation IDs like so:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
journalctl -o json -u $service | jq -r '&amp;quot;[\(.INVOCATION_ID // ._SYSTEMD_INVOCATION_ID)] \(.MESSAGE)&amp;quot;'
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="getting-logs-for-an-invocation-id"&gt;
&lt;h2&gt;Getting Logs for an Invocation ID&lt;/h2&gt;
&lt;p&gt;Once you have the invocation ID for the service run you want to view logs for,
you can get the service’s output with:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
journalctl _SYSTEMD_INVOCATION_ID=$id
&lt;/pre&gt;
&lt;p&gt;where &lt;tt class="docutils literal"&gt;$id&lt;/tt&gt; is replaced by the invocation ID.  Note that there is no need to
specify the service name, nor even to specify &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--user&lt;/span&gt;&lt;/tt&gt; for user session
units.&lt;/p&gt;
&lt;p&gt;Note that the output from this command will include fields like timestamp,
hostname, command name, and PID in each line.  If you just want only the actual
output from the service with no “decorations,” add &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-o&lt;/span&gt; cat&lt;/tt&gt; to the command.
If you want custom formatting, your best bet is to output all the journal
fields with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-o&lt;/span&gt; json&lt;/tt&gt; and process the entries with &lt;tt class="docutils literal"&gt;jq&lt;/tt&gt; or another program.&lt;/p&gt;
&lt;p&gt;If you also want to include systemd’s “Starting”, “Stopped”, etc. messages in
the output (say, in order to see the command’s exit status), change the match
arguments like so:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
journalctl INVOCATION_ID=$id + _SYSTEMD_INVOCATION_ID=$id
&lt;/pre&gt;
&lt;p&gt;If querying a user session unit, change &lt;tt class="docutils literal"&gt;INVOCATION_ID&lt;/tt&gt; to
&lt;tt class="docutils literal"&gt;USER_INVOCATION_ID&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Software"></category><category term="systemd"></category><category term="UNIX"></category></entry><entry><title>Process Groups, Sessions, and Controlling Terminals</title><link href="https://jwodder.github.io/kbits/posts/process-groups/" rel="alternate"></link><published>2025-06-30T00:00:00-04:00</published><updated>2025-06-30T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2025-06-30:/kbits/posts/process-groups/</id><summary type="html">&lt;p class="first last"&gt;A summary of UNIX’s process groups, sessions, &amp;amp; controlling terminals and
how to work with them&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In UNIX, job control is implemented via &lt;em&gt;process groups&lt;/em&gt; and &lt;em&gt;sessions&lt;/em&gt;, which
allow a shell to place processes in the foreground (directly communicating with
a terminal) or in the background and to send signals to multiple processes at
once.  This article provides an overview of the concepts and shows the basics
of how to work with them.&lt;/p&gt;
&lt;p&gt;Unless specified otherwise, all information in this article is as per
&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/"&gt;POSIX.1-2024&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="concepts"&gt;
&lt;h2&gt;Concepts&lt;/h2&gt;
&lt;p&gt;Each UNIX process belongs to a &lt;em&gt;process group&lt;/em&gt; (a.k.a. &lt;em&gt;job&lt;/em&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Each process group is identified by an integer &lt;em&gt;process group ID&lt;/em&gt;, and the
process (if any) whose process ID equals this process group ID is called the
&lt;em&gt;process group leader&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;It is possible to send a signal to all processes in a process group at once
using &lt;tt class="docutils literal"&gt;kill()&lt;/tt&gt; [&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/kill.html"&gt;POSIX&lt;/a&gt;] [&lt;a class="reference external" href="https://man7.org/linux/man-pages/man2/kill.2.html"&gt;man7&lt;/a&gt;] or &lt;tt class="docutils literal"&gt;killpg()&lt;/tt&gt; [&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/killpg.html"&gt;POSIX&lt;/a&gt;] [&lt;a class="reference external" href="https://man7.org/linux/man-pages/man3/killpg.3.html"&gt;man7&lt;/a&gt;].&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each process group belongs to a &lt;em&gt;session&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The process that created a session is the &lt;em&gt;session leader&lt;/em&gt;.  This process is
also the process group leader of its process group.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;POSIX does not specify IDs for sessions, though Linux uses the process
(group) ID of the session leader as the session ID.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A session may be associated with at most one terminal called its &lt;em&gt;controlling
terminal&lt;/em&gt;, and each controlling terminal is associated with exactly one
session.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The controlling terminal is established by the session leader, which then
becomes known as the &lt;em&gt;controlling process&lt;/em&gt; for as long as the terminal
remains the controlling terminal.  When the controlling process terminates,
the session loses the controlling terminal, and any attempts by the remaining
processes in the session to access the terminal may result in a &lt;tt class="docutils literal"&gt;SIGHUP&lt;/tt&gt;
signal.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;It is possible for an individual process in a session to dissociate from the
controlling terminal without affecting the rest of the session.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;When a modem disconnect is detected for a controlling terminal, unless
&lt;tt class="docutils literal"&gt;CLOCAL&lt;/tt&gt; is set in the terminal’s &lt;tt class="docutils literal"&gt;c_cflag&lt;/tt&gt; field, &lt;tt class="docutils literal"&gt;SIGHUP&lt;/tt&gt; is sent to
the terminal’s controlling process, which by default terminates it.  Any
further attempts to read from the terminal will return EOF.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given a session associated with a controlling terminal, at most one process
group in the session is the &lt;em&gt;foreground process group&lt;/em&gt;, and all others are
&lt;em&gt;background process groups&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Processes in a foreground process group may read from &amp;amp; write to the
controlling terminal.  If a process in a background process group tries to
read from the controlling terminal, the entire process group will normally
&lt;a class="footnote-reference" href="#fn1" id="footnote-reference-1"&gt;[1]&lt;/a&gt; be sent a &lt;tt class="docutils literal"&gt;SITTIN&lt;/tt&gt; signal, which by default stops &amp;amp; suspends the
group.  If a process in a background process group tries to write to a
controlling terminal, the entire process group will normally &lt;a class="footnote-reference" href="#fn1" id="footnote-reference-2"&gt;[1]&lt;/a&gt; be sent
a &lt;tt class="docutils literal"&gt;SIGTTOU&lt;/tt&gt; signal, which by default stops &amp;amp; suspends the group; if
&lt;tt class="docutils literal"&gt;TOSTOP&lt;/tt&gt; is not set in the controlling terminal’s &lt;tt class="docutils literal"&gt;c_lflag&lt;/tt&gt; field, the
process will instead be allowed to write to the terminal, and no signal will
be sent.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="fn1" 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;[1]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-1"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-2"&gt;2&lt;/a&gt;)&lt;/em&gt; &lt;p class="last"&gt;See the special cases listed under the &lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap11.html#tag_11_01_04"&gt;“Terminal Access
Control”&lt;/a&gt; section of the POSIX standard for when this is not the case.&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Certain input key sequences like &lt;tt class="kbd docutils literal"&gt;Ctrl&lt;/tt&gt;-&lt;tt class="kbd docutils literal"&gt;C&lt;/tt&gt;, when entered at a
controlling terminal, will cause a signal to be sent to all processes in the
associated foreground process group.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Processes in the foreground process group are sent a &lt;tt class="docutils literal"&gt;SIGWINCH&lt;/tt&gt; signal
whenever the size of the controlling terminal changes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whenever a new process is created via &lt;tt class="docutils literal"&gt;fork()&lt;/tt&gt; or similar, it starts out with
the same session, process group, and controlling terminal as its parent.  A
process’s session, process group, and controlling terminal remain the same
across a call to &lt;tt class="docutils literal"&gt;execve()&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="process-groups-at-the-shell"&gt;
&lt;h2&gt;Process Groups at the Shell&lt;/h2&gt;
&lt;p&gt;In a POSIX-compatible shell, running a line composed of one or more &lt;em&gt;AND-OR
lists&lt;/em&gt; (commands containing zero or more of the operators &lt;tt class="docutils literal"&gt;!&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;|&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;amp;&amp;amp;&lt;/tt&gt;,
and/or &lt;tt class="docutils literal"&gt;||&lt;/tt&gt;) separated by semicolons creates a single foreground process
group.  If an AND-OR list in a line is terminated by &lt;tt class="docutils literal"&gt;&amp;amp;&lt;/tt&gt; (making it an
&lt;em&gt;asynchronous AND-OR list&lt;/em&gt;), then everything before it in the line (up to the
previous &lt;tt class="docutils literal"&gt;&amp;amp;&lt;/tt&gt;, if any) is run in a single foreground process group, and the
asynchronous AND-OR list itself is run as a single background process group;
processing of the line then continues afterwards.&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="c1"&gt;# These commands are all run in a single foreground process group:
&lt;/span&gt;head&lt;span class="w"&gt; &lt;/span&gt;bigfile.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;foo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Those were the foos.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;bigfile.txt&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# These commands are all run in a single background process group:
&lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-fsSL&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;download.html&lt;span class="w"&gt; &lt;/span&gt;https://www.example.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;touch&lt;span class="w"&gt; &lt;/span&gt;download-failed.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# The `echo` is run in a foreground process group, while the `wget` is
# run in a background process group:
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Going to download now'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;--quiet&lt;span class="w"&gt; &lt;/span&gt;https://www.example.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# The first `rm` and the `mkdir` are run in a foreground process group,
# then the `wget` is started in a background process group, then the second
# `rm` is started in a second background process group, and finally the
# `echo` is run in another foreground process group.
&lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;-rf&lt;span class="w"&gt; &lt;/span&gt;download&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;downloads&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-qO&lt;span class="w"&gt; &lt;/span&gt;downloads/example.html&lt;span class="w"&gt; &lt;/span&gt;https://www.example.com&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;-rf&lt;span class="w"&gt; &lt;/span&gt;bigdir&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Am I done?'&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;A background process group created by a shell can be brought to the foreground
with the &lt;tt class="docutils literal"&gt;fg&lt;/tt&gt; command, and a foreground process group can be placed in the
background by first stopping/suspending it with &lt;tt class="kbd docutils literal"&gt;Ctrl&lt;/tt&gt;-&lt;tt class="kbd docutils literal"&gt;Z&lt;/tt&gt; and then
running &lt;tt class="docutils literal"&gt;bg&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="querying-manipulating-process-groups-sessions-via-system-calls"&gt;
&lt;h2&gt;Querying &amp;amp; Manipulating Process Groups &amp;amp; Sessions via System Calls&lt;/h2&gt;
&lt;p&gt;The process group ID of the current process can be retrieved with the
&lt;tt class="docutils literal"&gt;getpgrp()&lt;/tt&gt; [&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/getpgrp.html"&gt;POSIX&lt;/a&gt;] [&lt;a class="reference external" href="https://man7.org/linux/man-pages/man3/getpgrp.3p.html"&gt;man7&lt;/a&gt;] function; the process group ID of an arbitrary
process can be retrieved with the &lt;tt class="docutils literal"&gt;getpgid()&lt;/tt&gt; [&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/getpgid.html"&gt;POSIX&lt;/a&gt;] [&lt;a class="reference external" href="https://man7.org/linux/man-pages/man3/getpgid.3p.html"&gt;man7&lt;/a&gt;] function.&lt;/p&gt;
&lt;p&gt;A process can change its process group or the process group of a child process
via the &lt;tt class="docutils literal"&gt;setpgid()&lt;/tt&gt; [&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/setpgid.html"&gt;POSIX&lt;/a&gt;] [&lt;a class="reference external" href="https://www.man7.org/linux/man-pages/man2/setpgid.2.html"&gt;man7&lt;/a&gt;] function; the target process group can
be either a pre-existing group in the same session or a new process group that
will be created in the same session.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The process group ID of a session leader cannot be changed.  Thus, programs
intending to create a new process group typically call &lt;tt class="docutils literal"&gt;fork()&lt;/tt&gt; first and
then call &lt;tt class="docutils literal"&gt;setpgid()&lt;/tt&gt; from the child process in order to ensure that it’s
not being called by a session leader.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;getsid()&lt;/tt&gt; [&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/getsid.html"&gt;POSIX&lt;/a&gt;] [&lt;a class="reference external" href="https://man7.org/linux/man-pages/man2/getsid.2.html"&gt;man7&lt;/a&gt;] function can be used to retrieve the
process group ID of the session leader (equal to Linux’s session ID) of a given
process.&lt;/p&gt;
&lt;p&gt;A new session can be created via the &lt;tt class="docutils literal"&gt;setsid()&lt;/tt&gt; [&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/setsid.html"&gt;POSIX&lt;/a&gt;] [&lt;a class="reference external" href="https://man7.org/linux/man-pages/man2/setsid.2.html"&gt;man7&lt;/a&gt;] function,
which makes the calling process into the new session’s session leader and into
the process group leader of a new process group in the session; the calling
process will have no controlling terminal afterwards.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;setsid()&lt;/tt&gt; cannot be called by a process group leader.  Thus, programs
intending to create a new session typically call &lt;tt class="docutils literal"&gt;fork()&lt;/tt&gt; first and then
call &lt;tt class="docutils literal"&gt;setsid()&lt;/tt&gt; from the child process in order to ensure that it’s not
being called by a process group leader.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;ctermid()&lt;/tt&gt; [&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/ctermid.html"&gt;POSIX&lt;/a&gt;] [&lt;a class="reference external" href="https://man7.org/linux/man-pages/man3/ctermid.3.html"&gt;man7&lt;/a&gt;] function can be used to obtain the path to
the controlling terminal for the current process; the &lt;a class="reference external" href="https://www.gnu.org/software/libc/manual/html_node/Identifying-the-Terminal.html"&gt;GNU C Library
implementation&lt;/a&gt; always returns &lt;tt class="docutils literal"&gt;&amp;quot;/dev/tty&amp;quot;&lt;/tt&gt;, which is a synonym for the
controlling terminal on Linux (and macOS?).&lt;/p&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Tip&lt;/p&gt;
&lt;p&gt;If you really want the actual path to a process’s controlling terminal, and
you don’t want to invoke &lt;tt class="docutils literal"&gt;ps(1)&lt;/tt&gt; to get it, you can get partway there
using Linux’s &lt;tt class="docutils literal"&gt;/proc&lt;/tt&gt; filesystem: the seventh field of
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/proc/$PID/stat&lt;/span&gt;&lt;/tt&gt; contains the device number for the controlling terminal
of process &lt;tt class="docutils literal"&gt;$PID&lt;/tt&gt;, or 0 if the process doesn’t have a controlling
terminal.  Unfortunately, there is no convenient way to map the device
number to a path; cf. &lt;a class="reference external" href="https://gitlab.com/procps-ng/procps/-/blob/v4.0.5/library/devname.c?ref_type=tags#L326"&gt;how ps does it&lt;/a&gt;.&lt;/p&gt;
&lt;p class="last"&gt;Alternatively, you can approximate the controlling terminal for the current
process with &lt;tt class="docutils literal"&gt;ttyname(STDIN_FILENO)&lt;/tt&gt; or similar, but this won’t be
accurate in the rare cases where stdin has been replaced with something
other than the controlling terminal, possibly even a different, unrelated
terminal.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;POSIX does not specify a mechanism for setting the controlling terminal.  On
Linux and macOS, the controlling terminal for a session is established when a
session leader first opens a terminal, unless the &lt;tt class="docutils literal"&gt;O_NOCTTY&lt;/tt&gt; flag was passed
to the &lt;tt class="docutils literal"&gt;open()&lt;/tt&gt; call.  Linux and macOS also support setting the controlling
terminal via a session leader calling &lt;tt class="docutils literal"&gt;ioctl()&lt;/tt&gt; with &lt;tt class="docutils literal"&gt;op&lt;/tt&gt; set to
&lt;tt class="docutils literal"&gt;TIOCSCTTY&lt;/tt&gt; [&lt;a class="reference external" href="https://man7.org/linux/man-pages/man2/TIOCSCTTY.2const.html"&gt;man7&lt;/a&gt;], and any process may dissociate from its controlling
terminal by calling &lt;tt class="docutils literal"&gt;ioctl()&lt;/tt&gt; with &lt;tt class="docutils literal"&gt;op&lt;/tt&gt; set to &lt;tt class="docutils literal"&gt;TIOCNOTTY&lt;/tt&gt; [&lt;a class="reference external" href="https://man7.org/linux/man-pages/man2/TIOCNOTTY.2const.html"&gt;man7&lt;/a&gt;].&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;When a session gains a controlling terminal, the process group of the session
leader becomes the foreground process group.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Note that a session gaining a controlling terminal will not cause any
pre-existing processes in the session (other than the session leader) to gain
a controlling terminal, but any processes spawned from the session leader
afterwards will have a controlling terminal.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A process with a controlling terminal can acquire the process group ID of its
session’s foreground process group by calling &lt;tt class="docutils literal"&gt;tcgetpgrp()&lt;/tt&gt; [&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/tcgetpgrp.html"&gt;POSIX&lt;/a&gt;]
[&lt;a class="reference external" href="https://man7.org/linux/man-pages/man3/tcgetpgrp.3.html"&gt;man7&lt;/a&gt;], and it can set the foreground process group by calling
&lt;tt class="docutils literal"&gt;tcsetpgrp()&lt;/tt&gt; [&lt;a class="reference external" href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/tcsetpgrp.html"&gt;POSIX&lt;/a&gt;] [&lt;a class="reference external" href="https://man7.org/linux/man-pages/man3/tcsetpgrp.3.html"&gt;man7&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;There does not appear to be any way to get a list of processes in a process
group, a list of process groups in a session, or a list of extant sessions
other than by iterating over &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/proc/*/stat&lt;/span&gt;&lt;/tt&gt; files or using a facility that
does that for you, like &lt;tt class="docutils literal"&gt;ps(1)&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="creating-a-background-process-without-a-controlling-terminal-daemonization"&gt;
&lt;h2&gt;Creating a Background Process Without a Controlling Terminal (Daemonization)&lt;/h2&gt;
&lt;p&gt;In order to run a process as a &lt;em&gt;daemon&lt;/em&gt;, running truly in the background,
without a controlling terminal that could send &lt;tt class="docutils literal"&gt;SIGHUP&lt;/tt&gt; on session exit, you
could use a super-server like &lt;tt class="docutils literal"&gt;systemd&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;supervisord&lt;/tt&gt;, but if you’re
reading this, you probably want to know how they do it.&lt;/p&gt;
&lt;p&gt;A program seeking to run itself or another executable as a daemon should take
the following steps:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Call &lt;tt class="docutils literal"&gt;fork()&lt;/tt&gt;.  The rest of the steps are carried out in the resulting
child process, which is guaranteed not to be a session leader or process
group leader.  The parent process can either exit immediately or else track
the child process in order to detect &amp;amp; report any immediate unsuccessful
terminations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Call &lt;tt class="docutils literal"&gt;setsid()&lt;/tt&gt; to create a new session, one not associated with any
controlling terminal.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Close or redirect stdin, stdout, &amp;amp; stderr so that they no longer refer to
the original terminal.  It’s also recommended to set the current working
directory to the root directory, as using a different working directory
could prevent unmounting.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Call &lt;tt class="docutils literal"&gt;fork()&lt;/tt&gt; again to create a child process that is not a session leader
and thus cannot establish a controlling terminal.  This child process is
then used for the actual program proper (possibly via &lt;tt class="docutils literal"&gt;execve()&lt;/tt&gt;), and the
parent process exits.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content><category term="Programming"></category><category term="UNIX"></category><category term="processes"></category><category term="terminals"></category></entry><entry><title>Getting a Terminal’s Default Foreground &amp; Background Colors</title><link href="https://jwodder.github.io/kbits/posts/term-fgbg/" rel="alternate"></link><published>2025-06-10T00:00:00-04:00</published><updated>2025-08-22T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2025-06-10:/kbits/posts/term-fgbg/</id><summary type="html">&lt;p class="first last"&gt;When using &lt;a class="reference external" href="https://en.wikipedia.org/wiki/ANSI_escape_code"&gt;ANSI escape sequences&lt;/a&gt; to style text on a terminal,
you may need to know exactly what the default foreground &amp;amp; background
colors — the ones set with &lt;tt class="docutils literal"&gt;\e[39m&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;\e[49m&lt;/tt&gt; — are, as knowing
whether the user’s terminal is light-on-dark or dark-on-light can help you
pick an appropriate color theme.  Fortunately, the &lt;a class="reference external" href="https://invisible-island.net/xterm/ctlseqs/ctlseqs.html"&gt;escape sequences
supported by xterm and compatible terminals&lt;/a&gt; include sequences
for doing just that.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;When using &lt;a class="reference external" href="https://en.wikipedia.org/wiki/ANSI_escape_code"&gt;ANSI escape sequences&lt;/a&gt; to style text on a terminal, you
may need to know exactly what the default foreground &amp;amp; background colors — the
ones set with &lt;tt class="docutils literal"&gt;\e[39m&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;\e[49m&lt;/tt&gt; — are, as knowing whether the user’s
terminal is light-on-dark or dark-on-light can help you pick an appropriate
color theme.  Fortunately, the &lt;a class="reference external" href="https://invisible-island.net/xterm/ctlseqs/ctlseqs.html"&gt;escape sequences supported by xterm and
compatible terminals&lt;/a&gt; include sequences for doing just that.&lt;/p&gt;
&lt;p&gt;A program whose standard input &amp;amp; standard output are both connected to an
xterm-compatible terminal can query the default foreground color by writing the
characters &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;\e]10;?\e\\\\&lt;/span&gt;&lt;/tt&gt; to standard output, where &lt;tt class="docutils literal"&gt;\e&lt;/tt&gt; is the Escape
character (0x1B) and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;\\\\&lt;/span&gt;&lt;/tt&gt; represents a single backslash; to query the
default background color instead, change the &lt;tt class="docutils literal"&gt;10&lt;/tt&gt; to an &lt;tt class="docutils literal"&gt;11&lt;/tt&gt;.  The terminal
will then respond by writing back the query string with the &lt;tt class="docutils literal"&gt;?&lt;/tt&gt; replaced by a
string describing the default foreground or background color.&lt;/p&gt;
&lt;p&gt;In my limited experience, all color strings I’ve seen in responses have been
RGB values of the form &lt;tt class="docutils literal"&gt;rgb:XXXX/XXXX/XXXX&lt;/tt&gt;, where the &lt;tt class="docutils literal"&gt;X&lt;/tt&gt;’s are lowercase
hexadecimal digits (so white would be &lt;tt class="docutils literal"&gt;rgb:ffff/ffff/ffff&lt;/tt&gt; and black would be
&lt;tt class="docutils literal"&gt;rgb:0000/0000/0000&lt;/tt&gt;), but &lt;a class="reference external" href="https://invisible-island.net/xterm/ctlseqs/ctlseqs.html"&gt;xterm’s documentation&lt;/a&gt; seems to
suggest that color names (presumably ones from the X11 color list) and any RGB
specifications accepted by &lt;a class="reference external" href="https://linux.die.net/man/3/xparsecolor"&gt;&lt;tt class="docutils literal"&gt;XParseColor(3)&lt;/tt&gt;&lt;/a&gt; are also possible return values.&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;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;\e\\\\&lt;/span&gt;&lt;/tt&gt; portion of the query &amp;amp; response (called the &lt;em&gt;string
terminator&lt;/em&gt; or ST) also has a legacy variant, a single BEL character
(0x07), which you may see sometimes.  xterm always responds using the same
string terminator as used in the request.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Tip&lt;/p&gt;
&lt;p class="last"&gt;By replacing the &lt;tt class="docutils literal"&gt;?&lt;/tt&gt; with an RGB specification, you can change the
default foreground &amp;amp; background colors instead!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;As with &lt;a class="reference external" href="https://jwodder.github.io/kbits/posts/cursor-pos/"&gt;getting the current cursor position&lt;/a&gt;, the
terminal will need to be set in cbreak and noecho modes when reading the
response.&lt;/p&gt;
&lt;p&gt;If you just want to see some code for doing all this on a Unix-like system,
here it is as a Python script:&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;__future__&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;annotations&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;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;Iterator&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;contextlib&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;contextmanager&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;copy&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;deepcopy&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;re&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;sys&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;termios&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;get_default_fg&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;
    Query the attached terminal for the default foreground color and return the
    color string from the response

    :raises IOError: if stdin or stdout is not a terminal
    :raises ValueError: if the reply from the terminal is malformed
    &amp;quot;&amp;quot;&amp;quot;&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;osc_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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;get_default_bg&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;
    Query the attached terminal for the default background color and return the
    color string from the response

    :raises IOError: if stdin or stdout is not a terminal
    :raises ValueError: if the reply from the terminal is malformed
    &amp;quot;&amp;quot;&amp;quot;&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;osc_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&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;osc_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ps&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="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;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;stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isatty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&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;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isatty&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;cbreak_noecho&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="se"&gt;\x1b&lt;/span&gt;&lt;span class="s2"&gt;]&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;?&lt;/span&gt;&lt;span class="se"&gt;\x1b\\&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&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="n"&gt;flush&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;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&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="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\x1b\\&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\x07&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;resp&lt;/span&gt; &lt;span class="o"&gt;+=&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;stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&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="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;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&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="s2"&gt;&amp;quot;surrogateescape&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;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;fullmatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;rf&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;\x1B\]&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;(.+)(?:\x1B&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;|\x07)&amp;quot;&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&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;else&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;ValueError&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="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="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;IOError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;not connected to a terminal&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;# File descriptor for standard input:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;STDIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# Indices into the tuple returned by `tcgetattr()`:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;LFLAG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;CC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;contextmanager&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;cbreak_noecho&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;Iterator&lt;/span&gt;&lt;span class="p"&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;
    A context manager that configures the terminal on standard input to use
    cbreak mode and to disable input echoing.  The original terminal
    configuration is restored on exit.
    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;orig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tcgetattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STDIN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;term&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deepcopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;LFLAG&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ICANON&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ECHO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CC&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VMIN&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="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CC&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VTIME&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tcsetattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STDIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TCSANOW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;term&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;yield&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tcsetattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STDIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TCSANOW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orig&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="s2"&gt;&amp;quot;__main__&amp;quot;&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;Foreground color:&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_default_fg&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;Background color:&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_default_bg&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programming"></category><category term="terminals"></category><category term="ANSI escape codes"></category></entry><entry><title>Getting the Current Cursor Position from a Terminal</title><link href="https://jwodder.github.io/kbits/posts/cursor-pos/" rel="alternate"></link><published>2025-05-29T00:00:00-04:00</published><updated>2025-08-22T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2025-05-29:/kbits/posts/cursor-pos/</id><summary type="html">&lt;p class="first last"&gt;When using &lt;a class="reference external" href="https://en.wikipedia.org/wiki/ANSI_escape_code"&gt;ANSI escape sequences&lt;/a&gt; to manipulate a compatible
terminal, you may need to know where the text cursor is currently located
on the screen, especially if its current location was set by the user or a
previous program rather than your code.  Fortunately, the ANSI escape
sequence standard &lt;a class="reference external" href="https://ecma-international.org/publications-and-standards/standards/ecma-48/"&gt;ECMA-48&lt;/a&gt; provides a sequence for doing just that.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;When using &lt;a class="reference external" href="https://en.wikipedia.org/wiki/ANSI_escape_code"&gt;ANSI escape sequences&lt;/a&gt; to manipulate a compatible
terminal, you may need to know where the text cursor is currently located on
the screen, especially if its current location was set by the user or a
previous program rather than your code.  Fortunately, the ANSI escape sequence
standard &lt;a class="reference external" href="https://ecma-international.org/publications-and-standards/standards/ecma-48/"&gt;ECMA-48&lt;/a&gt; provides a sequence for doing just that.&lt;/p&gt;
&lt;p&gt;A program whose standard input &amp;amp; standard output are both connected to an
ANSI-compatible terminal can query the current cursor location by writing the
characters &lt;tt class="docutils literal"&gt;\e[6n&lt;/tt&gt; to standard output, where &lt;tt class="docutils literal"&gt;\e&lt;/tt&gt; is the Escape character
(0x1B).  The terminal will then respond by writing back a string of the form
&lt;tt class="docutils literal"&gt;\e[l;cR&lt;/tt&gt; to standard input, where &lt;tt class="docutils literal"&gt;\e&lt;/tt&gt; is the Escape character, &lt;tt class="docutils literal"&gt;l&lt;/tt&gt; is a
decimal integer giving the line number of the cursor’s current position, and
&lt;tt class="docutils literal"&gt;c&lt;/tt&gt; is a decimal integer giving the column number of the cursor’s current
position.  The line &amp;amp; column numbers are both 1-based: the upper-left corner of
the screen is represented by (1, 1) rather than (0, 0).&lt;/p&gt;
&lt;p&gt;Note that reading the terminal’s response isn’t as simple as it may seem at
first.  On Unix-like systems, standard input from the terminal is buffered by
default and only made available to the running program when a newline is
entered, but the terminal’s response doesn’t end in a newline, so typical
line-reading functions won’t return until the user manually presses “Enter.”
This can be solved by putting the terminal in &lt;em&gt;cbreak mode&lt;/em&gt;, in which this
buffering is disabled and characters sent to standard input can be read
immediately.  (Alternatively, the terminal may be put in &lt;em&gt;raw mode&lt;/em&gt; instead,
which is unbuffered like cbreak mode but also disables the special meanings of
certain terminal-affecting key sequences like Ctrl-Q and Ctrl-S.)&lt;/p&gt;
&lt;p&gt;In addition to disabling buffering, you’ll also want to disable echoing of
input.  By default, when the terminal sends its response to standard input, the
characters will appear on the screen as if the user typed them, which is likely
not what you want; turning off input echoing fixes this.&lt;/p&gt;
&lt;p&gt;The full details of working with cbreak &amp;amp; noecho mode are a bit beyond the
scope of this article.  On Unix-like systems, you’ll need to use the
&lt;tt class="docutils literal"&gt;tcgetattr()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;tcsetattr()&lt;/tt&gt; functions from &lt;tt class="docutils literal"&gt;&amp;lt;termios.h&amp;gt;&lt;/tt&gt; or whatever
wrapper around them your programming language of choice provides.&lt;/p&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Tip&lt;/p&gt;
&lt;p class="last"&gt;To avoid a race condition, set cbreak and noecho mode &lt;em&gt;before&lt;/em&gt; printing the
query.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition important"&gt;
&lt;p class="first admonition-title"&gt;Important&lt;/p&gt;
&lt;p class="last"&gt;Be sure to set the terminal’s cbreak and echo settings back to what they
were originally when you’re done reading the response!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Finally, if you just want to see some code for doing all this on a Unix-like
system, here it is as a Python script:&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;__future__&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;annotations&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;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;Iterator&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;contextlib&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;contextmanager&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;copy&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;deepcopy&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;re&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;sys&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;termios&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;cursor_pos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;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="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;
    Query the attached terminal for the current cursor position and return
    the result as a ``(line, column)`` pair.

    :raises IOError: if stdin or stdout is not a terminal
    :raises ValueError: if the reply from the terminal is malformed
    &amp;quot;&amp;quot;&amp;quot;&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;stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isatty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&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;stdout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isatty&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;cbreak_noecho&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;&lt;/span&gt;&lt;span class="se"&gt;\x1b&lt;/span&gt;&lt;span class="s2"&gt;[6n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&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="n"&gt;flush&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;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&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="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;R&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;resp&lt;/span&gt; &lt;span class="o"&gt;+=&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;stdin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buffer&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="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;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&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="s2"&gt;&amp;quot;surrogateescape&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;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;fullmatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;\x1B\[(?P&amp;lt;line&amp;gt;[0-9]+);(?P&amp;lt;col&amp;gt;[0-9]+)R&amp;quot;&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="k"&gt;return&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;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;line&amp;quot;&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;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;col&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="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&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="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="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;IOError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;not connected to a terminal&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;# File descriptor for standard input:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;STDIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# Indices into the tuple returned by `tcgetattr()`:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;LFLAG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;CC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;span class="nd"&gt;&amp;#64;contextmanager&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;cbreak_noecho&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;Iterator&lt;/span&gt;&lt;span class="p"&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="sd"&gt;&amp;quot;&amp;quot;&amp;quot;
    A context manager that configures the terminal on standard input to use
    cbreak mode and to disable input echoing.  The original terminal
    configuration is restored on exit.
    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;orig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tcgetattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STDIN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;term&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deepcopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;LFLAG&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ICANON&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ECHO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CC&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VMIN&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="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CC&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VTIME&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tcsetattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STDIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TCSANOW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;term&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;yield&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;        &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tcsetattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;STDIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;termios&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TCSANOW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orig&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="s2"&gt;&amp;quot;__main__&amp;quot;&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;cursor_pos&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programming"></category><category term="terminals"></category><category term="ANSI escape codes"></category></entry><entry><title>The BitTorrent Encryption Protocol</title><link href="https://jwodder.github.io/kbits/posts/bt-encrypt/" rel="alternate"></link><published>2023-10-19T00:00:00-04:00</published><updated>2023-12-03T00:00:00-05:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2023-10-19:/kbits/posts/bt-encrypt/</id><summary type="html">&lt;p class="first last"&gt;The &lt;a class="reference external" href="https://en.wikipedia.org/wiki/BitTorrent_protocol_encryption"&gt;encryption protocol&lt;/a&gt; used by the &lt;a class="reference external" href="https://en.wikipedia.org/wiki/BitTorrent"&gt;BitTorrent&lt;/a&gt; peer-to-peer
file-sharing protocol — known variously as Message Stream Encryption (MSE),
Protocol Encryption (PE), or MSE/PE, among other names — is what keeps you
secure while you download massive amounts of … Linux ISOs.  Here’s how it
works.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;The &lt;a class="reference external" href="https://en.wikipedia.org/wiki/BitTorrent_protocol_encryption"&gt;encryption protocol&lt;/a&gt; used by the &lt;a class="reference external" href="https://en.wikipedia.org/wiki/BitTorrent"&gt;BitTorrent&lt;/a&gt; peer-to-peer file-sharing
protocol — known variously as Message Stream Encryption (MSE), Protocol
Encryption (PE), or MSE/PE, among other names — is what keeps you secure while
you download massive amounts of … Linux ISOs.  While some (including the
creator of BitTorrent) have been critical of the protocol, comparing it to mere
“obfuscation,” it remains highly popular among users distributing perfectly
legitimate files over the internet that ISPs shouldn’t concern themselves over.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;de facto&lt;/em&gt; specification for the protocol appears to be
&amp;lt;&lt;a class="reference external" href="https://wiki.vuze.com/w/Message_Stream_Encryption"&gt;https://wiki.vuze.com/w/Message_Stream_Encryption&lt;/a&gt;&amp;gt;, but the page has been down
whenever I’ve checked recently, and the actual content is not optimally
presented.  Thus, I’ve written up everything I’ve been able to determine about
MSE/PE here.&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="#overview" id="toc-entry-1"&gt;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="#client-s-handshake" id="toc-entry-3"&gt;Client’s Handshake&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#server-s-handshake" id="toc-entry-4"&gt;Server’s Handshake&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#after-the-handshake" id="toc-entry-5"&gt;After the Handshake&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#bittorrent-specific-aspects" id="toc-entry-6"&gt;BitTorrent-Specific Aspects&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#detecting-encryption" id="toc-entry-7"&gt;Detecting Encryption&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#broadcasting-encryption-support" id="toc-entry-8"&gt;Broadcasting Encryption Support&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="#references" id="toc-entry-9"&gt;References&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="overview"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Overview&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An MSE/PE connection begins with the client and server performing a
&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Diffie–Hellman_key_exchange"&gt;Diffie–Hellman key exchange&lt;/a&gt; handshake, in which each party generates a
private key with corresponding public key, the public keys are exchanged, and
then — by the power of mathematics — both parties independently calculate the
same number (the &lt;em&gt;shared secret&lt;/em&gt;), which remains unknown to eavesdroppers.
Each party then uses the shared secret to initialize two &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Keystream"&gt;keystreams&lt;/a&gt;: infinite
generators of pseudo-random bytes calculated from an initial value; the bytes
from one keystream are then used to encrypt &amp;amp; decrypt data sent from the client
to the server, and the other keystream is used for data sent from the server to
the client.&lt;/p&gt;
&lt;p&gt;After the handshake, the parties transmit their data, which is encrypted using
a method negotiated during the handshake; the only defined options are to keep
using the keystreams or to stop using encryption entirely.&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;MSE/PE encryption uses the following constants and functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;P&lt;/tt&gt; is the following 96-byte (768-bit) prime, here rendered in
hexadecimal:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
ffffffffffffffff c90fdaa22168c234  c4c6628b80dc1cd1 29024e088a67cc74
020bbea63b139b22 514a08798e3404dd  ef9519b3cd3a431b 302b0a6df25f1437
4fe1356d6d51c245 e485b576625e7ec6  f44c42e9a63a3621 0000000000090563
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;G&lt;/tt&gt; is 2 (a &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Primitive_root_modulo_n"&gt;primitive root&lt;/a&gt; &lt;em&gt;modulo&lt;/em&gt; &lt;tt class="docutils literal"&gt;P&lt;/tt&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;SKEY&lt;/tt&gt; is a shared key — a byte string with a value known or recognizable
by both parties.  For BitTorrent, this is the 20-byte info hash of the
torrent the connection is dedicated to.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;len(X)&lt;/tt&gt; is the length of the byte string &lt;tt class="docutils literal"&gt;X&lt;/tt&gt; as a two-byte big-endian
integer.  The length of &lt;tt class="docutils literal"&gt;X&lt;/tt&gt; cannot exceed 65535.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;HASH(X)&lt;/tt&gt; is the 20-byte SHA1 hash of the byte string &lt;tt class="docutils literal"&gt;X&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="client-s-handshake"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Client’s Handshake&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The peer initiating an MSE/PE connection performs its side of the handshake as
follows as soon as it opens the connection:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The client generates a random integer &lt;tt class="docutils literal"&gt;Xa&lt;/tt&gt; to use as its private key for
this connection only.  &lt;tt class="docutils literal"&gt;Xa&lt;/tt&gt; must be at least 128 bits long; using more than
180 bits is not believed to add further security.  160 bits is recommended.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The client calculates its public key: &lt;tt class="docutils literal"&gt;Ya = pow(G, Xa) mod P&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The client sends packet 1: &lt;tt class="docutils literal"&gt;Ya&lt;/tt&gt; encoded as a 96-byte (768-bit) big-endian
integer, followed by a string of random bytes with a randomly-chosen length
from 0 to 512.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The client receives packet 2.  Because the length of this packet is not known
by the client and there is no means for indicating the end of the packet, the
client must identify the end of the packet by waiting for sufficient time
(the original spec says 30 seconds) for the entire packet to arrive.  If the
server sends fewer than 96 bytes in that time (For comparison, the
unencrypted BitTorrent handshake message is 68 bytes), or the server sends
more than 608 bytes, then the server is not performing a valid MSE/PE
handshake.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The client extracts &lt;tt class="docutils literal"&gt;Yb&lt;/tt&gt; from the first 96 bytes of packet 2 and computes
the Diffie-Hellman shared secret: &lt;tt class="docutils literal"&gt;S = pow(Yb, Xa) mod P&lt;/tt&gt;.  &lt;tt class="docutils literal"&gt;Xa&lt;/tt&gt; is then
securely discarded.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;When used as a byte string in later steps, &lt;tt class="docutils literal"&gt;S&lt;/tt&gt; is encoded as a 96-byte
(768-bit) big-endian integer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The client initializes an outgoing &lt;a class="reference external" href="https://en.wikipedia.org/wiki/RC4"&gt;RC4&lt;/a&gt;
keystream from the key &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;HASH(&amp;quot;keyA&amp;quot;&lt;/span&gt; + S + SKEY)&lt;/tt&gt; and an incoming RC4
keystream from the key &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;HASH(&amp;quot;keyB&amp;quot;&lt;/span&gt; + S + SKEY)&lt;/tt&gt;.  The first 1024 bytes
output by each keystream are discarded.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The client sends packet 3, constructed as follows:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
HASH(&amp;quot;req1&amp;quot; + S)
+ (HASH(&amp;quot;req2&amp;quot; + SKEY) XOR HASH(&amp;quot;req3&amp;quot; + S))
+ RC4(VC + crypto_provide + len(PadC) + PadC + len(IA) + IA)
&lt;/pre&gt;
&lt;p&gt;where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;RC4(X)&lt;/tt&gt; encrypts the byte string &lt;tt class="docutils literal"&gt;X&lt;/tt&gt; by XORing it with bytes produced
by the outgoing RC4 keystream.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;VC&lt;/tt&gt; is a verification constant of eight zero-valued bytes that is used
to verify whether the other party knows &lt;tt class="docutils literal"&gt;S&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;SKEY&lt;/tt&gt; and thus defeat
replay attacks of the &lt;tt class="docutils literal"&gt;SKEY&lt;/tt&gt; hash.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;crypto_provide&lt;/tt&gt; is a 32-bit big-endian integer in which individual bits
are set to indicate the encryption methods supported by the client.  The
defined methods are plain text (bit 0x01) and RC4 (bit 0x02).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;PadC&lt;/tt&gt; is arbitrary data with a length of 0 to 512 bytes, reserved for
extending the crypto handshake in future versions.  Current implementations
may choose to set it to the empty string.  For padding-only usage in the
current version, the bytes should be zeroed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;IA&lt;/tt&gt; is the initial (post-handshake) data that the client wishes to send.
It may be 0 bytes long, and it cannot be more than 65535 bytes long.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The client receives &amp;amp; verifies packet 4:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The first eight bytes are received and decrypted by XORing them with bytes
from the incoming RC4 keystream.  If the resulting bytes are not all zero,
the handshake is invalid.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next four bytes are received and decrypted in the same manner to obtain
&lt;tt class="docutils literal"&gt;crypto_select&lt;/tt&gt;, a big-endian integer in which a bit corresponding to one
of the methods given in &lt;tt class="docutils literal"&gt;crypto_provide&lt;/tt&gt; has been set in order to
indicate which encryption method will be used after the handshake.  If
&lt;tt class="docutils literal"&gt;crypto_select&lt;/tt&gt; does not have exactly one bit set, or if the set bit does
not correspond to one of the methods in &lt;tt class="docutils literal"&gt;crypto_provide&lt;/tt&gt;, the handshake
is invalid.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next two bytes are received and decrypted to obtain &lt;tt class="docutils literal"&gt;len(PadD)&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next &lt;tt class="docutils literal"&gt;len(PadD)&lt;/tt&gt; bytes are received and decrypted to obtain &lt;tt class="docutils literal"&gt;PadD&lt;/tt&gt;.
Note that, although the result of the decryption is unused, the decryption
must still be performed in order to keep the incoming keystream in sync
with the server’s outgoing keystream.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="server-s-handshake"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Server’s Handshake&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The peer receiving an MSE/PE connection performs its side of the handshake as
follows as soon as it accepts the connection:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The server generates a private key &lt;tt class="docutils literal"&gt;Xb&lt;/tt&gt; following the same rules as for the
client’s private key.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The server calculates its public key: &lt;tt class="docutils literal"&gt;Yb = pow(G, Xb) mod P&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The server sends packet 2: &lt;tt class="docutils literal"&gt;Yb&lt;/tt&gt; encoded as a 96-byte (768-bit) big-endian
integer, followed by a string of random bytes with a randomly-chosen length
from 0 to 512.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The server receives packet 1.  As with the client’s receipt of packet 2, the
server must determine the end of packet 1 by waiting for sufficient time (the
original spec says 30 seconds) for the entire packet to arrive.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The server extracts &lt;tt class="docutils literal"&gt;Ya&lt;/tt&gt; from the first 96 bytes of packet 1 and computes
the Diffie-Hellman shared secret: &lt;tt class="docutils literal"&gt;S = pow(Ya, Xb) mod P&lt;/tt&gt; (This is equal to
the &lt;tt class="docutils literal"&gt;S&lt;/tt&gt; computed by the client).  &lt;tt class="docutils literal"&gt;Xb&lt;/tt&gt; is then securely discarded.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;When used as a byte string in later steps, &lt;tt class="docutils literal"&gt;S&lt;/tt&gt; is encoded as a 96-byte
(768-bit) big-endian integer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The server receives &amp;amp; verifies packet 3:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The first 20 bytes must equal &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;HASH(&amp;quot;req1&amp;quot;&lt;/span&gt; + S)&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next 20 bytes are received and XORed with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;HASH(&amp;quot;req3&amp;quot;&lt;/span&gt; + S)&lt;/tt&gt; to
obtain &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;HASH(&amp;quot;req2&amp;quot;&lt;/span&gt; + SKEY)&lt;/tt&gt;.  The server then identifies &lt;tt class="docutils literal"&gt;SKEY&lt;/tt&gt; by
comparing this hash against &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;HASH(&amp;quot;req2&amp;quot;&lt;/span&gt; + K)&lt;/tt&gt; for all known/accepted
shared keys &lt;tt class="docutils literal"&gt;K&lt;/tt&gt;.  (For BitTorrent, this means comparing against
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;HASH(&amp;quot;req2&amp;quot;&lt;/span&gt; + info_hash)&lt;/tt&gt; for all info hashes of torrents managed by the
server.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The server initializes an outgoing RC4 keystream from the key &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;HASH(&amp;quot;keyB&amp;quot;&lt;/span&gt;
+ S + SKEY)&lt;/tt&gt; and an incoming RC4 keystream from the key &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;HASH(&amp;quot;keyA&amp;quot;&lt;/span&gt; + S
+ SKEY)&lt;/tt&gt;.  (Note that this is the reverse of the client.)  The first 1024
bytes output by each keystream are discarded.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next eight bytes are received and decrypted by XORing them with bytes
from the incoming RC4 keystream.  If the resulting bytes are not all zero,
the handshake is invalid.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next four bytes are received and decrypted in the same manner to obtain
&lt;tt class="docutils literal"&gt;crypto_provide&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next two bytes are received and decrypted to obtain &lt;tt class="docutils literal"&gt;len(PadC)&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next &lt;tt class="docutils literal"&gt;len(PadC)&lt;/tt&gt; bytes are received and decrypted to obtain &lt;tt class="docutils literal"&gt;PadC&lt;/tt&gt;.
Note that, although the result of the decryption is unused, the decryption
must still be performed in order to keep the incoming keystream in sync
with the client’s outgoing keystream.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next two bytes are received and decrypted to obtain &lt;tt class="docutils literal"&gt;len(IA)&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next &lt;tt class="docutils literal"&gt;len(IA)&lt;/tt&gt; bytes are received and decrypted to obtain &lt;tt class="docutils literal"&gt;IA&lt;/tt&gt;, the
beginning of the actual data being transferred.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The server chooses one of the encryption methods given by &lt;tt class="docutils literal"&gt;crypto_provide&lt;/tt&gt;
to use for the rest of the connection.  Bits with unknown meanings are
ignored.  If &lt;tt class="docutils literal"&gt;crypto_provide&lt;/tt&gt; does not contain any encryption methods that
the server supports, the handshake fails.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The server sends packet 4: &lt;tt class="docutils literal"&gt;RC4(VC + crypto_select + len(PadD) + PadD)&lt;/tt&gt;,
where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;RC4(X)&lt;/tt&gt; encrypts the byte string &lt;tt class="docutils literal"&gt;X&lt;/tt&gt; by XORing it with bytes produced
by the server’s outgoing RC4 keystream.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;VC&lt;/tt&gt; is eight zero-valued bytes, the same as in packet 3.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;crypto_select&lt;/tt&gt; is a 32-bit big-endian integer with one bit set to
indicate the encryption method chosen by the server.  The bits have the
same meanings as for &lt;tt class="docutils literal"&gt;crypto_provide&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;PadD&lt;/tt&gt; is arbitrary data with a length of 0 to 512 bytes, reserved for
extending the crypto handshake in future versions.  Current implementations
may choose to set them to 0-length.  For padding-only usage in the current
version, they should be zeroed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="after-the-handshake"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;After the Handshake&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once all of the above is carried out, the MSE/PE handshake is complete, and the
client &amp;amp; server transmit the data they came here to transmit, encrypted using
the selected encryption method.  If plain text was selected, further data is
sent &amp;amp; received as-is without encryption.  If RC4 was selected, sent &amp;amp; received
data will be encrypted using the sender’s outgoing RC4 keystream and decrypted
using the receiver’s incoming RC4 keystream; these are the same keystreams as
used during the handshake, i.e., they are not reinitialized.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="bittorrent-specific-aspects"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;BitTorrent-Specific Aspects&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="detecting-encryption"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Detecting Encryption&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MSE/PE was introduced into a world where BitTorrent connections were already
being made without encryption, and many connections still aren’t encrypted, so
peers need a way to determine whether a fresh connection is encrypted or not.&lt;/p&gt;
&lt;p&gt;When a BitTorrent peer that supports MSE/PE receives an incoming connection, it
can determine whether an MSE/PE handshake is being performed by checking
whether the first 20 bytes received equal the BitTorrent handshake header
&lt;tt class="docutils literal"&gt;&amp;quot;\x13BitTorrent protocol&amp;quot;&lt;/tt&gt;; if the bytes match, the connection is (almost
certainly) not using MSE/PE, and the peer can choose to either continue the
connection unencrypted or else sever the connection.&lt;/p&gt;
&lt;p&gt;When a BitTorrent peer that supports MSE/PE makes an outgoing connection, it
has the following options, which it chooses among based on its configuration
and any broadcasts of encryption support it’s received (see below):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The peer can attempt an MSE/PE handshake; if that fails, it abandons the
remote peer.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The peer can attempt an MSE/PE handshake; if that fails, it severs the
connection and tries to reconnect without using encryption.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The peer connects without using encryption.  If the remote peer sends a &lt;a class="reference external" href="https://www.bittorrent.org/beps/bep_0010.html"&gt;BEP
10&lt;/a&gt; extended handshake containing an &lt;tt class="docutils literal"&gt;e&lt;/tt&gt; value of &lt;tt class="docutils literal"&gt;1&lt;/tt&gt;, the local peer
severs the connection and reconnects using MSE/PE.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The peer connects without using encryption and does not use MSE/PE with the
remote peer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="broadcasting-encryption-support"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Broadcasting Encryption Support&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;BitTorrent peers can broadcast their support of MSE/PE to other peers via HTTP
trackers and/or Peer Exchange.  (The UDP tracker protocol and DHT do not appear
to have any capabilities for broadcasting encryption support.)&lt;/p&gt;
&lt;p&gt;When a BitTorrent peer that supports MSE/PE makes an announcement to an HTTP
tracker, it can include one or more of the following URL query parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;supportcrypto=1&lt;/tt&gt; — Indicates that the peer can create &amp;amp; receive MSE/PE
connections&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;requirecrypto=1&lt;/tt&gt; — Indicates that the peer only creates &amp;amp; accepts MSE/PE
connections.  If the tracker supports this parameter, then this peer will not
be returned in responses to peers that do not set &lt;tt class="docutils literal"&gt;supportcrypto=1&lt;/tt&gt; or
&lt;tt class="docutils literal"&gt;requirecrypto=1&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;cryptoport=X&lt;/tt&gt; (used in combination with &lt;tt class="docutils literal"&gt;port=0&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;requirecrypto=1&lt;/tt&gt;) — If the tracker supports the &lt;tt class="docutils literal"&gt;cryptoport&lt;/tt&gt; parameter,
it will provide this peer’s port as &lt;tt class="docutils literal"&gt;X&lt;/tt&gt; in responses to other peers that
also support MSE/PE and will not provide this peer at all to peers that do
not support MSE/PE.  If the tracker does not support the &lt;tt class="docutils literal"&gt;cryptoport&lt;/tt&gt;
parameter, then this peer’s actual port will not be given out to any peers.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When &lt;tt class="docutils literal"&gt;supportcrypto=1&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;requirecrypto=1&lt;/tt&gt; is set in an announcement to a
supporting HTTP tracker, the response will include a &lt;tt class="docutils literal"&gt;crypto_flags&lt;/tt&gt; field,
the value of which is a sequence of bytes, one for each peer in &lt;tt class="docutils literal"&gt;peers&lt;/tt&gt; in
order; a given byte will be &lt;tt class="docutils literal"&gt;1&lt;/tt&gt; if the peer requires MSE/PE and &lt;tt class="docutils literal"&gt;0&lt;/tt&gt;
otherwise.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Preliminary searching on GitHub indicates that, when an HTTP tracker sends a
response with “&lt;tt class="docutils literal"&gt;peers&lt;/tt&gt;”, “&lt;tt class="docutils literal"&gt;peers6&lt;/tt&gt;”, and “&lt;tt class="docutils literal"&gt;crypto_flags&lt;/tt&gt;” fields, the
“&lt;tt class="docutils literal"&gt;crypto_flags&lt;/tt&gt;” only applies to the “&lt;tt class="docutils literal"&gt;peers&lt;/tt&gt;” field and not
“&lt;tt class="docutils literal"&gt;peers6&lt;/tt&gt;”, though I have yet to encounter a tracker that actually sends
“&lt;tt class="docutils literal"&gt;crypto_flags&lt;/tt&gt;” in the wild.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a peer prefers MSE/PE connections to unencrypted, it can indicate this to
connecting peers by including an &lt;tt class="docutils literal"&gt;e&lt;/tt&gt; field with a value of &lt;tt class="docutils literal"&gt;1&lt;/tt&gt; in the &lt;a class="reference external" href="https://www.bittorrent.org/beps/bep_0010.html"&gt;BEP
10&lt;/a&gt; extended handshakes it sends.  This &lt;tt class="docutils literal"&gt;e&lt;/tt&gt; value will then be broadcast to
other peers using Peer Exchange (&lt;a class="reference external" href="https://www.bittorrent.org/beps/bep_0011.html"&gt;BEP 11&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="references"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;References&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&amp;lt;&lt;a class="reference external" href="https://wiki.vuze.com/w/Message_Stream_Encryption"&gt;https://wiki.vuze.com/w/Message_Stream_Encryption&lt;/a&gt;&amp;gt; [&lt;a class="reference external" href="http://web.archive.org/web/20230405235517/https://wiki.vuze.com/w/Message_Stream_Encryption"&gt;Internet Archive Mirror&lt;/a&gt;]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&amp;lt;&lt;a class="reference external" href="https://css.csail.mit.edu/6.858/2018/projects/bgu-kelvinlu.pdf"&gt;https://css.csail.mit.edu/6.858/2018/projects/bgu-kelvinlu.pdf&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&amp;lt;&lt;a class="reference external" href="https://atomashpolskiy.github.io/bt/encryption/"&gt;https://atomashpolskiy.github.io/bt/encryption/&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Software"></category><category term="BitTorrent"></category><category term="encryption"></category></entry><entry><title>Converting Lists to Simple Tables and Back with rs</title><link href="https://jwodder.github.io/kbits/posts/reshaping/" rel="alternate"></link><published>2023-05-03T00:00:00-04:00</published><updated>2023-05-03T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2023-05-03:/kbits/posts/reshaping/</id><summary type="html">&lt;p class="first last"&gt;If you have a file that’s just a list of items, one item per line, and you
want to turn it into a simple table — one delimited just by whitespace
without any border characters — how would you do that?  Follow up question:
If you have a simple table, and you want to convert it into a list of
items, one per line, how would you do &lt;em&gt;that&lt;/em&gt;?  The answer to both questions
is: with the &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; command, and this article will show you how.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;If you have a file that’s just a list of items, one item per line, and you want
to turn it into a simple table — one delimited just by whitespace without any
border characters — how would you do that?  Follow up question: If you have a
simple table, and you want to convert it into a list of items, one per line,
how would you do &lt;em&gt;that&lt;/em&gt;?  The answer to both questions is: with the &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt;
command, and this article will show you how.&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; is a Unix command-line program for &lt;strong&gt;r&lt;/strong&gt;e&lt;strong&gt;s&lt;/strong&gt;haping arrays of
data.  Most Linux users can get it by installing the &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; package, and macOS
users will find it preinstalled.&lt;/p&gt;
&lt;div class="section" id="converting-a-list-of-lines-to-a-simple-table"&gt;
&lt;h2&gt;Converting a List of Lines to a Simple Table&lt;/h2&gt;
&lt;p&gt;When &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; is invoked without any options, it constructs a table from standard
input, treating each line as its own table entry, and fills in columns before
rows.  Thus, if we have the following file saved in &lt;tt class="docutils literal"&gt;lines.txt&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Dapper Drake
Edgy Eft
Feisty Fawn
Gutsy Gibbon
Hardy Heron
Intrepid Ibex
Jaunty Jackalope
Karmic Koala
Lucid Lynx
Maverick Meerkat
Natty Narwhal
Oneiric Ocelot
Precise Pangolin
Quantal Quetzal
Raring Ringtail
Saucy Salamander
Trusty Tahr
Utopic Unicorn
Vivid Vervet
Wily Werewolf
Xenial Xerus
Yakkety Yak
Zesty Zapus
&lt;/pre&gt;
&lt;p&gt;Then running &lt;tt class="docutils literal"&gt;rs &amp;lt; lines.txt&lt;/tt&gt; will produce the following output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Dapper Drake      Jaunty Jackalope  Precise Pangolin  Vivid Vervet
Edgy Eft          Karmic Koala      Quantal Quetzal   Wily Werewolf
Feisty Fawn       Lucid Lynx        Raring Ringtail   Xenial Xerus
Gutsy Gibbon      Maverick Meerkat  Saucy Salamander  Yakkety Yak
Hardy Heron       Natty Narwhal     Trusty Tahr       Zesty Zapus
Intrepid Ibex     Oneiric Ocelot    Utopic Unicorn
&lt;/pre&gt;
&lt;div class="admonition important"&gt;
&lt;p class="first admonition-title"&gt;Important&lt;/p&gt;
&lt;p class="last"&gt;When &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; is run without any arguments, it acts like it was given the
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-e&lt;/span&gt;&lt;/tt&gt; (Read one table entry from each line of input) and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-t&lt;/span&gt;&lt;/tt&gt; (Fill in
columns before rows) options.  If you specify any arguments of your own,
then &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-e&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-t&lt;/span&gt;&lt;/tt&gt; will not be in effect unless you specify them
explicitly.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; automatically determines the number of table columns based on what will
fit in an 80-character line.  To change the line length to, say, 60 characters,
pass &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-w60&lt;/span&gt;&lt;/tt&gt; to the command (No space is allowed between the option and its
argument).  To ask for a specific number of table rows and let &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; figure
out the number of columns, supply the desired number of rows as an argument,
e.g., &lt;tt class="docutils literal"&gt;rs &lt;span class="pre"&gt;-e&lt;/span&gt; &lt;span class="pre"&gt;-t&lt;/span&gt; 8 &amp;lt; lines.txt&lt;/tt&gt;.  To ask for a specific number of table
columns instead, pass a &lt;tt class="docutils literal"&gt;0&lt;/tt&gt; argument (to tell &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; “Figure the number of
rows out yourself”) followed by the desired number of columns, e.g., &lt;tt class="docutils literal"&gt;rs &lt;span class="pre"&gt;-e&lt;/span&gt; &lt;span class="pre"&gt;-t&lt;/span&gt;
0 3 &amp;lt; lines.txt&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;By default, &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; will output every column at the same width; in the example
above, this results in the first column having more padding on the right than
is strictly necessary.  The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-z&lt;/span&gt;&lt;/tt&gt; option will get rid of that padding; thus,
by running &lt;tt class="docutils literal"&gt;rs &lt;span class="pre"&gt;-e&lt;/span&gt; &lt;span class="pre"&gt;-t&lt;/span&gt; &lt;span class="pre"&gt;-z&lt;/span&gt; &amp;lt; lines.txt&lt;/tt&gt;, we get the following output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Dapper Drake   Jaunty Jackalope  Precise Pangolin  Vivid Vervet
Edgy Eft       Karmic Koala      Quantal Quetzal   Wily Werewolf
Feisty Fawn    Lucid Lynx        Raring Ringtail   Xenial Xerus
Gutsy Gibbon   Maverick Meerkat  Saucy Salamander  Yakkety Yak
Hardy Heron    Natty Narwhal     Trusty Tahr       Zesty Zapus
Intrepid Ibex  Oneiric Ocelot    Utopic Unicorn
&lt;/pre&gt;
&lt;p&gt;One thing you might not have noticed about the output is that the last line,
having fewer columns than the others, ends in several spaces to make the end
line up with the start of the last column.  &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; doesn’t have an option to
disable this extra whitespace, but if you really want to get rid of it, you can
pipe the output through &lt;tt class="docutils literal"&gt;sed &lt;span class="pre"&gt;-e&lt;/span&gt; 's/ &lt;span class="pre"&gt;*$//'&lt;/span&gt;&lt;/tt&gt; to strip all trailing spaces.&lt;/p&gt;
&lt;p&gt;Lastly, if you want the rows of the table to be filled in before the columns,
invoke &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; with the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-e&lt;/span&gt;&lt;/tt&gt; option and no &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-t&lt;/span&gt;&lt;/tt&gt; option; thus, &lt;tt class="docutils literal"&gt;rs &lt;span class="pre"&gt;-e&lt;/span&gt; &amp;lt;
lines.txt&lt;/tt&gt; gives us:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Dapper Drake      Edgy Eft          Feisty Fawn       Gutsy Gibbon
Hardy Heron       Intrepid Ibex     Jaunty Jackalope  Karmic Koala
Lucid Lynx        Maverick Meerkat  Natty Narwhal     Oneiric Ocelot
Precise Pangolin  Quantal Quetzal   Raring Ringtail   Saucy Salamander
Trusty Tahr       Utopic Unicorn    Vivid Vervet      Wily Werewolf
Xenial Xerus      Yakkety Yak       Zesty Zapus
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="converting-a-simple-table-to-a-list-of-lines"&gt;
&lt;h2&gt;Converting a Simple Table to a List of Lines&lt;/h2&gt;
&lt;p&gt;Say we have the following text saved in &lt;tt class="docutils literal"&gt;table.txt&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Dapper Drake      Jaunty Jackalope  Precise Pangolin  Vivid Vervet
Edgy Eft          Karmic Koala      Quantal Quetzal   Wily Werewolf
Feisty Fawn       Lucid Lynx        Raring Ringtail   Xenial Xerus
Gutsy Gibbon      Maverick Meerkat  Saucy Salamander  Yakkety Yak
Hardy Heron       Natty Narwhal     Trusty Tahr       Zesty Zapus
Intrepid Ibex     Oneiric Ocelot    Utopic Unicorn    Artful Aardvark
&lt;/pre&gt;
&lt;p&gt;and we want to convert this into a list of table entries, one per line, column
by column (i.e., we want &lt;tt class="docutils literal"&gt;Intrepid Ibex&lt;/tt&gt; to come before &lt;tt class="docutils literal"&gt;Jaunty Jackalope&lt;/tt&gt;
in the output).  Because the columns are separated by multiple spaces and the
table entries also contain spaces, we can’t use &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; by itself to accomplish
this.  Instead, we first use &lt;tt class="docutils literal"&gt;sed &lt;span class="pre"&gt;-e&lt;/span&gt; 's/ &lt;span class="pre"&gt;\{2,\}/\t/g'&lt;/span&gt;&lt;/tt&gt; to convert runs of two
or more spaces to tab characters, and then &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; can process the table using
tabs as the cell delimiter.&lt;/p&gt;
&lt;p&gt;Next, we have to pipe the output of &lt;tt class="docutils literal"&gt;sed&lt;/tt&gt; through two &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; invocations: the
first invocation transposes the table so that the second invocation will split
its entries apart in the correct order (For whatever reason, &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; can’t do
all this in a single invocation).  The full command line will look like this:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sed -e 's/ \{2,\}/\t/g' table.txt | rs -c -C -T | rs -c 0 1
&lt;/pre&gt;
&lt;p&gt;(The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-c&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-C&lt;/span&gt;&lt;/tt&gt; options tell &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; to use a tab as the input and output
column delimiters, respectively.)&lt;/p&gt;
&lt;p&gt;This works fine for the table above, but if the last column is short by two or
more columns, like so:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Dapper Drake      Jaunty Jackalope  Precise Pangolin  Vivid Vervet
Edgy Eft          Karmic Koala      Quantal Quetzal   Wily Werewolf
Feisty Fawn       Lucid Lynx        Raring Ringtail   Xenial Xerus
Gutsy Gibbon      Maverick Meerkat  Saucy Salamander  Yakkety Yak
Hardy Heron       Natty Narwhal     Trusty Tahr
Intrepid Ibex     Oneiric Ocelot    Utopic Unicorn
&lt;/pre&gt;
&lt;p&gt;then &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; will not do what we want by default.  When the &lt;tt class="docutils literal"&gt;rs &lt;span class="pre"&gt;-c&lt;/span&gt; &lt;span class="pre"&gt;-C&lt;/span&gt; &lt;span class="pre"&gt;-T&lt;/span&gt;&lt;/tt&gt; step
goes to transpose its input, it finds that a direct transposition would result
in the last two columns of the output being short, which &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; dislikes, and
so it decides to fix things by moving “Intrepid Ibex” (the next cell after
“Trusty Tahr”) to the cell below “Trusty Tahr” and right of “Yakkety Yak” in
the output, producing this (with tabs converted to aligned spaces to make it
easier to read):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Dapper Drake      Edgy Eft          Feisty Fawn       Gutsy Gibbon      Hardy Heron       Oneiric Ocelot
Jaunty Jackalope  Karmic Koala      Lucid Lynx        Maverick Meerkat  Natty Narwhal     Utopic Unicorn
Precise Pangolin  Quantal Quetzal   Raring Ringtail   Saucy Salamander  Trusty Tahr
Vivid Vervet      Wily Werewolf     Xenial Xerus      Yakkety Yak       Intrepid Ibex
&lt;/pre&gt;
&lt;p&gt;and then when this table is flattened with &lt;tt class="docutils literal"&gt;rs &lt;span class="pre"&gt;-c&lt;/span&gt; 0 1&lt;/tt&gt;, the output will be in
the wrong order.&lt;/p&gt;
&lt;p&gt;We can tell &lt;tt class="docutils literal"&gt;rs&lt;/tt&gt; to not do this by passing the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-n&lt;/span&gt;&lt;/tt&gt; option to the &lt;tt class="docutils literal"&gt;rs &lt;span class="pre"&gt;-c&lt;/span&gt;
&lt;span class="pre"&gt;-C&lt;/span&gt; &lt;span class="pre"&gt;-T&lt;/span&gt;&lt;/tt&gt; command, which will make it output an all-blank entry below “Trusty”
and right of “Yakkety” in the output instead of moving “Intrepid.”  However,
this blank cell will result in the final &lt;tt class="docutils literal"&gt;rs &lt;span class="pre"&gt;-c&lt;/span&gt; 0 1&lt;/tt&gt; command printing blank
lines at the end of the output; we can avoid this by stripping trailing tabs
before passing the table on.  Hence, the final command line, that works
regardless of how short the last column happens to be, is:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sed -e 's/ \{2,\}/\t/g' table.txt | rs -c -C -T -n | sed -e 's/\t*$//' | rs -c 0 1
&lt;/pre&gt;
&lt;p&gt;On the other hand, if the table we’re converting to a list that happens to be
read by going across the first row, then the second row, etc. — e.g., if it was
produced with &lt;tt class="docutils literal"&gt;rs &lt;span class="pre"&gt;-e&lt;/span&gt;&lt;/tt&gt; without the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-t&lt;/span&gt;&lt;/tt&gt; option — instead of being read by
going down the first, second, etc. column, then the whole business with &lt;tt class="docutils literal"&gt;rs &lt;span class="pre"&gt;-c&lt;/span&gt;
&lt;span class="pre"&gt;-C&lt;/span&gt; &lt;span class="pre"&gt;-T&lt;/span&gt; &lt;span class="pre"&gt;-n&lt;/span&gt;&lt;/tt&gt; and stripping trailing tabs is unnecessary, and we can turn this
table:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Dapper Drake      Edgy Eft          Feisty Fawn       Gutsy Gibbon
Hardy Heron       Intrepid Ibex     Jaunty Jackalope  Karmic Koala
Lucid Lynx        Maverick Meerkat  Natty Narwhal     Oneiric Ocelot
Precise Pangolin  Quantal Quetzal   Raring Ringtail   Saucy Salamander
Trusty Tahr       Utopic Unicorn    Vivid Vervet      Wily Werewolf
Xenial Xerus      Yakkety Yak
&lt;/pre&gt;
&lt;p&gt;into a list by just running:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sed -e 's/ \{2,\}/\t/g' table.txt | rs -c 0 1
&lt;/pre&gt;
&lt;/div&gt;
</content><category term="Software"></category><category term="rs"></category><category term="tables"></category><category term="text processing"></category><category term="Unix utilities"></category></entry><entry><title>Basics of Writing Unix Man Pages</title><link href="https://jwodder.github.io/kbits/posts/writing-manpages/" rel="alternate"></link><published>2022-11-24T00:00:00-05:00</published><updated>2026-05-22T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2022-11-24:/kbits/posts/writing-manpages/</id><summary type="html">&lt;p class="first last"&gt;A guide to the basic syntax &amp;amp; commands of Unix man pages&lt;/p&gt;
</summary><content type="html">&lt;p&gt;On Unix-like systems, the documents that one views with the &lt;tt class="docutils literal"&gt;man&lt;/tt&gt; command
(known as “man pages”) are written in a markup language called “roff” (short
for “run off”) that dates back to the pre-Unix days in the 1960’s.  roff is
technically a full-blown programming language with numerous features, but you
only need to know a very small subset in order to produce most man pages.  This
article will describe that subset so that you can go on to write man pages for
your own software.&lt;/p&gt;
&lt;p&gt;Man pages, like most roff documents, use a roff &lt;em&gt;macro package&lt;/em&gt; that defines a
set of high-level commands.  The macro package used by most man pages is,
unsurprisingly, the &lt;tt class="docutils literal"&gt;man&lt;/tt&gt; package, and that is what is covered here.  Some
man pages instead use the &lt;tt class="docutils literal"&gt;mdoc&lt;/tt&gt; package, which originated in BSD.  Modern
versions of the &lt;tt class="docutils literal"&gt;man&lt;/tt&gt; command use the &lt;tt class="docutils literal"&gt;mandoc&lt;/tt&gt; package for processing man
pages, which autodetects whether a file is written using &lt;tt class="docutils literal"&gt;man&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;mdoc&lt;/tt&gt;
and processes it accordingly.&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="#roff-syntax" id="toc-entry-1"&gt;roff Syntax&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#document-structure-commands" id="toc-entry-2"&gt;Document Structure Commands&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#font-commands" id="toc-entry-3"&gt;Font Commands&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#additional-escape-sequences" id="toc-entry-4"&gt;Additional Escape Sequences&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#select-non-ascii-characters" id="toc-entry-5"&gt;Select Non-ASCII Characters&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#special-ascii-characters" id="toc-entry-6"&gt;Special ASCII Characters&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#other" id="toc-entry-7"&gt;Other&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="#man-page-conventions" id="toc-entry-8"&gt;Man Page Conventions&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#manual-sections" id="toc-entry-9"&gt;Manual Sections&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#sections-of-a-man-page" id="toc-entry-10"&gt;Sections of a Man Page&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#other-conventions" id="toc-entry-11"&gt;Other Conventions&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="#rendering-a-man-page" id="toc-entry-12"&gt;Rendering a Man Page&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#a-sample-man-page" id="toc-entry-13"&gt;A Sample Man Page&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#further-references" id="toc-entry-14"&gt;Further References&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="roff-syntax"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;roff Syntax&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A roff file is composed of a mixture of &lt;em&gt;control lines&lt;/em&gt; — lines that start with
a &lt;em&gt;control character&lt;/em&gt;, usually a period or single-quote — and &lt;em&gt;text lines&lt;/em&gt; —
lines that do not.&lt;/p&gt;
&lt;p&gt;Control lines are commands to roff (also known as &lt;em&gt;requests&lt;/em&gt;).  They consist of
a control character &amp;amp; a command name followed by some number of space-separated
(not tab-separated!) arguments.  To include spaces in an argument, either
escape them with a backslash or enclose the entire argument in double-quotes;
to use double-quotes inside an argument, write them as &lt;tt class="docutils literal"&gt;\(dq&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;For example, the input:&lt;/p&gt;
&lt;pre class="code groff literal-block"&gt;
.&lt;span class="k"&gt;B&lt;/span&gt; &lt;span class="s"&gt;Bold&lt;/span&gt;
and brash?  More like
.&lt;span class="k"&gt;IR&lt;/span&gt; &lt;span class="s"&gt;Belongs&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; in the &amp;quot;&lt;/span&gt; &lt;span class="s"&gt;Trash.&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;contains the command &lt;tt class="docutils literal"&gt;.B&lt;/tt&gt; (for making text bold) with the argument “Bold” and
the command &lt;tt class="docutils literal"&gt;.IR&lt;/tt&gt; (for alternating between italic and roman text) with the
arguments “Belongs” (which will be italic), “ in the ” (which will be roman),
and “Trash” (which will be italic).  This is all rendered as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;strong&gt;Bold&lt;/strong&gt; and brash?  More like &lt;em&gt;Belongs&lt;/em&gt; in the &lt;em&gt;Trash.&lt;/em&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;There may be any number of spaces &amp;amp; tabs (or none at all) between the control
character and the command name, but the control character must be the first
character in the line.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;A line with just a period is ignored.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Text lines give the text that will be displayed.  They can contain &lt;em&gt;escape
sequences&lt;/em&gt;, inline commands that start with backslashes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Whitespace around escape sequences is significant and is not discarded.  The
syntax of an escape sequence allows roff to automatically determine where it
ends; for example, escape sequences starting with &lt;tt class="docutils literal"&gt;\(&lt;/tt&gt; are always followed
by two more characters to complete the sequence, and so an escape sequence
like &lt;tt class="docutils literal"&gt;\(em&lt;/tt&gt; (em-dash) can be embedded in the middle of a word:
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;foo\(embar&lt;/span&gt;&lt;/tt&gt; becomes “foo—bar”.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;To start a text line with a period, precede the period with either a
backslash or the escape sequence &lt;tt class="docutils literal"&gt;\&amp;amp;&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;To render a literal backslash in text, use the escape sequence &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;\\\\&lt;/span&gt;&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;\e&lt;/tt&gt;, or &lt;tt class="docutils literal"&gt;\(rs&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, the input from above can be rewritten using escape sequences like
so:&lt;/p&gt;
&lt;pre class="code groff literal-block"&gt;
&lt;span class="se"&gt;\fB&lt;/span&gt;Bold&lt;span class="se"&gt;\fR&lt;/span&gt; and brash?  More like &lt;span class="se"&gt;\fI&lt;/span&gt;Belongs&lt;span class="se"&gt;\fR&lt;/span&gt; in the &lt;span class="se"&gt;\fI&lt;/span&gt;Trash.&lt;span class="se"&gt;\fR&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;A comment consists of a backslash and double quote (&lt;tt class="docutils literal"&gt;\&amp;quot;&lt;/tt&gt;) and extends to the
end of the line.  A full-line comment can be formed by using the command
&lt;tt class="docutils literal"&gt;.\&amp;quot;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;A single logical line can be broken across multiple physical lines by placing a
backslash at the end of each physical line.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="document-structure-commands"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Document Structure Commands&lt;/a&gt;&lt;/h2&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.TH title section &lt;span class="pre"&gt;[footer-middle]&lt;/span&gt; &lt;span class="pre"&gt;[footer-outside]&lt;/span&gt; &lt;span class="pre"&gt;[header-middle]&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p class="first"&gt;This must be the first non-comment command in a man page, and it must appear
exactly once.  It sets the page title (which is conventionally in all-caps)
and section number for the man page (see “&lt;a class="reference internal" href="#manual-sections"&gt;Manual Sections&lt;/a&gt;” below) to the
given values, to be displayed in the form &lt;tt class="docutils literal"&gt;title(section)&lt;/tt&gt; at the left &amp;amp;
right sides of the header of the rendered manual page.&lt;/p&gt;
&lt;p&gt;The remaining three arguments are optional.  To omit an argument but still
be able to specify an argument after it, write &lt;tt class="docutils literal"&gt;\&amp;amp;&lt;/tt&gt; in place of the
omitted argument.&lt;/p&gt;
&lt;ul class="last"&gt;
&lt;li&gt;&lt;p class="first"&gt;If &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;footer-middle&lt;/span&gt;&lt;/tt&gt; is given, it will be rendered in the middle of the
footer.  This argument is usually set to the date the man page was
written.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;footer-outside&lt;/span&gt;&lt;/tt&gt; is given, it will be rendered on the left side of
the footer.  This is usually set to the version of the software being
documented.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;header-middle&lt;/span&gt;&lt;/tt&gt; is given, it will be rendered in the middle of the
header.  If it is omitted and &lt;tt class="docutils literal"&gt;section&lt;/tt&gt; is a number from 1 to 9,
certain versions of &lt;tt class="docutils literal"&gt;man&lt;/tt&gt; will supply a default value.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.SH [name]&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Start a section with the given name.  If no argument is given, the next
line will be used as the name.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.SS [name]&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Start a subsection with the given name.  If no argument is given, the next
line will be used as the name.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.LP&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;.PP&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;.P&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Paragraph break, resetting any indentation caused by the &lt;tt class="docutils literal"&gt;.TP&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;.IP&lt;/tt&gt;,
or &lt;tt class="docutils literal"&gt;.HP&lt;/tt&gt; command&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.TP [n]&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Start a labelled, indented paragraph.  The next text line after this
command is the paragraph label, and any following text lines up to the next
&lt;tt class="docutils literal"&gt;.PP&lt;/tt&gt; will be indented.  If a numeric argument is given, the paragraph
will be indented by that many columns.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.IP [text] [n]&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p class="first"&gt;Start an indented paragraph.  The text argument, if given, will be used as
the paragraph’s bullet/“tag”; this is usually the bullet escape sequence
(&lt;tt class="docutils literal"&gt;\(bu&lt;/tt&gt;), the em-dash escape sequence (&lt;tt class="docutils literal"&gt;\(em&lt;/tt&gt;), or a number followed by
a period.  If no text argument is supplied, no bullet will be present, but
the following paragraph will still be indented; this can be used to start a
new indented paragraph after an initial indented paragraph created by
&lt;tt class="docutils literal"&gt;.TP&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;.IP&lt;/tt&gt;, or &lt;tt class="docutils literal"&gt;.HP&lt;/tt&gt;.&lt;/p&gt;
&lt;p class="last"&gt;If a numeric second argument is given, the paragraph will be indented by
that many columns.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.HP [n]&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Start an indented paragraph in which the first line is not indented.  If a
numeric second argument is given, the paragraph will be indented by that
many columns.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.RS [n]&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Increase the amount of indentation until a corresponding &lt;tt class="docutils literal"&gt;.RE&lt;/tt&gt;.  If a
numeric second argument is given, the indentation will be increased by that
many columns.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.RE&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Undo the increase in indentation caused by the last &lt;tt class="docutils literal"&gt;.RS&lt;/tt&gt;&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.br&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Insert a line break&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.sp&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Skip a line&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.sp N&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Skip &lt;tt class="docutils literal"&gt;N&lt;/tt&gt; lines&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="section" id="font-commands"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Font Commands&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The following escape sequences can be used to change the font within a text
line:&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;\fB&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Change the font to bold&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;\fI&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Change the font to italic (on a terminal, underlined)&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;\fR&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Change the font to roman&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;\fP&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Change back to the previous font&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The following requests render an argument in a given font:&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.B [text]&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Renders the given text (or the text of the next line if no argument is
given) in bold with a word break before &amp;amp; after.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.I [text]&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Renders the given text (or the text of the next line if no argument is
given) in italic (on a terminal, underlined) with a word break before &amp;amp;
after.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The following commands take multiple arguments and render them in alternating
fonts.  A word break/whitespace will be inserted before &amp;amp; after the arguments,
but there will be no words breaks/whitespace inserted between the arguments.
For example, the following:&lt;/p&gt;
&lt;pre class="code groff literal-block"&gt;
This is
.&lt;span class="k"&gt;BI&lt;/span&gt; &lt;span class="s"&gt;very&lt;/span&gt; &lt;span class="s"&gt;styled&lt;/span&gt;
text.
&lt;/pre&gt;
&lt;p&gt;will render as:&lt;/p&gt;
&lt;blockquote&gt;
This is &lt;strong&gt;very&lt;/strong&gt;&lt;em&gt;styled&lt;/em&gt; text.&lt;/blockquote&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.RB text ...&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Renders the given arguments in alternating roman and bold, roman first.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.BR text ...&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Renders the given arguments in alternating bold and roman, bold first.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.RI text ...&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Renders the given arguments in alternating roman and italic/underlined,
roman first.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.IR text ...&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Renders the given arguments in alternating italic/underlined and roman,
italic/underlined first.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.BI text ...&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Renders the given arguments in alternating bold and italic/underlined, bold
first.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;.IB text ...&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Renders the given arguments in alternating italic/underlined and bold,
italic/underlined first.&lt;/dd&gt;
&lt;/dl&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Tip&lt;/p&gt;
&lt;p class="last"&gt;While modern groff lets you use these commands with any number of
arguments, traditional implementations limit usage to six arguments; keep
this in mind if you want to make your man page portable.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="additional-escape-sequences"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Additional Escape Sequences&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="select-non-ascii-characters"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Select Non-ASCII Characters&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://man7.org/linux/man-pages/man7/groff_char.7.html"&gt;&lt;tt class="docutils literal"&gt;grof_char(7)&lt;/tt&gt;&lt;/a&gt; for the complete set of available character escape sequences.&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="24%" /&gt;
&lt;col width="76%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Escape&lt;/th&gt;
&lt;th class="head"&gt;Character&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(bu&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;bullet (•)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\*R&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;registration symbol (®)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;\*(Tm&lt;/span&gt;&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;trademark symbol (™)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(co&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;copyright (©)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(em&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;em-dash (—)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(en&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;en-dash (–)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(rq&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;right double-quote (“)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(lq&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;left double-quote (”)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(oq&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;left single-quote (‘)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(cq&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;right single-quote (’)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;When viewing a man page in the terminal, not all installations will display
Unicode characters.  On systems that display man pages in ASCII (which
include macOS as of Big Sur), non-ASCII characters will be rendered as the
visually closest ASCII character where possible.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="special-ascii-characters"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Special ASCII Characters&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Some output devices transform certain ASCII input characters to similar Unicode
characters, so the following escape sequences can be used to ensure that the
desired ASCII character appears in the rendered man page:&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="22%" /&gt;
&lt;col width="78%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Escape&lt;/th&gt;
&lt;th class="head"&gt;Character&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(aq&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Apostrophe (‘)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(ga&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Grave accent (`)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(ha&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Caret/circumflex accent (^)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\(ti&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Tilde (~)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;\-&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Hyphen/minus (-)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class="section" id="other"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Other&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;A backslash followed by a space produces a non-breaking space that remains at
a fixed width when text is justified.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;\~&lt;/tt&gt; produces a non-breaking space that nevertheless stretches like a
normal inter-word space when justifying text.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;\&amp;amp;&lt;/tt&gt; produces a non-printable, zero-width character.  It can be placed next
to a token to deprive it of any special meaning; for example, it can be
placed after a period at the end of an abbreviation to prevent it from being
treated as the end of a sentence.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="man-page-conventions"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Man Page Conventions&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="manual-sections"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Manual Sections&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Each man page is traditionally placed into one of nine manual &lt;em&gt;sections&lt;/em&gt; (not
to be confused with the sections within a man page created by the &lt;tt class="docutils literal"&gt;.SH&lt;/tt&gt;
command; for that, see below).  The pages for a given section are stored
together, and the section number is also used as the file extension.  The
sections are:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Commands for use by general users&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;C system calls&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;C library functions, libraries, &amp;amp; headers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Devices, special files, and sockets&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;File formats&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Games&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Miscellaneous&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Commands for use by system administrators (including servers/daemons)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;C kernel functions&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="sections-of-a-man-page"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Sections of a Man Page&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The contents of a man page are divided into sections by the &lt;tt class="docutils literal"&gt;.SH&lt;/tt&gt; command.
Different sources give slightly different lists of the “standard” sections, but
the most common, in roughly the order they should appear in a man page, are:&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;NAME&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p class="first"&gt;Gives the name of the man page and a short description of what it
documents.  This is usually considered the only mandatory section.&lt;/p&gt;
&lt;p class="last"&gt;In order for a man page named “foobar” to be properly indexed by &lt;tt class="docutils literal"&gt;whatis&lt;/tt&gt;
and &lt;tt class="docutils literal"&gt;apropos&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;NAME&lt;/tt&gt; must be the first section in the man page, and
the &lt;tt class="docutils literal"&gt;.SH NAME&lt;/tt&gt; line must be followed immediately by a line of the form
&lt;tt class="docutils literal"&gt;foobar \- short description of foobar&lt;/tt&gt;.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;SYNOPSIS&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;&lt;p class="first"&gt;Shows the syntax for invoking a command or calling a C function.&lt;/p&gt;
&lt;p&gt;The synopsis for a command usually follows the following conventions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Text that should be entered as-is by the user (e.g., options and the name
of the command) should be in &lt;strong&gt;bold&lt;/strong&gt;, while placeholder text that should
be replaced with some value by the user (e.g., command arguments) should
be in &lt;em&gt;italics/underlined&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Optional syntax elements (e.g., most options) should be enclosed in
square brackets.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Alternative forms of a syntax element (e.g., the short and long form of
an option) should be separated by whitespace and a vertical bar.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Syntax elements that can be repeated (e.g., arguments that can be given
multiple times) are indicated by appending three periods (&lt;tt class="docutils literal"&gt;...&lt;/tt&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="last"&gt;See &lt;a class="reference internal" href="#a-sample-man-page"&gt;A Sample Man Page&lt;/a&gt; below for an example of these rules in action.&lt;/p&gt;
&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;DESCRIPTION&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;An explanation of what the command, function, etc. does&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;OPTIONS&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;A list of any command-line options a program takes and their meanings.
This list is usually created using &lt;tt class="docutils literal"&gt;.TP&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;.IP&lt;/tt&gt; to produce paragraphs
labeled with the option they describe, with each option in &lt;strong&gt;bold&lt;/strong&gt; and any
argument it may take in &lt;em&gt;italics/underlined&lt;/em&gt;.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;EXIT STATUS&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;A list of the possible exit statuses for a command and their meanings&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;ENVIRONMENT&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;A description of any environment variables that affect the command or
function&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;FILES&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;A description of any files the command uses (configuration files, startup
files, etc.).  It is recommended that file paths be styled in
&lt;em&gt;italics/underlined&lt;/em&gt;.&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;NOTES&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Any miscellaneous notes&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;BUGS&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;A list of known shortcomings in the documented software or functionality&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;EXAMPLES&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Examples of how to use the software or functionality&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;AUTHORS&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;A list of the authors of the software and/or man page&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;REPORTING BUGS&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Information on how to report any bugs found in the software&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;COPYRIGHT&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;Copyright/license details&lt;/dd&gt;
&lt;dt&gt;&lt;tt class="docutils literal"&gt;SEE ALSO&lt;/tt&gt;&lt;/dt&gt;
&lt;dd&gt;A comma-separated list of related man pages and/or other documents.
References to other man pages should be formatted with the name in bold and
the section number in roman enclosed in parentheses.&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="section" id="other-conventions"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Other Conventions&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Use &lt;tt class="docutils literal"&gt;\-&lt;/tt&gt; instead of plain &lt;tt class="docutils literal"&gt;-&lt;/tt&gt; for ASCII hyphens, e.g., in command-line
options.  Use plain &lt;tt class="docutils literal"&gt;-&lt;/tt&gt; in hyphenated words.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Blank lines are discouraged, as they may not render correctly in all output
formats.  Use the &lt;tt class="docutils literal"&gt;.sp&lt;/tt&gt; command instead to produce a blank line, or use
&lt;tt class="docutils literal"&gt;.PP&lt;/tt&gt; to start a new paragraph.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Each sentence should typically start on a new line.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Use only a single space between words in text; multiple spaces will not be
collapsed into one when rendering.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="rendering-a-man-page"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Rendering a Man Page&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To render a man page in the terminal the way that &lt;tt class="docutils literal"&gt;man&lt;/tt&gt; would, run &lt;tt class="docutils literal"&gt;man &lt;span class="pre"&gt;-l&lt;/span&gt;
path/to/man/page&lt;/tt&gt;.  (On macOS, you have to instead run &lt;tt class="docutils literal"&gt;mandoc &lt;span class="pre"&gt;-a&lt;/span&gt;
path/to/man/page&lt;/tt&gt;).  You may also want to pass the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--warnings&lt;/span&gt;&lt;/tt&gt; option
(&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-Wall&lt;/span&gt;&lt;/tt&gt; for &lt;tt class="docutils literal"&gt;mandoc&lt;/tt&gt;) in order to catch any problematic syntax.&lt;/p&gt;
&lt;p&gt;If your version of &lt;tt class="docutils literal"&gt;man&lt;/tt&gt; does not support the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-l&lt;/span&gt;&lt;/tt&gt; option, you can instead
run &lt;tt class="docutils literal"&gt;groff&lt;/tt&gt; (GNU roff, the typical roff implementation on nearly all Unix
machines nowadays) directly with &lt;tt class="docutils literal"&gt;groff &lt;span class="pre"&gt;-man&lt;/span&gt; &lt;span class="pre"&gt;-Tutf8&lt;/span&gt; path/to/man/page | less
&lt;span class="pre"&gt;-is&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Of course, groff can render to more than just terminals by changing the value
passed to the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-T&lt;/span&gt;&lt;/tt&gt; option in the &lt;tt class="docutils literal"&gt;groff&lt;/tt&gt; command.  Values of interest
include &lt;tt class="docutils literal"&gt;pdf&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;ps&lt;/tt&gt; (for PostScript), and &lt;tt class="docutils literal"&gt;html&lt;/tt&gt;; these require the
&lt;tt class="docutils literal"&gt;gropdf&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;grops&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;grohtml&lt;/tt&gt; commands, respectively, to be installed
in order to work.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="a-sample-man-page"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;A Sample Man Page&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="code groff literal-block"&gt;
.&lt;span class="k"&gt;TH&lt;/span&gt; &lt;span class="s"&gt;FOOBAR&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2022&lt;/span&gt;&lt;span class="s"&gt;-11-24&lt;/span&gt; &lt;span class="s"&gt;v1.0&lt;/span&gt;
.&lt;span class="k"&gt;SH&lt;/span&gt; &lt;span class="s"&gt;NAME&lt;/span&gt;
foobar &lt;span class="se"&gt;\-&lt;/span&gt; foo all your bars
.&lt;span class="k"&gt;SH&lt;/span&gt; &lt;span class="s"&gt;SYNOPSIS&lt;/span&gt;
.&lt;span class="k"&gt;B&lt;/span&gt; &lt;span class="s"&gt;foobar&lt;/span&gt;
[&lt;span class="se"&gt;\fB\-&lt;/span&gt;a&lt;span class="se"&gt;\fR&lt;/span&gt; &lt;span class="se"&gt;\fI&lt;/span&gt;arg&lt;span class="se"&gt;\fP&lt;/span&gt;]
.&lt;span class="k"&gt;RB&lt;/span&gt; &lt;span class="s"&gt;[&lt;/span&gt; &lt;span class="se"&gt;\-&lt;/span&gt;&lt;span class="s"&gt;f&lt;/span&gt; &lt;span class="s"&gt;|&lt;/span&gt; &lt;span class="se"&gt;\-\-&lt;/span&gt;&lt;span class="s"&gt;fu&lt;/span&gt; &lt;span class="s"&gt;]&lt;/span&gt;
.&lt;span class="k"&gt;RB&lt;/span&gt; &lt;span class="s"&gt;[&lt;/span&gt; &lt;span class="se"&gt;\-&lt;/span&gt;&lt;span class="s"&gt;xyz&lt;/span&gt; &lt;span class="s"&gt;]&lt;/span&gt;
.&lt;span class="k"&gt;IR&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;bar &amp;quot;&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
.&lt;span class="k"&gt;SH&lt;/span&gt; &lt;span class="s"&gt;DESCRIPTION&lt;/span&gt;
.&lt;span class="k"&gt;B&lt;/span&gt; &lt;span class="s"&gt;foobar&lt;/span&gt;
takes a list of one or more
.&lt;span class="k"&gt;IR&lt;/span&gt; &lt;span class="s"&gt;bar&lt;/span&gt; &lt;span class="s"&gt;s&lt;/span&gt;
and foos each of them.
.&lt;span class="k"&gt;PP&lt;/span&gt;
In detail, lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi
ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.
.&lt;span class="k"&gt;SH&lt;/span&gt; &lt;span class="s"&gt;OPTIONS&lt;/span&gt;
.&lt;span class="k"&gt;TP&lt;/span&gt;
.&lt;span class="k"&gt;BI&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;\-a &amp;quot;&lt;/span&gt; &lt;span class="s"&gt;arg&lt;/span&gt;
Put the apple at
.&lt;span class="k"&gt;IR&lt;/span&gt; &lt;span class="s"&gt;arg&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
.&lt;span class="k"&gt;TP&lt;/span&gt;
.&lt;span class="k"&gt;BR&lt;/span&gt; &lt;span class="se"&gt;\-&lt;/span&gt;&lt;span class="s"&gt;f&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;, &amp;quot;&lt;/span&gt; &lt;span class="se"&gt;\-\-&lt;/span&gt;&lt;span class="s"&gt;fu&lt;/span&gt;
Do a FUBAR instead.
.&lt;span class="k"&gt;IP&lt;/span&gt;
Note that this can permanently destroy your computer.
.&lt;span class="k"&gt;IP&lt;/span&gt; &lt;span class="se"&gt;\fB\-&lt;/span&gt;&lt;span class="s"&gt;x\fR&lt;/span&gt;
Be exact about it.
.&lt;span class="k"&gt;TP&lt;/span&gt;
.&lt;span class="k"&gt;B&lt;/span&gt; &lt;span class="s"&gt;-y&lt;/span&gt;
Be yucky about it.
.&lt;span class="k"&gt;IP&lt;/span&gt; &lt;span class="se"&gt;\fB&lt;/span&gt;&lt;span class="s"&gt;-z\fR&lt;/span&gt;
Be zucchini about it.
.&lt;span class="k"&gt;SH&lt;/span&gt; &lt;span class="s"&gt;FILES&lt;/span&gt;
.&lt;span class="k"&gt;TP&lt;/span&gt;
.&lt;span class="k"&gt;I&lt;/span&gt; &lt;span class="s"&gt;~/.cache/foo&lt;/span&gt;
This is where the bars are stored.
.&lt;span class="k"&gt;SH&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;SEE ALSO&amp;quot;&lt;/span&gt;
.&lt;span class="k"&gt;BR&lt;/span&gt; &lt;span class="s"&gt;man&lt;/span&gt; &lt;span class="s"&gt;(1),&lt;/span&gt;
.&lt;span class="k"&gt;BR&lt;/span&gt; &lt;span class="s"&gt;groff&lt;/span&gt; &lt;span class="s"&gt;(7),&lt;/span&gt;
.&lt;span class="k"&gt;BR&lt;/span&gt; &lt;span class="s"&gt;groff_man&lt;/span&gt; &lt;span class="s"&gt;(7)&lt;/span&gt;
.&lt;span class="k"&gt;PP&lt;/span&gt;
.&lt;span class="k"&gt;I&lt;/span&gt; &lt;span class="s"&gt;A&lt;/span&gt; &lt;span class="s"&gt;Brief&lt;/span&gt; &lt;span class="s"&gt;History&lt;/span&gt; &lt;span class="s"&gt;of&lt;/span&gt; &lt;span class="s"&gt;Foo&lt;/span&gt;
by Fabian Oscar Oh
.&lt;span class="k"&gt;PP&lt;/span&gt;
.&lt;span class="k"&gt;RI&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;https://www.example.com/foo/bar.html&lt;/span&gt; &lt;span class="s"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;[&lt;a class="reference external" href="https://jwodder.github.io/kbits/posts/writing-manpages/foobar.1"&gt;Download this file&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;Rendered:&lt;/p&gt;
&lt;script id="asciicast-LtGNGNNqtSYDLi72H6e8Yp1sQ" src="https://asciinema.org/a/LtGNGNNqtSYDLi72H6e8Yp1sQ.js" async data-autoplay="true" data-loop="true"&gt;&lt;/script&gt;&lt;p&gt;[&lt;a class="reference external" href="https://asciinema.org/a/LtGNGNNqtSYDLi72H6e8Yp1sQ"&gt;View animation on asciinema.org&lt;/a&gt;]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="further-references"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Further References&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;groff(7)&lt;/tt&gt; man page: &amp;lt;&lt;a class="reference external" href="https://man7.org/linux/man-pages/man7/groff.7.html"&gt;https://man7.org/linux/man-pages/man7/groff.7.html&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;groff_char(7)&lt;/tt&gt; man page: &amp;lt;&lt;a class="reference external" href="https://man7.org/linux/man-pages/man7/groff_char.7.html"&gt;https://man7.org/linux/man-pages/man7/groff_char.7.html&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;groff_man(7)&lt;/tt&gt; man page: &amp;lt;&lt;a class="reference external" href="https://man7.org/linux/man-pages/man7/groff_man.7.html"&gt;https://man7.org/linux/man-pages/man7/groff_man.7.html&lt;/a&gt;&amp;gt;&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;man-pages(7)&lt;/span&gt;&lt;/tt&gt; man page: &amp;lt;&lt;a class="reference external" href="https://man7.org/linux/man-pages/man7/man-pages.7.html"&gt;https://man7.org/linux/man-pages/man7/man-pages.7.html&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Software"></category><category term="documentation"></category><category term="groff"></category><category term="roff"></category><category term="markup"></category><category term="man pages"></category><category term="UNIX"></category><category term="Unix utilities"></category></entry><entry><title>Implementing Boolean Negation Flags with Clap</title><link href="https://jwodder.github.io/kbits/posts/clap-bool-negate/" rel="alternate"></link><published>2022-10-23T00:00:00-04:00</published><updated>2022-10-23T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2022-10-23:/kbits/posts/clap-bool-negate/</id><summary type="html">&lt;p class="first last"&gt;How to use Rust’s &lt;a class="reference external" href="https://github.com/clap-rs/clap"&gt;clap&lt;/a&gt; library to implement boolean &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--no-foo&lt;/span&gt;&lt;/tt&gt; flags that undo each other&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Rust’s &lt;a class="reference external" href="https://github.com/clap-rs/clap"&gt;clap&lt;/a&gt; library is the language’s most popular crate for parsing
command-line arguments.  Though it has many useful features, programmers used
to libraries like Python’s &lt;a class="reference external" href="https://palletsprojects.com/p/click/"&gt;Click&lt;/a&gt; may find themselves struggling to implement
one certain CLI convention: boolean flags &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--no-foo&lt;/span&gt;&lt;/tt&gt; that undo
each other.  This article will show you how to implement such flags using
clap’s &lt;tt class="docutils literal"&gt;Parser&lt;/tt&gt; derivation mode — no need to dig into the far more verbose
“builder” mode!&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;The code in this article was tested with clap 4.0.18 on Rust 1.64.0.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Tip&lt;/p&gt;
&lt;p class="last"&gt;There is currently &lt;a class="reference external" href="https://github.com/clap-rs/clap/issues/815"&gt;an open issue&lt;/a&gt; on clap’s repository asking for an
easier way to implement negation flags, but it doesn’t seem that it’ll be
resolved any time soon.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To implement two boolean flags &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--no-foo&lt;/span&gt;&lt;/tt&gt; such that the field
&lt;tt class="docutils literal"&gt;foo&lt;/tt&gt; is true when &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt; is given last and false when either no arguments
are given or when &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--no-foo&lt;/span&gt;&lt;/tt&gt; is given last, simply declare a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt;
boolean option as usual, then add a separate &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--no-foo&lt;/span&gt;&lt;/tt&gt; option, and declare
that they override each other using &lt;a class="reference external" href="https://docs.rs/clap/4.0/clap/builder/struct.Arg.html#method.overrides_with"&gt;overrides_with&lt;/a&gt;.  The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt; option
field will then end up holding the final boolean value, and the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--no-foo&lt;/span&gt;&lt;/tt&gt;
field will be unused, so put an underscore at the start of its name so that
clippy doesn’t complain.  (If you don’t want any unused fields in your
arguments struct, I’m afraid your only option is to turn to the more verbose
builder mode.)&lt;/p&gt;
&lt;p&gt;A minimal example of such code would look like this:&lt;/p&gt;
&lt;pre class="code rust literal-block"&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clap&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="cp"&gt;#[derive(Debug, Parser)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Arguments&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="sd"&gt;/// Foo all the bars
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[clap(long, overrides_with = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;_no_foo&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="sd"&gt;/// Don't foo any bars [default]
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[clap(long = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;no-foo&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;_no_foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&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;fn&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="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;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&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="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&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="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&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;Arguments&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;parse_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{opts:?} -&amp;gt; {args:?}&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;/pre&gt;
&lt;p&gt;&lt;a class="reference external" href="https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=1ca92e953973e4e2649ec1c522957455"&gt;[Link to the code on the Rust Playground]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The output from the above code is:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[&amp;quot;arg0&amp;quot;] -&amp;gt; Arguments { foo: false, _no_foo: false }
[&amp;quot;arg0&amp;quot;, &amp;quot;--foo&amp;quot;] -&amp;gt; Arguments { foo: true, _no_foo: false }
[&amp;quot;arg0&amp;quot;, &amp;quot;--no-foo&amp;quot;] -&amp;gt; Arguments { foo: false, _no_foo: true }
[&amp;quot;arg0&amp;quot;, &amp;quot;--no-foo&amp;quot;, &amp;quot;--foo&amp;quot;] -&amp;gt; Arguments { foo: true, _no_foo: false }
[&amp;quot;arg0&amp;quot;, &amp;quot;--foo&amp;quot;, &amp;quot;--no-foo&amp;quot;] -&amp;gt; Arguments { foo: false, _no_foo: true }
[&amp;quot;arg0&amp;quot;, &amp;quot;--no-foo&amp;quot;, &amp;quot;--foo&amp;quot;, &amp;quot;--no-foo&amp;quot;] -&amp;gt; Arguments { foo: false, _no_foo: true }
[&amp;quot;arg0&amp;quot;, &amp;quot;--foo&amp;quot;, &amp;quot;--no-foo&amp;quot;, &amp;quot;--foo&amp;quot;] -&amp;gt; Arguments { foo: true, _no_foo: false }
&lt;/pre&gt;
&lt;p&gt;As you can see, the value of the &lt;tt class="docutils literal"&gt;foo&lt;/tt&gt; field is true when &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt; is the
last &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo/--no-foo&lt;/span&gt;&lt;/tt&gt; option given and false otherwise.&lt;/p&gt;
&lt;p&gt;What if you want a pair of boolean flags where the default is &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt;/true
rather than &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--no-foo&lt;/span&gt;&lt;/tt&gt;/false?  This is doable, but the code can look quite a
bit confusing.  Starting with the setup above, add &lt;tt class="docutils literal"&gt;action =
&lt;span class="pre"&gt;clap::builder::ArgAction::SetFalse&lt;/span&gt;&lt;/tt&gt; to the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--no-foo&lt;/span&gt;&lt;/tt&gt; option; this will
invert the values of the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--no-foo&lt;/span&gt;&lt;/tt&gt; field, causing it to be true whenever
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt; is the option in effect and false otherwise.  But wait — that’s what
we want for the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt; field, isn’t it?  So we then swap the names of the
fields (along with any documentation comments) while preserving their &lt;tt class="docutils literal"&gt;long&lt;/tt&gt;
and/or &lt;tt class="docutils literal"&gt;short&lt;/tt&gt; attributes (which must now be given explicit values), so that
the field named &lt;tt class="docutils literal"&gt;foo&lt;/tt&gt;, now corresponding to the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--no-foo&lt;/span&gt;&lt;/tt&gt; option, will be
true when &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--foo&lt;/span&gt;&lt;/tt&gt; is given last and also when no options are given.&lt;/p&gt;
&lt;p&gt;Sample code:&lt;/p&gt;
&lt;pre class="code rust literal-block"&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ArgAction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clap&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="cp"&gt;#[derive(Debug, Parser)]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Arguments&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="sd"&gt;/// Don't foo any bars
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[clap(long = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;no-foo&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;, action = ArgAction::SetFalse)]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="sd"&gt;/// Foo all the bars [default]
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[clap(long = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;, overrides_with = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;_no_foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&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;fn&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="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;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&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="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;arg0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--no-foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;--foo&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="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&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;Arguments&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;parse_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{opts:?} -&amp;gt; {args:?}&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;/pre&gt;
&lt;p&gt;&lt;a class="reference external" href="https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=07852c0f651919961b4653b10be521a2"&gt;[Link to the code on the Rust Playground]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[&amp;quot;arg0&amp;quot;] -&amp;gt; Arguments { foo: true, _no_foo: false }
[&amp;quot;arg0&amp;quot;, &amp;quot;--foo&amp;quot;] -&amp;gt; Arguments { foo: true, _no_foo: true }
[&amp;quot;arg0&amp;quot;, &amp;quot;--no-foo&amp;quot;] -&amp;gt; Arguments { foo: false, _no_foo: false }
[&amp;quot;arg0&amp;quot;, &amp;quot;--no-foo&amp;quot;, &amp;quot;--foo&amp;quot;] -&amp;gt; Arguments { foo: true, _no_foo: true }
[&amp;quot;arg0&amp;quot;, &amp;quot;--foo&amp;quot;, &amp;quot;--no-foo&amp;quot;] -&amp;gt; Arguments { foo: false, _no_foo: false }
[&amp;quot;arg0&amp;quot;, &amp;quot;--no-foo&amp;quot;, &amp;quot;--foo&amp;quot;, &amp;quot;--no-foo&amp;quot;] -&amp;gt; Arguments { foo: false, _no_foo: false }
[&amp;quot;arg0&amp;quot;, &amp;quot;--foo&amp;quot;, &amp;quot;--no-foo&amp;quot;, &amp;quot;--foo&amp;quot;] -&amp;gt; Arguments { foo: true, _no_foo: true }
&lt;/pre&gt;
</content><category term="Programming"></category><category term="Rust"></category><category term="clap"></category><category term="command-line parsing"></category></entry><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>Special Version Control Files</title><link href="https://jwodder.github.io/kbits/posts/vcs-files/" rel="alternate"></link><published>2021-06-22T00:00:00-04:00</published><updated>2022-02-06T00:00:00-05:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2021-06-22:/kbits/posts/vcs-files/</id><summary type="html">&lt;p class="first last"&gt;A list of version control system-specific files that one may find in the
working directories of common version control systems&lt;/p&gt;
</summary><content type="html">&lt;p&gt;The following is a list of VCS-specific files that one may find in the working
directories of common version control systems.  This list is useful for, say,
knowing what files to ignore when traversing a project directory.&lt;/p&gt;
&lt;p&gt;Did I leave anything out?  &lt;a class="reference external" href="https://github.com/jwodder/kbits"&gt;Feel free to send a pull request.&lt;/a&gt;&lt;/p&gt;
&lt;table border="1" class="docutils align-center"&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;VCS&lt;/th&gt;
&lt;th class="head"&gt;File/Directory&lt;/th&gt;
&lt;th class="head"&gt;Purpose&lt;/th&gt;
&lt;th class="head"&gt;Documentation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td rowspan="5"&gt;&lt;a class="reference external" href="https://git-scm.com"&gt;Git&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;tt class="docutils literal"&gt;.git/&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Repository data&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://git-scm.com/docs/gitrepository-layout"&gt;gitrepository-layout(5)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;.gitattributes&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Defines per-path attributes&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://git-scm.com/docs/gitattributes"&gt;gitattributes(5)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;.gitignore&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Lists files to exclude from version control&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://git-scm.com/docs/gitignore"&gt;gitignore(5)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;.gitmodules&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Defines submodules&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://git-scm.com/docs/gitmodules"&gt;gitmodules(5)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;.mailmap&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Maps names &amp;amp; e-mails to canonical values&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://git-scm.com/docs/gitmailmap"&gt;gitmailmap(5)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td rowspan="4"&gt;&lt;a class="reference external" href="https://www.mercurial-scm.org"&gt;Mercurial&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;tt class="docutils literal"&gt;.hg/&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Repository data&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://www.mercurial-scm.org/wiki/FileFormats"&gt;wiki:FileFormats&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;.hgignore&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Lists files to exclude from version control&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://www.selenic.com/mercurial/hgignore.5.html"&gt;hgignore(5)&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;.hgsigs&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Contains changeset signatures from the GPG extension&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;.hgtags&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Defines tags&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td rowspan="3"&gt;&lt;a class="reference external" href="http://darcs.net"&gt;Darcs&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;tt class="docutils literal"&gt;_darcs/&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Repository data&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;.binaries&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Lists files to treat as binary &lt;a class="footnote-reference" href="#fn1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="binaries"&gt;Manual&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;.boring&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Lists files to exclude from version control &lt;a class="footnote-reference" href="#fn1" id="footnote-reference-2"&gt;[1]&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="http://darcs.net/manual/Configuring_darcs.html#SECTION00410040000000000000"&gt;Manual&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td rowspan="2"&gt;&lt;a class="reference external" href="https://bazaar.canonical.com"&gt;Bazaar&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;tt class="docutils literal"&gt;.bzr/&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Repository data&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;.bzrignore&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Lists files to exclude from version control&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="http://doc.bazaar.canonical.com/bzr.2.7/en/user-reference/ignore-help.html"&gt;bzr ignore&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a class="reference external" href="http://subversion.apache.org"&gt;Subversion&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;tt class="docutils literal"&gt;.svn/&lt;/tt&gt; or
&lt;tt class="docutils literal"&gt;_svn/&lt;/tt&gt; &lt;a class="footnote-reference" href="#fn2" id="footnote-reference-3"&gt;[2]&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Local copy of repository data &lt;a class="footnote-reference" href="#fn3" id="footnote-reference-4"&gt;[3]&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a class="reference external" href="http://cvs.nongnu.org"&gt;CVS&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;tt class="docutils literal"&gt;CVS/&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Local copy of repository data (one per directory)&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://www.gnu.org/software/trans-coord/manual/cvs/html_node/Working-directory-storage.html"&gt;Manual&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td rowspan="2"&gt;&lt;a class="reference external" href="https://www.gnu.org/software/rcs/"&gt;RCS&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;filename&lt;/em&gt;&lt;tt class="docutils literal"&gt;,v&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Version history for &lt;em&gt;filename&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;a class="reference external" href="https://www.gnu.org/software/rcs/manual/html_node/Concepts.html#RCS-file"&gt;Manual&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;tt class="docutils literal"&gt;RCS/&lt;/tt&gt;&lt;/td&gt;
&lt;td&gt;Conventional directory for storing &lt;tt class="docutils literal"&gt;*,v&lt;/tt&gt; files&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="fn1" 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;[1]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-1"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-2"&gt;2&lt;/a&gt;)&lt;/em&gt; Darcs normally stores its binaries file and boring file inside the
&lt;tt class="docutils literal"&gt;_darcs/&lt;/tt&gt; directory, but it is possible to use any file under version
control in their place; the names listed here are the conventional names for
such files.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="fn2" 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;[2]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;For compatibility with ASP.NET, Subversion will use the name &lt;tt class="docutils literal"&gt;_svn&lt;/tt&gt;
instead of &lt;tt class="docutils literal"&gt;.svn&lt;/tt&gt; if the &lt;tt class="docutils literal"&gt;SVN_ASP_DOT_NET_HACK&lt;/tt&gt; environment variable is
defined.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="fn3" 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-4"&gt;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Prior to version 1.7, Subversion placed a &lt;tt class="docutils literal"&gt;.svn&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;_svn&lt;/tt&gt; directory
in every subdirectory of the working directory under version control.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</content><category term="Software"></category><category term="Git"></category><category term="version control"></category><category term="dotfiles"></category></entry><entry><title>Integrating auto with bump2version</title><link href="https://jwodder.github.io/kbits/posts/auto-bump2version/" rel="alternate"></link><published>2021-02-11T00:00:00-05:00</published><updated>2021-02-11T00:00:00-05:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2021-02-11:/kbits/posts/auto-bump2version/</id><summary type="html">&lt;p class="first last"&gt;&lt;a class="reference external" href="https://github.com/intuit/auto"&gt;&lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;&lt;/a&gt; by Intuit lets you set up automatic creation of tags &amp;amp; releases and
population of changelogs in a GitHub project.  It takes care of determining
the version number for new releases, but, by default, it does not set the
new version number in your code.  This isn’t a problem if your project uses
something like &lt;a class="reference external" href="https://github.com/pypa/setuptools_scm"&gt;&lt;tt class="docutils literal"&gt;setuptools_scm&lt;/tt&gt;&lt;/a&gt; or &lt;a class="reference external" href="https://github.com/python-versioneer/python-versioneer"&gt;&lt;tt class="docutils literal"&gt;versioneer&lt;/tt&gt;&lt;/a&gt; to fetch the version
number from Git, but if your project’s version number is hardcoded in your
code, you’ll need another solution.  &lt;a class="reference external" href="https://github.com/c4urself/bump2version"&gt;&lt;tt class="docutils literal"&gt;bump2version&lt;/tt&gt;&lt;/a&gt; is that solution, and
it can be integrated into &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; as shown here.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;a class="reference external" href="https://github.com/intuit/auto"&gt;&lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;&lt;/a&gt; by Intuit lets you set up automatic creation of tags &amp;amp; releases and
population of changelogs in a GitHub project.  It takes care of determining the
version number for new releases, but, by default, it does not set the new
version number in your code.  This isn’t a problem if your project uses
something like &lt;a class="reference external" href="https://github.com/pypa/setuptools_scm"&gt;&lt;tt class="docutils literal"&gt;setuptools_scm&lt;/tt&gt;&lt;/a&gt; or &lt;a class="reference external" href="https://github.com/python-versioneer/python-versioneer"&gt;&lt;tt class="docutils literal"&gt;versioneer&lt;/tt&gt;&lt;/a&gt; to fetch the version number
from Git, but if your project’s version number is hardcoded in your code,
you’ll need another solution.  &lt;a class="reference external" href="https://github.com/c4urself/bump2version"&gt;&lt;tt class="docutils literal"&gt;bump2version&lt;/tt&gt;&lt;/a&gt; is that solution, and it can be
integrated into &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; as follows.&lt;/p&gt;
&lt;div class="section" id="set-up-bump2version"&gt;
&lt;h2&gt;Set up &lt;tt class="docutils literal"&gt;bump2version&lt;/tt&gt;&lt;/h2&gt;
&lt;p&gt;To make your project’s repository usable with &lt;tt class="docutils literal"&gt;bump2version&lt;/tt&gt;, create a
&lt;tt class="docutils literal"&gt;.bumpversion.cfg&lt;/tt&gt; (no “2”!) file as follows:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[bumpversion]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# Replace the value here with your project's current version number:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;current_version&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;0.1.0&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="na"&gt;commit&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;True&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# If integrating with GitHub Actions, you'll need to include &amp;quot;[skip ci]&amp;quot; in&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# the bump2version commit message in order to prevent auto from running&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# unnecessarily:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;message&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;[skip ci] Bump version: {current_version} → {new_version}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# auto will be taking care of the tagging for us, so set `tag` to False:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;tag&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;False&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;# For each file in your code that contains your project's version number,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# add a `[bumpversion:file:PATH]` section header, like so:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;[bumpversion:file:src/myproject/__init__.py]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;With this file in place and &lt;tt class="docutils literal"&gt;bump2version&lt;/tt&gt; installed, you can automatically
update your project’s version number by running &lt;tt class="docutils literal"&gt;bump2version $PART&lt;/tt&gt;, where
&lt;tt class="docutils literal"&gt;$PART&lt;/tt&gt; is the part of the version number to increase (&lt;tt class="docutils literal"&gt;major&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;minor&lt;/tt&gt;,
or &lt;tt class="docutils literal"&gt;patch&lt;/tt&gt;).&lt;/p&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://github.com/c4urself/bump2version/blob/master/README.md"&gt;the bump2version documentation&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="integrate-with-auto"&gt;
&lt;h2&gt;Integrate with &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;&lt;/h2&gt;
&lt;p&gt;I assume &lt;a class="reference external" href="https://intuit.github.io/auto/docs/welcome/getting-started"&gt;you’ve already set up auto for your repository&lt;/a&gt;.  To get &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;
to run &lt;tt class="docutils literal"&gt;bump2version&lt;/tt&gt; automatically at the right time when creating a new
release, use the &lt;a class="reference external" href="https://intuit.github.io/auto/docs/generated/exec"&gt;&lt;tt class="docutils literal"&gt;exec&lt;/tt&gt; plugin&lt;/a&gt; to register an &lt;a class="reference external" href="https://intuit.github.io/auto/docs/plugins/release-lifecycle-hooks#afterchangelog"&gt;&lt;tt class="docutils literal"&gt;afterChangelog&lt;/tt&gt;&lt;/a&gt; hook.  Add the
following to the &lt;tt class="docutils literal"&gt;&amp;quot;plugins&amp;quot;&lt;/tt&gt; field in your repository’s &lt;tt class="docutils literal"&gt;.autorc&lt;/tt&gt; file:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
{
    ...
    &amp;quot;plugins&amp;quot;: [
        ...
        [
            &amp;quot;exec&amp;quot;,
            {
                &amp;quot;afterChangelog&amp;quot;: &amp;quot;bump2version \&amp;quot;$(printf '%s\n' \&amp;quot;$ARG_0\&amp;quot; | jq -r .bump)\&amp;quot;&amp;quot;
            }
        ]
    ]
}
&lt;/pre&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Tip&lt;/p&gt;
&lt;p class="last"&gt;Despite what the &lt;tt class="docutils literal"&gt;exec&lt;/tt&gt; documentation may imply, the &lt;tt class="docutils literal"&gt;$ARG_0&lt;/tt&gt;
environment variable is a JSON object containing the payload passed to the
respective hook.  This means we must extract the semantic version part to
bump using &lt;tt class="docutils literal"&gt;jq&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="first admonition-title"&gt;Warning&lt;/p&gt;
&lt;p class="last"&gt;&lt;strong&gt;Do not&lt;/strong&gt; use &lt;tt class="docutils literal"&gt;echo&lt;/tt&gt; in place of &lt;tt class="docutils literal"&gt;printf&lt;/tt&gt; here!  The &lt;tt class="docutils literal"&gt;$ARG_0&lt;/tt&gt;
variable contains JSON containing strings with &lt;tt class="docutils literal"&gt;\n&lt;/tt&gt; escape sequences,
which &lt;tt class="docutils literal"&gt;echo&lt;/tt&gt; would convert into newlines, resulting in invalid JSON.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;With this setting in place, &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; will run &lt;tt class="docutils literal"&gt;bump2version&lt;/tt&gt; on each new
release after populating the changelog, and the commit created by
&lt;tt class="docutils literal"&gt;bump2version&lt;/tt&gt; will be the commit to receive the new version tag.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="integrate-with-github-actions"&gt;
&lt;h2&gt;Integrate with GitHub Actions&lt;/h2&gt;
&lt;p&gt;Assuming you’ve already set up a GitHub Actions workflow for running &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;
(&lt;a class="reference external" href="https://jwodder.github.io/kbits/posts/auto-post-release/"&gt;see here&lt;/a&gt; for an example), the only
addition needed to support &lt;tt class="docutils literal"&gt;bump2version&lt;/tt&gt; is to install it before running
&lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Set up Python&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/setup-python&amp;#64;v2&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;python-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'^3.6'&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Install bump2version&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;python -m pip install bump2version&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
</content><category term="Programming"></category><category term="GitHub Actions"></category><category term="auto"></category><category term="bump2version"></category><category term="continuous integration"></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>Running Extra Steps after Releasing with auto in GitHub Actions</title><link href="https://jwodder.github.io/kbits/posts/auto-post-release/" rel="alternate"></link><published>2020-10-26T00:00:00-04:00</published><updated>2024-05-22T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2020-10-26:/kbits/posts/auto-post-release/</id><summary type="html">&lt;p class="first last"&gt;Let’s say you’ve set up &lt;a class="reference external" href="https://github.com/intuit/auto"&gt;&lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;&lt;/a&gt; for your project via a GitHub Actions
workflow, and now you want that workflow to carry out additional steps —
such as building &amp;amp; uploading assets — whenever &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; creates a new
release.  Let’s also say that none of the available plugins for &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;
covers your use-case and you’re not a JavaScript programmer, so you won’t
be writing a new plugin to do what you want.  How do you adjust your GitHub
Actions workflow to run these extra steps at the right time?  Read to find
out.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Let’s say you’ve set up &lt;a class="reference external" href="https://github.com/intuit/auto"&gt;&lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;&lt;/a&gt; for your project via a GitHub Actions workflow,
and now you want that workflow to carry out additional steps — such as building
&amp;amp; uploading assets — whenever &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; creates a new release.  Let’s also say
that none of the available plugins for &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; covers your use-case and you’re
not a JavaScript programmer, so you won’t be writing a new plugin to do what
you want.  How do you adjust your GitHub Actions workflow to run these extra
steps at the right time?  Read on to find out.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;p&gt;So you’ve got a GitHub Actions workflow for &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; already set up.
Presumably, it looks something liks this:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Auto-release on PR merge&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c1"&gt;# This is the closest thing to triggering on a PR merge, as long as you&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c1"&gt;# don't push directly to master.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;master&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;auto-release&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;!contains(github.event.head_commit.message,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'ci&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;skip')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;!contains(github.event.head_commit.message,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'skip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ci')&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Checkout source&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/checkout&amp;#64;v4&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nt"&gt;fetch-depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;0&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Download latest auto&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;auto_download_url=&amp;quot;$(curl -fsSL https://api.github.com/repos/intuit/auto/releases/latest | jq -r '.assets[] | select(.name == &amp;quot;auto-linux.gz&amp;quot;) | .browser_download_url')&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;wget -O- &amp;quot;$auto_download_url&amp;quot; | gunzip &amp;gt; ~/auto&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;chmod a+x ~/auto&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Create release&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;~/auto shipit&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nt"&gt;GH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now you want to insert further steps that will be triggered whenever &lt;tt class="docutils literal"&gt;auto
shipit&lt;/tt&gt; successfully creates a new release.&lt;/p&gt;
&lt;p&gt;For simple cases — where the commands to run can be expressed in a single shell
command — we can use &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;’s &lt;a class="reference external" href="https://intuit.github.io/auto/docs/generated/exec"&gt;&lt;tt class="docutils literal"&gt;exec&lt;/tt&gt; plugin&lt;/a&gt; to run the desired commands via
the &lt;tt class="docutils literal"&gt;afterRelease&lt;/tt&gt; hook.  For example, building &amp;amp; uploading a Python package
for PyPI can be integrated into &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; by adding the following item to the
&lt;tt class="docutils literal"&gt;&amp;quot;plugins&amp;quot;&lt;/tt&gt; field in the repository’s &lt;tt class="docutils literal"&gt;.autorc&lt;/tt&gt; file:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
{
    ...
    &amp;quot;plugins&amp;quot;: [
        ...
        [
            &amp;quot;exec&amp;quot;,
            {
                &amp;quot;afterRelease&amp;quot;: &amp;quot;python -m build &amp;amp;&amp;amp; twine upload/*&amp;quot;
            }
        ]
    ]
}
&lt;/pre&gt;
&lt;p&gt;(This particular example assumes that the appropriate Python dependencies are
already set up earlier in the workflow and that the twine username &amp;amp; password
are passed as environment variables to the &lt;tt class="docutils literal"&gt;~/auto shipit&lt;/tt&gt; step.)&lt;/p&gt;
&lt;p&gt;For more complex post-release activity which can only be implemented as GitHub
Actions steps, we need something else.  Just adding the steps and nothing else
directly to the workflow won’t work, as &lt;tt class="docutils literal"&gt;auto shipit&lt;/tt&gt; doesn’t always create a
new release, such as when a pull request with a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;skip-release&lt;/span&gt;&lt;/tt&gt; label is
merged, or when a pull request without a &lt;tt class="docutils literal"&gt;release&lt;/tt&gt; label is merged while
&lt;tt class="docutils literal"&gt;onlyPublishWithReleaseLabel&lt;/tt&gt; is set to &lt;tt class="docutils literal"&gt;true&lt;/tt&gt;.  So we need some logic to
test whether there’s a new release.&lt;/p&gt;
&lt;p&gt;Theoretically, one option would be to create a separate workflow that runs
whenever a new tag is pushed or a new GitHub release is created, but this won’t
work with an out-of-the-box setup; &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; uses &lt;tt class="docutils literal"&gt;GITHUB_TOKEN&lt;/tt&gt; to create the
tag &amp;amp; release, and GitHub Actions workflows &lt;a class="reference external" href="https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow"&gt;specifically do not trigger&lt;/a&gt; on
events performed with a &lt;tt class="docutils literal"&gt;GITHUB_TOKEN&lt;/tt&gt;.  You could get this approach to work
by passing &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; a personal access token instead of &lt;tt class="docutils literal"&gt;GITHUB_TOKEN&lt;/tt&gt;, but
there’s a more direct way to make this work instead that also lets you keep
your release-related workflow steps in a single file.&lt;/p&gt;
&lt;p&gt;Here’s the key trick: By running &lt;a class="reference external" href="https://intuit.github.io/auto/docs/generated/version"&gt;&lt;tt class="docutils literal"&gt;auto version&lt;/tt&gt;&lt;/a&gt; before &lt;tt class="docutils literal"&gt;auto shipit&lt;/tt&gt;, you
find out whether &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; is about to create a new release, and you can save
the output from &lt;tt class="docutils literal"&gt;auto version&lt;/tt&gt; to use to trigger extra steps later.  If
&lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; is about to create a new release, &lt;tt class="docutils literal"&gt;auto version&lt;/tt&gt; will output the
release level (”&lt;tt class="docutils literal"&gt;patch&lt;/tt&gt;”, “&lt;tt class="docutils literal"&gt;minor&lt;/tt&gt;”, or “&lt;tt class="docutils literal"&gt;major&lt;/tt&gt;”); otherwise, if &lt;tt class="docutils literal"&gt;auto
shipit&lt;/tt&gt; would do nothing, &lt;tt class="docutils literal"&gt;auto version&lt;/tt&gt; just outputs an empty line.&lt;/p&gt;
&lt;p&gt;Hence, insert the following step before the &lt;tt class="docutils literal"&gt;auto shipit&lt;/tt&gt; step:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Check whether a release is due&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;auto-version&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;version=&amp;quot;$(~/auto version)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;echo &amp;quot;version=$version&amp;quot; &amp;gt;&amp;gt; &amp;quot;$GITHUB_OUTPUT&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;GH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Here, we use a &lt;a class="reference external" href="https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter"&gt;workflow command&lt;/a&gt; to make the output from &lt;tt class="docutils literal"&gt;auto version&lt;/tt&gt;
available to subsequent steps.  Later steps can then be configured to only run
if a new release is being made by adding an &lt;a class="reference external" href="https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsif"&gt;&lt;tt class="docutils literal"&gt;if&lt;/tt&gt; field&lt;/a&gt; to them, like so:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Build asset for new release&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;steps.auto-version.outputs.version != ''&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you have multiple steps that you want to run after a release, adding an
&lt;tt class="docutils literal"&gt;if&lt;/tt&gt; field to all of them can become excessive; isn’t there a way to apply an
&lt;tt class="docutils literal"&gt;if&lt;/tt&gt; to a whole block of steps?  There is indeed; you can split off the extra
steps into a separate job in the same workflow and have that entire job be
guarded by a single &lt;tt class="docutils literal"&gt;if&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;First, in order to make the output from the &lt;tt class="docutils literal"&gt;auto version&lt;/tt&gt; step available to
other jobs in the workflow, you need to add an &lt;a class="reference external" href="https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idoutputs"&gt;&lt;tt class="docutils literal"&gt;outputs&lt;/tt&gt; field&lt;/a&gt; to the original
&lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; job (the one that in the example above is named “&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;auto-release&lt;/span&gt;&lt;/tt&gt;”),
at the same level as the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;runs-on&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;steps&lt;/tt&gt; keys.  This &lt;tt class="docutils literal"&gt;outputs&lt;/tt&gt;
field should contain a YAML object mapping a name for the output value to a
&lt;tt class="docutils literal"&gt;${{ &lt;span class="pre"&gt;steps.….outputs.…&lt;/span&gt; }}&lt;/tt&gt; expression that evaluates to the output from the
&lt;tt class="docutils literal"&gt;auto version&lt;/tt&gt; step.  For the example workflow configurations shown so far,
this would mean a configuration like the following:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;auto-release&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;!contains(github.event.head_commit.message,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'ci&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;skip')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;!contains(github.event.head_commit.message,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'skip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ci')&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;### vv Add this bit vv ###&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nt"&gt;auto-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;${{ steps.auto-version.outputs.version }}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;### ^^ Add this bit ^^ ###&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;With this in place, a new job can be added to the workflow containing all the
steps you want to run after a new release is made.  This new job needs two
special fields (at the same level as &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;runs-on&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;steps&lt;/tt&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;A &lt;a class="reference external" href="https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idneeds"&gt;&lt;tt class="docutils literal"&gt;needs&lt;/tt&gt; field&lt;/a&gt; containing the job ID of the &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; job (so &lt;tt class="docutils literal"&gt;needs:
&lt;span class="pre"&gt;auto-release&lt;/span&gt;&lt;/tt&gt; for the examples given here) to declare a dependency on it&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;An &lt;tt class="docutils literal"&gt;if&lt;/tt&gt; field containing an expression of the form
&lt;tt class="docutils literal"&gt;needs.AUTO_JOB_NAME.outputs.AUTO_VERSION_OUTPUT_NAME != ''&lt;/tt&gt; (so &lt;tt class="docutils literal"&gt;if:
&lt;span class="pre"&gt;needs.auto-release.outputs.auto-version&lt;/span&gt; != ''&lt;/tt&gt; for the examples given here);
this causes the job to be skipped if &lt;tt class="docutils literal"&gt;auto version&lt;/tt&gt; outputs nothing, i.e.,
if no release is made&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The configuration for this new job would then look like:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="c1"&gt;# `auto release` job from above omitted&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nt"&gt;build-and-publish&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;needs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;auto-release&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;needs.auto-release.outputs.auto-version != ''&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;There’s one more thing to be aware of: If you check out your repository in this
new job, by default the HEAD will be the commit that triggered the workflow
originally and will not include the changelog commit or tag created by
&lt;tt class="docutils literal"&gt;auto&lt;/tt&gt;.  If you need the commit or tag (say, because your project uses
&lt;a class="reference external" href="https://pypi.org/project/setuptools-scm/"&gt;&lt;tt class="docutils literal"&gt;setuptools_scm&lt;/tt&gt;&lt;/a&gt; or the like to derive its version number from Git tags at
build time), you can tell the &lt;tt class="docutils literal"&gt;actions/checkout&lt;/tt&gt; action to check out the
latest commit from the repository by passing the default branch as the &lt;tt class="docutils literal"&gt;ref&lt;/tt&gt;
input like so:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Checkout source&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/checkout&amp;#64;v4&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;master&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# or `main` or whatever your default branch is&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c1"&gt;# This setting is needed to fetch tags:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;fetch-depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;0&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This does come with a caveat, though: in the event that multiple commits or
merges to the default branch were made in quick succession, you may end up
checking out a later commit than the tag that &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; created.  If this is a
problem, one way to deal with it is to specifically check out the tag for the
latest GitHub release, like so:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Get tag of latest release&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;latest-release&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;latest_tag=&amp;quot;$(curl -fsSL https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest | jq -r .tag_name)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;echo &amp;quot;tag=$latest_tag&amp;quot; &amp;gt;&amp;gt; &amp;quot;$GITHUB_OUTPUT&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Checkout source&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/checkout&amp;#64;v4&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;${{ steps.latest-release.outputs.tag }}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;fetch-depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;0&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This, of course, fails if &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; creates multiple tags in quick succession.
I’m not aware of a decent way to deal with this eventuality; how about
&lt;a class="reference external" href="https://intuit.github.io/auto/docs/welcome/quick-merge"&gt;listening to the docs&lt;/a&gt; and just not running &lt;tt class="docutils literal"&gt;auto&lt;/tt&gt; that often in the first
place?&lt;/p&gt;
&lt;p&gt;Using all of these tricks, your final workflow configuration should look
something like this:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Auto-release on PR merge&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c1"&gt;# This is the closest thing to triggering on a PR merge, as long as you&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c1"&gt;# don't push directly to master.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;master&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;auto-release&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;!contains(github.event.head_commit.message,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'ci&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;skip')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;!contains(github.event.head_commit.message,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'skip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ci')&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nt"&gt;auto-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;${{ steps.auto-version.outputs.version }}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Checkout source&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/checkout&amp;#64;v4&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nt"&gt;fetch-depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;0&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Download latest auto&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;auto_download_url=&amp;quot;$(curl -fsSL https://api.github.com/repos/intuit/auto/releases/latest | jq -r '.assets[] | select(.name == &amp;quot;auto-linux.gz&amp;quot;) | .browser_download_url')&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;wget -O- &amp;quot;$auto_download_url&amp;quot; | gunzip &amp;gt; ~/auto&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;chmod a+x ~/auto&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Check whether a release is due&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;auto-version&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;version=&amp;quot;$(~/auto version)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;echo &amp;quot;version=$version&amp;quot; &amp;gt;&amp;gt; &amp;quot;$GITHUB_OUTPUT&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nt"&gt;GH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Create release&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;~/auto shipit&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nt"&gt;GH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nt"&gt;build-and-publish&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;needs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;auto-release&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;needs.auto-release.outputs.auto-version != ''&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Get tag of latest release&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;latest-release&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;latest_tag=&amp;quot;$(curl -fsSL https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest | jq -r .tag_name)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;echo &amp;quot;tag=$latest_tag&amp;quot; &amp;gt;&amp;gt; &amp;quot;$GITHUB_OUTPUT&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Checkout source&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/checkout&amp;#64;v4&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nt"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;${{ steps.latest-release.outputs.tag }}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nt"&gt;fetch-depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;0&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="c1"&gt;# Remaining steps go here&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content><category term="Programming"></category><category term="GitHub Actions"></category><category term="auto"></category><category term="continuous integration"></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>The Sum of Raising the First \(n\) Integers to a Given Power</title><link href="https://jwodder.github.io/kbits/posts/powsum/" rel="alternate"></link><published>2020-08-13T00:00:00-04:00</published><updated>2020-08-13T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2020-08-13:/kbits/posts/powsum/</id><summary type="html">&lt;p class="first last"&gt;How to derive the closed-form expression for &lt;span class="math"&gt;\(\sum_{i=1}^n i^m\)&lt;/span&gt; for a
given &lt;span class="math"&gt;\(m\)&lt;/span&gt; using the formulas for all lesser &lt;span class="math"&gt;\(m\)&lt;/span&gt;’s&lt;/p&gt;
</summary><content type="html">&lt;p&gt;The closed-form expression for &lt;span class="math"&gt;\(\sum_{i=1}^n i^m\)&lt;/span&gt; for a given
&lt;span class="math"&gt;\(m\in\mathbb{Z}^+\)&lt;/span&gt; can be derived — once we know the formulas for all
lesser &lt;span class="math"&gt;\(m\)&lt;/span&gt;’s — as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;First, observe that:&lt;/p&gt;
&lt;div class="math"&gt;
\begin{align*}
n^{m+1} &amp;amp; = n^{m+1} - (n-1)^{m+1} \\
        &amp;amp; + (n-1)^{m+1} - (n-2)^{m+1} \\
        &amp;amp; + (n-2)^{m+1} - (n-3)^{m+1} \\
        &amp;amp; + \cdots \\
        &amp;amp; + 2^{m+1} - 1^{m+1} \\
        &amp;amp; + 1^{m+1} - 0^{m+1} \\
        &amp;amp; = \sum_{i=1}^n (i^{m+1} - (i-1)^{m+1})
\end{align*}
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Expand &lt;span class="math"&gt;\(i^{m+1} - (i-1)^{m+1}\)&lt;/span&gt; for the &lt;span class="math"&gt;\(m\)&lt;/span&gt; in question and use
the linear transformation nature of summation to rewrite the right-hand side
of &lt;span class="math"&gt;\(n^{m+1} = \sum_{i=1}^n (i^{m+1} - (i-1)^{m+1})\)&lt;/span&gt; as a sum of
summations of &lt;span class="math"&gt;\(i^k\)&lt;/span&gt;’s.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Isolate the &lt;span class="math"&gt;\(\sum_{i=1}^n i^m\)&lt;/span&gt; term of the equation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Substitute the closed-form expressions for the remaining &lt;span class="math"&gt;\(\sum_{i=1}^n
i^k\)&lt;/span&gt; terms.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, once we know that &lt;span class="math"&gt;\(\sum_{i=1}^n i = \frac{n(n+1)}{2}\)&lt;/span&gt; and
&lt;span class="math"&gt;\(\sum_{i=1}^n i^2 = \frac{n(n+1)(2n+1)}{6}\)&lt;/span&gt;, we can derive
&lt;span class="math"&gt;\(\sum_{i=1}^n i^3\)&lt;/span&gt; as follows:&lt;/p&gt;
&lt;div class="math"&gt;
\begin{align*}
n^4 &amp;amp; = \sum_{i=1}^n (i^4 - (i-1)^4) \\
    &amp;amp; = \sum_{i=1}^n (4i^3 - 6i^2 + 4i - 1) \\
    &amp;amp; = 4\sum_{i=1}^n i^3 - 6\sum_{i=1}^n i^2 + 4\sum_{i=1}^n i - n \\
\sum_{i=1}^n i^3
    &amp;amp; = \frac{1}{4} (n^4 + 6\sum_{i=1}^n i^2 - 4\sum_{i=1}^n i + n) \\
    &amp;amp; = \frac{1}{4} (n^4 + 6\times\frac{n(n+1)(2n+1)}{6} - 4\times\frac{n(n+1)}{2} + n)\\
    &amp;amp; = \frac{1}{4} (n^4 + 2n^3 + n^2)
\end{align*}
&lt;/div&gt;
</content><category term="Mathematics"></category><category term="summations"></category></entry><entry><title>All About reStructuredText Hyperlinks</title><link href="https://jwodder.github.io/kbits/posts/rst-hyperlinks/" rel="alternate"></link><published>2020-07-28T00:00:00-04:00</published><updated>2020-07-28T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2020-07-28:/kbits/posts/rst-hyperlinks/</id><summary type="html">&lt;p class="first last"&gt;Writing the various hyperlink syntaxes in reStructuredText, along with
internal hyperlinks and styling link text&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;a class="reference external" href="https://docutils.sourceforge.io/rst.html"&gt;reStructuredText&lt;/a&gt; offers a number of different ways to write hyperlinks, but
keeping track of all of them and their gotchas isn’t easy, and the information
is scattered around the spec.  This document aims to summarize all of the
hyperlink-related information from the &lt;a class="reference external" href="https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html"&gt;reStructuredText Markup Specification&lt;/a&gt;
in one (hopefully) well-organized place.&lt;/p&gt;
&lt;p&gt;This document describes reStructuredText hyperlinks as of &lt;a class="reference external" href="https://docutils.sourceforge.io"&gt;Docutils&lt;/a&gt; version
0.16, the latest version at time of writing.&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="#standalone-hyperlinks" id="toc-entry-1"&gt;Standalone Hyperlinks&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#embedded-uri-hyperlinks" id="toc-entry-2"&gt;Embedded URI Hyperlinks&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#embedded-alias-hyperlinks-and-hyperlink-targets" id="toc-entry-3"&gt;Embedded Alias Hyperlinks and Hyperlink Targets&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#named-hyperlink-references" id="toc-entry-4"&gt;Named Hyperlink References&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#anonymous-hyperlinks" id="toc-entry-5"&gt;Anonymous Hyperlinks&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#embedded-uri-hyperlinks-and-automatic-reference-names" id="toc-entry-6"&gt;Embedded URI Hyperlinks and Automatic Reference Names&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#gotcha-duplicate-link-text" id="toc-entry-7"&gt;Gotcha: Duplicate Link Text&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="#embedded-alias-hyperlinks-and-automatic-reference-names" id="toc-entry-8"&gt;Embedded Alias Hyperlinks and Automatic Reference Names&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#intra-document-links" id="toc-entry-9"&gt;Intra-Document Links&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#internal-hyperlink-targets" id="toc-entry-10"&gt;Internal Hyperlink Targets&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#named-directives" id="toc-entry-11"&gt;Named Directives&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#inline-internal-targets" id="toc-entry-12"&gt;Inline Internal Targets&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#implicit-hyperlink-targets-for-section-titles" id="toc-entry-13"&gt;Implicit Hyperlink Targets for Section Titles&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="#chaining-hyperlink-targets" id="toc-entry-14"&gt;Chaining Hyperlink Targets&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#styling-link-text" id="toc-entry-15"&gt;Styling Link Text&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#link-text-within-a-word" id="toc-entry-16"&gt;Link Text within a Word&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="standalone-hyperlinks"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Standalone Hyperlinks&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Firstly, reStructuredText supports &lt;em&gt;standalone hyperlinks&lt;/em&gt; — just a bare URI
(including a scheme) or e-mail address without any link text:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Go to http://www.example.com to see something neat!&lt;span class="w"&gt;

&lt;/span&gt;E-mail me at me&amp;#64;example.com.
&lt;/pre&gt;
&lt;p&gt;The above renders as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Go to &lt;a class="reference external" href="http://www.example.com"&gt;http://www.example.com&lt;/a&gt; to see something neat!&lt;/p&gt;
&lt;p&gt;E-mail me at &lt;a class="reference external" href="mailto:me&amp;#64;example.com"&gt;me&amp;#64;example.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note that, unlike Markdown, angle brackets are not required around standalone
hyperlinks, and if you do include angle brackets, the brackets will be present
in the rendered output.&lt;/p&gt;
&lt;p&gt;Also note that the scheme is required in order for a URI to be recognized as a
standalone hyperlink.  The domains names in the following will &lt;em&gt;not&lt;/em&gt; be
converted to hyperlinks:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Go to www.example.com — or to &amp;lt;www.example.org&amp;gt;!
&lt;/pre&gt;
&lt;p&gt;If you want a hyperlink that links to &lt;tt class="docutils literal"&gt;www.example.com&lt;/tt&gt; without a scheme and
uses the address as the link text, you can either write out the link the long
way as an &lt;a class="reference internal" href="#embedded-uri-hyperlinks"&gt;embedded URI hyperlink with link text&lt;/a&gt;,
or you can use embedded URI syntax without any link text, in which case the URI
becomes the link text.  For example:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Go to &lt;span class="s"&gt;`&amp;lt;www.example.com&amp;gt;`_&lt;/span&gt;.
&lt;/pre&gt;
&lt;p&gt;renders as:&lt;/p&gt;
&lt;blockquote&gt;
Go to &lt;a class="reference external" href="www.example.com"&gt;www.example.com&lt;/a&gt;.&lt;/blockquote&gt;
&lt;p&gt;This isn’t very useful for linking to domains, but it can be useful when you
want a link to a page in the same directory with the page filename used as the
link text:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
See &lt;span class="s"&gt;`&amp;lt;other_page.html&amp;gt;`_&lt;/span&gt; for other stuff.
&lt;/pre&gt;
&lt;p&gt;Rendered:&lt;/p&gt;
&lt;blockquote&gt;
See &lt;a class="reference external" href="other_page.html"&gt;other_page.html&lt;/a&gt; for other stuff.&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section" id="embedded-uri-hyperlinks"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Embedded URI Hyperlinks&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want to create a hyperlink with link text, the most straightforward way
to do so is with the &lt;em&gt;embedded URI&lt;/em&gt; syntax:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Here is &lt;span class="s"&gt;`a link &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;http://www.example.com&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt; to somewhere.
&lt;/pre&gt;
&lt;p&gt;This renders as:&lt;/p&gt;
&lt;blockquote&gt;
Here is &lt;a class="reference external" href="http://www.example.com"&gt;a link&lt;/a&gt; to somewhere.&lt;/blockquote&gt;
&lt;p&gt;The syntax consists of a backtick, the link text (with any embedded backticks
escaped with backslashes), whitespace, the target URI or e-mail address inside
angle brackets, another backtick, and a single underscore.  If the URI ends
with an underscore, the underscore must be preceded by a backslash in order to
not be parsed as an &lt;a class="reference internal" href="#embedded-alias"&gt;embedded alias&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note that link text is treated literally rather than processed for any inline
markup.  See “&lt;a class="reference internal" href="#styling-link-text"&gt;Styling Link Text&lt;/a&gt;” below for a way around this.&lt;/p&gt;
&lt;p&gt;There is a gotcha you may run into when defining two embedded URI hyperlinks
with the same link text but different URIs; &lt;a class="reference internal" href="#gotcha"&gt;see below for more information&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="embedded-alias-hyperlinks-and-hyperlink-targets"&gt;
&lt;span id="embedded-alias"&gt;&lt;/span&gt;&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Embedded Alias Hyperlinks and Hyperlink Targets&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If the URI is lengthy, or if you want to link to the same location more than
once, you may want to use an &lt;em&gt;embedded alias&lt;/em&gt;.  In this form, instead of
specifying the URI next to the link text, you specify a &lt;em&gt;hyperlink reference&lt;/em&gt;
containing a &lt;em&gt;reference name&lt;/em&gt;, and then you specify elsewhere (in a &lt;em&gt;hyperlink
target&lt;/em&gt;) what URI the reference name points to.  For example:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Here is &lt;span class="s"&gt;`a link &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;link_target_&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt; to somewhere.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_link_target:&lt;/span&gt; http://www.example.com
&lt;/pre&gt;
&lt;p&gt;Rendered:&lt;/p&gt;
&lt;blockquote&gt;
Here is &lt;a class="reference external" href="http://www.example.com"&gt;a link&lt;/a&gt; to somewhere.&lt;/blockquote&gt;
&lt;p&gt;This syntax consists of two parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;At the location in the text where you want the link to appear, write a
backtick, the link text (with embedded backticks escaped), whitespace, a
reference name followed by an underscore and encased in angle brackets,
another backtick, and another underscore.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The reference name can be any sequence of characters, though if it contains
any backticks or angle brackets, or begins or ends with space characters,
the characters in question will need to be escaped with backslashes when
using the name in an embedded alias link.&lt;/p&gt;
&lt;p&gt;When comparing two reference names for equality, runs of whitespace are
normalized to a single space, and alphabetic characters are converted to
lowercase.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul id="target"&gt;
&lt;li&gt;&lt;p class="first"&gt;Elsewhere in the reStructuredText document (either before or after the
hyperlink reference), write a &lt;em&gt;(external) hyperlink target&lt;/em&gt; on a line of its
own: optional whitespace, two periods, a space, an underscore, the same
reference name as before (&lt;em&gt;without&lt;/em&gt; the trailing underscore from before), a
colon, whitespace, and then the URI or e-mail address that the link should
point to.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;If the reference name contains any colons or is just a single underscore,
you must either escape the characters in question or else enclose the
reference name in backticks (in which case any backticks in the reference
name need to be escaped).  Either way, any leading or trailing space
characters or backticks in the reference name need to be escaped as well.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If the URI contains any space characters or ends with an underscore, the
characters in question will need to be escaped with backslashes.&lt;/p&gt;
&lt;/li&gt;
&lt;li id="multiline"&gt;&lt;p class="first"&gt;The reference name and the URI may be on the same line, or you can put them
on separate lines, in which case the URI must be indented relative to the
two periods and there must be no intervening blank lines.  The URI may even
span multiple lines, in which case the lines are concatenated and any
whitespace in the URI that isn’t escaped is discarded.  For example, the
following hyperlink targets all map to the same URI:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_one-liner:&lt;/span&gt; http://docutils.sourceforge.net/rst.html&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_starts-on-this-line:&lt;/span&gt; http://&lt;span class="w"&gt;
&lt;/span&gt;   docutils.sourceforge.net/rst.html&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_entirely-below:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   http://docutils.&lt;span class="w"&gt;
&lt;/span&gt;   sourceforge.net/rst.html
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If the same reference name is used for two or more hyperlink targets with
different URIs, a warning is produced, and the reference name will be
unusable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Hyperlink reference names, footnote labels, and citation labels share the
same namespace.  This means you can link to a footnote or citation by its
label, but it also means that you can’t define a reference name that is the
same as a footnote or citation label.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once a reference name is defined in a hyperlink target, the same reference name
can be used in any number of embedded alias links to create multiple hyperlinks
to the same destination.&lt;/p&gt;
&lt;p&gt;As with embedded URI hyperlinks, link text is treated literally rather than
processed for any inline markup.  See “&lt;a class="reference internal" href="#styling-link-text"&gt;Styling Link Text&lt;/a&gt;” below for a way
around this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="named-hyperlink-references"&gt;
&lt;span id="named-hyperlink-reference"&gt;&lt;/span&gt;&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Named Hyperlink References&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We can simplify embedded aliases one step further and use the link text as the
reference name.  Simply omit the part in angle brackets:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Here is &lt;span class="s"&gt;`a link`_&lt;/span&gt; to somewhere.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_a link:&lt;/span&gt; http://www.example.com
&lt;/pre&gt;
&lt;p&gt;If the link text ends with text inside angle brackets, at least one of the
angle brackets needs to be escaped — or an escaped space character should be
added to the end of the link text — in order to prevent the link from being
parsed as an embedded URI or alias hyperlink.&lt;/p&gt;
&lt;p id="simple-reference-name"&gt;This gets even simpler if the link text is a &lt;em&gt;simple reference name&lt;/em&gt; — a single
word (no whitespace) consisting only of letters, numbers, hyphens, underscores,
periods, colons, and/or plus signs, with no punctuation at the beginning or
end, and with no occurrences of two or more punctuation characters in a row.  A
simple reference name can be written with just the trailing underscore, no
backticks:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
This following word_ is a hyperlink.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_word:&lt;/span&gt; https://www.example.com
&lt;/pre&gt;
&lt;p&gt;The same reference name may be used both as a named hyperlink reference and in
an embedded alias link:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="s"&gt;`This site`_ links to the same location as `these words &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;This site_&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt;.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_This site:&lt;/span&gt; https://www.example.com
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="anonymous-hyperlinks"&gt;
&lt;span id="anon"&gt;&lt;/span&gt;&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Anonymous Hyperlinks&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What if you want to use the hyperlink reference syntax, but it’s for a URI that
will only be linked once, you don’t feel like giving it a reference name, and
the link text is too long to use as an efficient reference name?  The solution:
&lt;em&gt;anonymous hyperlinks&lt;/em&gt;.&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="s"&gt;`This link`__&lt;/span&gt; goes to a dot-com.  &lt;span class="s"&gt;`This other link`__&lt;/span&gt; goes to a dot-net.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;__:&lt;/span&gt; https://www.example.com&lt;span class="w"&gt;
&lt;/span&gt;__ https://www.example.net
&lt;/pre&gt;
&lt;p&gt;Rendered:&lt;/p&gt;
&lt;blockquote&gt;
&lt;a class="reference external" href="https://www.example.com"&gt;This link&lt;/a&gt; goes to a dot-com.  &lt;a class="reference external" href="https://www.example.net"&gt;This other link&lt;/a&gt; goes to a dot-net.&lt;/blockquote&gt;
&lt;p&gt;Write the link text as a &lt;a class="reference internal" href="#named-hyperlink-reference"&gt;named hyperlink reference&lt;/a&gt;, but instead of ending it
with one underscore, use two.  (As with named hyperlink references, the
backticks can be omitted for a &lt;a class="reference internal" href="#simple-reference-name"&gt;simple reference name&lt;/a&gt;.) Then, for the
&lt;a class="reference internal" href="#target"&gt;hyperlink target&lt;/a&gt;, use an underscore in place of the reference name
(so that you have two underscores in a row); alternatively, the entire
hyperlink target can be written as just two underscores, whitespace, and the
URI or e-mail address.&lt;/p&gt;
&lt;p&gt;The first anonymous hyperlink in a document will link to the URI given by the
first anonymous hyperlink target, the second anonymous hyperlink will link to
the second anonymous target, etc.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="embedded-uri-hyperlinks-and-automatic-reference-names"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Embedded URI Hyperlinks and Automatic Reference Names&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s an interesting fact about &lt;a class="reference internal" href="#embedded-uri-hyperlinks"&gt;embedded URI hyperlinks&lt;/a&gt;: they’re equivalent
to a &lt;a class="reference internal" href="#named-hyperlink-reference"&gt;named hyperlink reference&lt;/a&gt; using the link text as the reference name.
That means this:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="s"&gt;`This website &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;https://www.example.com&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt; is awesome!
&lt;/pre&gt;
&lt;p&gt;is exactly equivalent to:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="s"&gt;`This website`_&lt;/span&gt; is awesome!&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_This website:&lt;/span&gt; https://www.example.com
&lt;/pre&gt;
&lt;p&gt;As a consequence of this, you can link to the same location as an embedded URI
link by using its link text as the reference name:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
I changed my mind; &lt;span class="s"&gt;`this website &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;https://www.example.com&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt; sucks.  Let me&lt;span class="w"&gt;
&lt;/span&gt;reiterate: The website at &lt;span class="s"&gt;`this link &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;this website_&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt; is nothing special.
&lt;/pre&gt;
&lt;div class="section" id="gotcha-duplicate-link-text"&gt;
&lt;span id="gotcha"&gt;&lt;/span&gt;&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Gotcha: Duplicate Link Text&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As stated above, if a reference name is associated with two different URIs,
rendering the document will produce a warning, and the reference name will be
unusable in hyperlinks.  So what happens if we define two embedded URI
hyperlinks with the same link text but different URIs, like so?&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
See &lt;span class="s"&gt;`here &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;https://www.example.com&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt; and &lt;span class="s"&gt;`here &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;https://www.example.net&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;for more information.
&lt;/pre&gt;
&lt;p&gt;With the above input, a warning will be produced, but the hyperlinks will still
point where you want them to, and the reference name &lt;tt class="docutils literal"&gt;here&lt;/tt&gt; will refer to the
first URI.  This normally isn’t all that bad, but if you’re using a renderer
that fails on warnings — e.g., if you’re uploading a project with a
reStructuredText README to the &lt;a class="reference external" href="https://pypi.org"&gt;Python Package Index&lt;/a&gt; — the
rendering will fail, and your upload to PyPI will either be rejected or end up
with an unrendered project description.&lt;/p&gt;
&lt;p&gt;So how do we cleanly write embedded URI links with the same link text but
different URIs?  Answer: We add an extra underscore to the end of the link,
turning it into an &lt;a class="reference internal" href="#anon"&gt;anonymous hyperlink&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
See &lt;span class="s"&gt;`here &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;https://www.example.com&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`__&lt;/span&gt; and `here&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;https://www.example.net&amp;gt;&lt;/span&gt;`__ for more information.
&lt;/pre&gt;
&lt;p&gt;With two underscores, no hyperlink target is created, and so there is no
conflict.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="embedded-alias-hyperlinks-and-automatic-reference-names"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Embedded Alias Hyperlinks and Automatic Reference Names&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Similarly to embedded URI hyperlinks, using an &lt;a class="reference internal" href="#embedded-alias"&gt;embedded alias hyperlink&lt;/a&gt; turns the link text into a reference name pointing at the
same location as the hyperlink reference.  The following markup defines four
hyperlinks that all point to &amp;lt;&lt;a class="reference external" href="https://www.example.com"&gt;https://www.example.com&lt;/a&gt;&amp;gt;:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
See &lt;span class="s"&gt;`this site &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;site_&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt; for more information.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_site:&lt;/span&gt; https://www.example.com&lt;span class="w"&gt;

&lt;/span&gt;Now that I've written that link, I can write these links: `Click me! &amp;lt;this&lt;span class="w"&gt;
&lt;/span&gt;site_&amp;gt;&lt;span class="s"&gt;`_  I link to `this site`_&lt;/span&gt;!  &lt;span class="s"&gt;`Click me!`_&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you define multiple embedded alias hyperlinks with the same link text but
different hyperlink references, the document will render without any warnings,
and the link text will be usable as a reference name pointing to the same
location as the first hyperlink reference.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="intra-document-links"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Intra-Document Links&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Linking to different parts of the same document is accomplished using &lt;a class="reference internal" href="#embedded-alias"&gt;embedded
alias hyperlinks&lt;/a&gt; and &lt;a class="reference internal" href="#named-hyperlink-references"&gt;named hyperlink references&lt;/a&gt;, just
like external links; the difference is in how the &lt;a class="reference internal" href="#target"&gt;hyperlink target&lt;/a&gt;
is defined.&lt;/p&gt;
&lt;div class="section" id="internal-hyperlink-targets"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Internal Hyperlink Targets&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A hyperlink target without a URI creates an &lt;em&gt;internal hyperlink target&lt;/em&gt; that
points to the next element in the document after the target.&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Click &lt;span class="s"&gt;`here &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;After Lorem_&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt; to skip the next paragraph.&lt;span class="w"&gt;

&lt;/span&gt;Lorem ipsum dolor sit amet …&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_After Lorem:&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;This paragraph can be linked to with the reference name &amp;quot;&lt;span class="s"&gt;``After Lorem``&lt;/span&gt;.&amp;quot;&lt;span class="w"&gt;
&lt;/span&gt;Aren't you glad you didn't skip the previous paragraph now?
&lt;/pre&gt;
&lt;p&gt;Rendered:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Click &lt;a class="reference internal" href="#after-lorem"&gt;here&lt;/a&gt; to skip the next paragraph.&lt;/p&gt;
&lt;p&gt;Lorem ipsum dolor sit amet …&lt;/p&gt;
&lt;p id="after-lorem"&gt;This paragraph can be linked to with the reference name “&lt;tt class="docutils literal"&gt;After Lorem&lt;/tt&gt;.”
Aren’t you glad you didn’t skip the previous paragraph now?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The target points to the next element even if the target is indented so as to
be “nested” at the end of an indented block.  This allows us to attach targets
to individual elements of a list:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="m"&gt;1.&lt;/span&gt; Any following lines that line up with &amp;quot;Any&amp;quot; belong to this list item.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;   ..&lt;/span&gt; &lt;span class="nt"&gt;_item2:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;
&lt;span class="m"&gt;2.&lt;/span&gt; This list item can be linked to with the reference name &lt;span class="s"&gt;``item2``&lt;/span&gt;.
&lt;/pre&gt;
&lt;p&gt;If the &lt;tt class="docutils literal"&gt;.. _item2:&lt;/tt&gt; line above wasn’t indented, it would split the list into
two lists, and the target would point to the second list.  (A target before a
list always points to the list as a whole; a target pointing to just the first
item is not possible.)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="named-directives"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Named Directives&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Most reStructuredText directives support a &lt;tt class="docutils literal"&gt;:name:&lt;/tt&gt; option that takes a
string as an argument.  Setting this option allows you to link to the directive
using that name, equivalent to preceding the directive with an internal
hyperlink target.&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="ow"&gt;danger&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="nc"&gt;:name:&lt;/span&gt; dont-or-whatever&lt;span class="w"&gt;

&lt;/span&gt;    Don't stick your finger in the— You know what?  Forget it.  I'm not&lt;span class="w"&gt;
&lt;/span&gt;    your mother.&lt;span class="w"&gt;

&lt;/span&gt;… Text passes …&lt;span class="w"&gt;

&lt;/span&gt;Hey, remember &lt;span class="s"&gt;`that admonition from earlier &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;dont-or-whatever_&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt;?  I was&lt;span class="w"&gt;
&lt;/span&gt;serious.
&lt;/pre&gt;
&lt;p&gt;Rendered:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div class="admonition danger" id="dont-or-whatever"&gt;
&lt;p class="first admonition-title"&gt;!DANGER!&lt;/p&gt;
&lt;p class="last"&gt;Don’t stick your finger in the— You know what?  Forget it.  I’m not
your mother.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;… Text passes …&lt;/p&gt;
&lt;p&gt;Hey, remember &lt;a class="reference internal" href="#dont-or-whatever"&gt;that admonition from earlier&lt;/a&gt;?  I was
serious.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As this is the same as using an internal hyperlink target, a warning will be
generated if two directives have the same name or if the name of a directive is
the same as a reference name of another hyperlink target.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="inline-internal-targets"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Inline Internal Targets&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A phrase within a paragraph of text can be made into a target by preceding the
phrase with an underscore and a backtick, escaping any backticks inside the
phrase, and appending a backtick to the end of the phrase.  (The backticks
cannot be omitted, no matter how simple the phrase is.)  This defines the
phrase itself as a reference name that points to the phrase’s location in the
document.&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
They're called &amp;quot;paragraphs,&amp;quot; but I've never seen them _&lt;span class="nv"&gt;`para`&lt;/span&gt;!  Know what I&lt;span class="w"&gt;
&lt;/span&gt;mean?&lt;span class="w"&gt;

&lt;/span&gt;(I don't know what I was saying &lt;span class="s"&gt;`here &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;para_&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt;.)
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="implicit-hyperlink-targets-for-section-titles"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Implicit Hyperlink Targets for Section Titles&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A section title in a reStructuredText document implicitly defines a hyperlink
target pointing to that section with the same reference name as the section
title.&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Go read &amp;quot;&lt;span class="s"&gt;`All About Eels`_&lt;/span&gt;&amp;quot; to learn about our wriggly friends!&lt;span class="w"&gt;

&lt;/span&gt;Didn't you hear me?  Who wouldn't want to click `this link &amp;lt;All About&lt;span class="w"&gt;
&lt;/span&gt;Eels_&amp;gt;`_?&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="gh"&gt;All About Eels&lt;/span&gt;
&lt;span class="gh"&gt;==============&lt;/span&gt;
Did you know?  When you're bit in the heel by a big giant eel, that's a&lt;span class="w"&gt;
&lt;/span&gt;moray.
&lt;/pre&gt;
&lt;p&gt;If a section has the same name as a hyperlink target or a directive, the
hyperlink target or directive takes precedence, and the section cannot be
linked to by name.  If two or more sections have the same name, none of them
can be linked to by name.  In order to link to a section that cannot be linked
by name, you must precede the section title with an internal hyperlink target
and link to that.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="chaining-hyperlink-targets"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Chaining Hyperlink Targets&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It’s possible to define multiple hyperlink targets all pointing to the same
location by “chaining” the targets together, one after the other:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_foo:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_bar:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_baz:&lt;/span&gt; https://www.example.com&lt;span class="w"&gt;

&lt;/span&gt;Now the reference names foo_, bar_, and baz_ all link to the same place.
&lt;/pre&gt;
&lt;p&gt;Chained hyperlink targets all point to the same location as the last target in
the chain.  If the last target is an internal hyperlink target, the chained
targets will all point to the same document element as that last target:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_foo:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_bar:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_baz:&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;Now the reference names foo_, bar_, and baz_ all link to this paragraph.
&lt;/pre&gt;
&lt;p id="indirect-hyperlink-target"&gt;Alternatively, a hyperlink target &lt;tt class="docutils literal"&gt;A&lt;/tt&gt; can be defined to point to the same
location as another target &lt;tt class="docutils literal"&gt;B&lt;/tt&gt; by defining the hyperlink target with &lt;tt class="docutils literal"&gt;B&lt;/tt&gt;
(as a named hyperlink reference) in place of the URI:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_some link:&lt;/span&gt; https://www.example.com&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_foo:&lt;/span&gt; &lt;span class="s"&gt;`some link`_&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;Now &lt;span class="s"&gt;`some link`_&lt;/span&gt; and foo_ go to the same website.
&lt;/pre&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;.. _foo:&lt;/tt&gt; definition is called an &lt;em&gt;indirect hyperlink target&lt;/em&gt;.  As with
named hyperlink references, the backticks can be dropped when the hyperlink
reference is a &lt;a class="reference internal" href="#simple-reference-name"&gt;simple reference name&lt;/a&gt;.  &lt;a class="reference internal" href="#multiline"&gt;As with external hyperlink targets&lt;/a&gt;, the hyperlink reference may begin on the same or next line as
the target, and it may span multiple lines.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="styling-link-text"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Styling Link Text&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As you may have noticed, inline markup in link text is treated literally rather
than being processed into emphasis etc.  For example, this:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Try this recipe for &lt;span class="s"&gt;`pie *à la mode* &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;https://www.example.com&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt;.
&lt;/pre&gt;
&lt;p&gt;renders as:&lt;/p&gt;
&lt;blockquote&gt;
Try this recipe for &lt;a class="reference external" href="https://www.example.com"&gt;pie *à la mode*&lt;/a&gt;.&lt;/blockquote&gt;
&lt;p&gt;The asterisks are rendered as-is instead of causing the “à la mode” to be
emphasized.&lt;/p&gt;
&lt;p&gt;Fortunately, there’s a trick to use inline markup in link text: Define the link
using a substitution:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Try this recipe for |pie à la mode|_.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;|pie à la mode|&lt;/span&gt; &lt;span class="ow"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt; pie &lt;span class="ge"&gt;*à la mode*&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_pie à la mode:&lt;/span&gt; https://www.example.com
&lt;/pre&gt;
&lt;p&gt;Rendered:&lt;/p&gt;
&lt;blockquote&gt;
Try this recipe for &lt;a class="reference external" href="https://www.example.com"&gt;pie &lt;em&gt;à la mode&lt;/em&gt;&lt;/a&gt;.&lt;/blockquote&gt;
&lt;p&gt;The steps to do this are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;In our text, we insert a &lt;em&gt;substitution reference&lt;/em&gt; where we want the link to
be.  A substitution reference consists of a vertical bar, some arbitrary
substitution text, and another vertical bar.  Because we also want this to be
a hyperlink, an underscore is added after the closing vertical bar, causing
the substitution reference to also be a &lt;a class="reference internal" href="#named-hyperlink-reference"&gt;named hyperlink reference&lt;/a&gt; with the
substitution text as the reference name.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The substitution text can be any text that does not begin or end with
whitespace.  Substitution text is matched case-sensitively, but if that
fails, a case-insensitive match is tried.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Elsewhere in the document, a &lt;em&gt;substitution definition&lt;/em&gt; is given for the
substitution reference: two periods, a space, a vertical bar, the same
substitution text as in the substitution reference, another vertical bar,
whitespace, a &lt;tt class="docutils literal"&gt;replace::&lt;/tt&gt; directive (without leading &lt;tt class="docutils literal"&gt;..&lt;/tt&gt;), whitespace,
and then finally the inline markup to display in place of the substitution
reference in the rendered document.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Elsewhere in the document, a &lt;a class="reference internal" href="#target"&gt;hyperlink target&lt;/a&gt; is created that
maps the substitution text to the URI or e-mail address that the substituted
text should link to.  To link to a location in the document rather than to an
external URI, either use an &lt;a class="reference internal" href="#indirect-hyperlink-target"&gt;indirect hyperlink target&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Try this recipe for |pie à la mode|_.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;|pie à la mode|&lt;/span&gt; &lt;span class="ow"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt; pie &lt;span class="ge"&gt;*à la mode*&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_pie à la mode:&lt;/span&gt; &lt;span class="s"&gt;`pie recipe`_&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;Some intervening text&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_pie recipe:&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;So here's how you make pie &lt;span class="ge"&gt;*à la mode*&lt;/span&gt;: …
&lt;/pre&gt;
&lt;p&gt;or else make the substitution text the same as the reference name of the
internal target:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
Try this recipe for |pie recipe|_.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;|pie recipe|&lt;/span&gt; &lt;span class="ow"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt; pie &lt;span class="ge"&gt;*à la mode*&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;Some intervening text&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_pie recipe:&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;So here's how you make pie &lt;span class="ge"&gt;*à la mode*&lt;/span&gt;: …
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If desired, the substitution reference can be made into an &lt;a class="reference internal" href="#anon"&gt;anonymous
hyperlink&lt;/a&gt; instead by placing two underscores instead of one after the closing
vertical bar, in which case the hyperlink target must follow the anonymous
hyperlink target syntax.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="link-text-within-a-word"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Link Text within a Word&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Normally, a hyperlink spans one or more full words, but what if we want to only
link part of a word?  To do so, we must insert a backslash (optionally followed
by a whitespace character) between the link and the rest of the word:&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
These &lt;span class="s"&gt;`link &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;https://www.example.com&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt;\s are getting out of control!  Now&lt;span class="w"&gt;
&lt;/span&gt;they're in the in\ test_\ ines of our words.&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="nt"&gt;_test:&lt;/span&gt; https://www.example.net
&lt;/pre&gt;
&lt;p&gt;This renders as:&lt;/p&gt;
&lt;blockquote&gt;
These &lt;a class="reference external" href="https://www.example.com"&gt;link&lt;/a&gt;s are getting out of control!  Now
they’re in the in&lt;a class="reference external" href="https://www.example.net"&gt;test&lt;/a&gt;ines of our words.&lt;/blockquote&gt;
&lt;/div&gt;
</content><category term="Software"></category><category term="markup"></category><category term="reStructuredText"></category></entry><entry><title>Unicode and LaTeX</title><link href="https://jwodder.github.io/kbits/posts/unicode-latex/" rel="alternate"></link><published>2020-07-27T00:00:00-04:00</published><updated>2020-07-27T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2020-07-27:/kbits/posts/unicode-latex/</id><summary type="html">&lt;p class="first last"&gt;How to configure LaTeX to accept UTF-8 input (or just use XeLaTeX/LuaLaTeX
instead)&lt;/p&gt;
</summary><content type="html">&lt;p&gt;LaTeX is a powerful document typesetting system, but (especially if you’re
using a version even a few years old), getting it to accept and display
non-ASCII characters natively requires knowledge squirreled away in scattered
documents.  Here we cover how to get LaTeX to work with UTF-8 input characters
in hopes of thwarting the squirrels of obscurity.&lt;/p&gt;
&lt;p&gt;Or you could just &lt;a class="reference internal" href="#xetex-and-luatex"&gt;skip all that&lt;/a&gt; and use XeLaTeX or
LuaLaTeX instead.&lt;/p&gt;
&lt;div class="section" id="pdftex-engine-pdflatex"&gt;
&lt;h2&gt;pdfTeX Engine (pdfLaTeX)&lt;/h2&gt;
&lt;p&gt;When using “basic” LaTeX with the pdfTeX engine, enabling UTF-8 input requires
simply placing the following commands at the top of your document preamble:&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[T1]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fontenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The exact effects of these commands are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;code class="tx tex"&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[T1]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fontenc&lt;span class="nb"&gt;}&lt;/span&gt;&lt;/code&gt; sets the output font encoding to &lt;a class="reference external" href="http://www.micropress-inc.com/fonts/encoding/t1.htm"&gt;T1&lt;/a&gt;.  A font
encoding is a mapping between character codes and glyphs in a font; the font
encodings defined by LaTeX are described in &lt;a class="footnote-reference" href="#encguide" id="footnote-reference-1"&gt;[4]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By default, LaTeX uses the &lt;a class="reference external" href="http://www.micropress-inc.com/fonts/encoding/ot1.htm"&gt;OT1&lt;/a&gt; font encoding, a 7-bit encoding in which
accented characters like “ö” are formed by adding an accent glyph to the base
letter.  T1, by contrast, is an 8-bit encoding supporting widespread European
languages in which many letter+accent combinations exist as single glyphs.
&lt;a class="footnote-reference" href="#fontenc-vs-inputenc" id="footnote-reference-2"&gt;[3]&lt;/a&gt; &lt;a class="footnote-reference" href="#use-fontenc" id="footnote-reference-3"&gt;[14]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Without this command, characters will be represented using what’s available
in OT1, and, as a result, words containing accented characters won’t be
correctly hyphenated, copying-and-pasting accented characters from a built
PDF won’t work correctly, and inputting a &lt;tt class="docutils literal"&gt;|&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&amp;lt;&lt;/tt&gt;, or &lt;tt class="docutils literal"&gt;&amp;gt;&lt;/tt&gt; will produce
a completely different character in the resulting PDF. &lt;a class="footnote-reference" href="#use-fontenc" id="footnote-reference-4"&gt;[14]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If one passes a comma-separated list of font encodings to the &lt;tt class="docutils literal"&gt;fontenc&lt;/tt&gt;
package, the last encoding in the list becomes the document’s default
encoding, and switching to the other encodings (e.g., in order to enter
characters only defined by those encodings) becomes possible using the
command sequence &lt;code class="tx tex"&gt;&lt;span class="k"&gt;\fontencoding&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;INSERT ENCODING NAME HERE&lt;span class="nb"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt;&lt;/code&gt;.
&lt;a class="footnote-reference" href="#source2e" id="footnote-reference-5"&gt;[6]&lt;/a&gt; &lt;a class="footnote-reference" href="#minimal" id="footnote-reference-6"&gt;[13]&lt;/a&gt; &lt;a class="footnote-reference" href="#latex2e-unoff" id="footnote-reference-7"&gt;[9]&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;code class="tx tex"&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;&lt;/code&gt; sets the input encoding for the document
source to UTF-8, allowing UTF-8 characters to appear in the input document.
Additionally, for each font encoding used in the document, &lt;tt class="docutils literal"&gt;inputenc&lt;/tt&gt; loads
a mapping of UTF-8 characters to commands usable in that font encoding.
&lt;a class="footnote-reference" href="#inputenc" id="footnote-reference-8"&gt;[1]&lt;/a&gt;  When paired with the &lt;tt class="docutils literal"&gt;fontenc&lt;/tt&gt; command above, on recent LaTeX
versions, &lt;tt class="docutils literal"&gt;inputenc&lt;/tt&gt; loads mappings from the files &lt;tt class="docutils literal"&gt;omsenc.dfu&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;ot1enc.dfu&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;t1enc.dfu&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;ts1enc.dfu&lt;/tt&gt; &lt;a class="footnote-reference" href="#minimal" id="footnote-reference-9"&gt;[13]&lt;/a&gt;, located in
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;$TEXDIR/texmf-dist/tex/latex/base&lt;/span&gt;&lt;/tt&gt; in an installed TeX Live distribution;
this in turn allows the user to input any of the characters mapped by those
files into a document and have the characters be typeset appropriately.&lt;/p&gt;
&lt;p&gt;Without this command, older versions of LaTeX will use a “raw” input encoding
in which each input byte is typeset as the glyph in the same position in the
current font. &lt;a class="footnote-reference" href="#ltnews28" id="footnote-reference-10"&gt;[8]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Beginning with the 2018-04-01 release, LaTeX uses UTF-8 as the default
encoding for source files, making &lt;code class="tx tex"&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;&lt;/code&gt;
redundant. &lt;a class="footnote-reference" href="#ltnews28" id="footnote-reference-11"&gt;[8]&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once the above commands are added to your document preamble, you will be able
to enter a number of UTF-8 characters directly into your document and have them
show up in the built PDF without having to type out their commands.  You’ll
even be able to write smart quotes (&lt;tt class="docutils literal"&gt;“&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;”&lt;/tt&gt;) directly instead of typing
quotes out as `` and &lt;tt class="docutils literal"&gt;''&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;So instead of writing this:&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
``My na&lt;span class="k"&gt;\&amp;quot;\i&lt;/span&gt;&lt;span class="nb"&gt;{}&lt;/span&gt;ve r&lt;span class="k"&gt;\'&lt;/span&gt;esum&lt;span class="k"&gt;\'&lt;/span&gt;e is attached.''  --- Se&lt;span class="k"&gt;\~&lt;/span&gt;nor &lt;span class="k"&gt;\TH&lt;/span&gt;&lt;span class="nb"&gt;{}&lt;/span&gt;or
&lt;/pre&gt;
&lt;p&gt;you can write this:&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
“My naïve résumé is attached.”  — Señor Þor
&lt;/pre&gt;
&lt;p&gt;and LaTeX will handle the input correctly.&lt;/p&gt;
&lt;p&gt;Note that LaTeX does not support combining characters; input must be in a
composed form.&lt;/p&gt;
&lt;p&gt;If LaTeX encounters a Unicode character that it doesn’t have a definition for,
typesetting will stop with an error message of the form:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
! Package inputenc Error: Unicode char ☃ (U+2603)
(inputenc)                not set up for use with LaTeX.
&lt;/pre&gt;
&lt;p&gt;If you want to use a certain character in your document that LaTeX doesn’t
recognize, you can use the &lt;code class="tx tex"&gt;&lt;span class="k"&gt;\DeclareUnicodeCharacter&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;hexcode&lt;span class="nb"&gt;}{&lt;/span&gt;cmd&lt;span class="nb"&gt;}&lt;/span&gt;&lt;/code&gt; command
provided by &lt;tt class="docutils literal"&gt;inputenc&lt;/tt&gt;.  Its first argument is the hexadecimal code point of
the Unicode character to define, and the second argument is the LaTeX command
to execute when the character is encountered. &lt;a class="footnote-reference" href="#inputenc" id="footnote-reference-12"&gt;[1]&lt;/a&gt;  For example:&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;tikzsymbols&lt;span class="nb"&gt;}&lt;/span&gt;  &lt;span class="c"&gt;% provides \Snowman
&lt;/span&gt;&lt;span class="k"&gt;\DeclareUnicodeCharacter&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;2603&lt;span class="nb"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;\Snowman&lt;/span&gt;&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;% Now you can put ☃ in your document!&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you don’t want to have to enter characters as codepoints, the
&lt;code class="tx tex"&gt;&lt;span class="k"&gt;\newunicodechar&lt;/span&gt;&lt;/code&gt; command provided by &lt;a class="reference external" href="https://ctan.org/pkg/newunicodechar"&gt;the newunicodechar package&lt;/a&gt; lets you use the character itself
instead, &lt;a class="footnote-reference" href="#newunicodechar-docs" id="footnote-reference-13"&gt;[2]&lt;/a&gt; allowing us to rewrite the example above as:&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;newunicodechar&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;tikzsymbols&lt;span class="nb"&gt;}&lt;/span&gt;  &lt;span class="c"&gt;% provides \Snowman
&lt;/span&gt;&lt;span class="k"&gt;\newunicodechar&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;☃&lt;span class="nb"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;\Snowman&lt;/span&gt;&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;% Now you can put ☃ in your document!&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;As a special case, loading the &lt;tt class="docutils literal"&gt;textcomp&lt;/tt&gt; package lets you input all of the
Unicode characters that can be output with &lt;tt class="docutils literal"&gt;textcomp&lt;/tt&gt;’s commands; for
example, &lt;tt class="docutils literal"&gt;textcomp&lt;/tt&gt; defines a &lt;code class="tx tex"&gt;&lt;span class="k"&gt;\textmusicalnote&lt;/span&gt;&lt;/code&gt; command that produces ♪
(U+266A, EIGHTH NOTE), and so including &lt;tt class="docutils literal"&gt;textcomp&lt;/tt&gt; in your preamble allows
you to write “♪” in your document and have it be treated as the
&lt;code class="tx tex"&gt;&lt;span class="k"&gt;\textmusicalnote&lt;/span&gt;&lt;/code&gt; command, producing a “♪” in the output.&lt;/p&gt;
&lt;div class="section" id="non-latin-alphabets"&gt;
&lt;h3&gt;Non-Latin Alphabets&lt;/h3&gt;
&lt;p&gt;The commands described so far only provide meaningful support for text in
Latin-derived alphabets.  In order to enter text in other alphabets, more
elaborate steps are required.&lt;/p&gt;
&lt;div class="section" id="cyrillic-alphabet"&gt;
&lt;h4&gt;Cyrillic Alphabet&lt;/h4&gt;
&lt;p&gt;The most direct way to enable Cyrillic input is to specify a Cyrillic font
encoding in the &lt;tt class="docutils literal"&gt;fontenc&lt;/tt&gt; command.  Due to the large number of Cyrillic
characters in existence, the script is split up into three font encodings (T2A,
T2B, and T2C) that each match up with the T1 encoding in the lower 7-bit range,
plus a fourth encoding, X2, that contains all of the Cyrillic characters but is
not compatible with T1. &lt;a class="footnote-reference" href="#encguide" id="footnote-reference-14"&gt;[4]&lt;/a&gt; &lt;a class="footnote-reference" href="#cyrguide" id="footnote-reference-15"&gt;[11]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A purely-Cyrillic document can be written with the X2 font encoding as follows:&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;article&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[X2]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fontenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
Пролетарии всех стран, соединяйтесь!
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you want to use both Cyrillic and Latin characters in your document, you
need to pass both T1 and X2 to &lt;tt class="docutils literal"&gt;fontenc&lt;/tt&gt;.  Whichever one is listed last in
the &lt;tt class="docutils literal"&gt;fontenc&lt;/tt&gt; command becomes the default font encoding for the document; the
other font encoding can be switched to by writing &lt;code class="tx tex"&gt;&lt;span class="k"&gt;\fontencoding&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;INSERT
ENCODING NAME HERE&lt;span class="nb"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt;&lt;/code&gt;. &lt;a class="footnote-reference" href="#source2e" id="footnote-reference-16"&gt;[6]&lt;/a&gt; &lt;a class="footnote-reference" href="#minimal" id="footnote-reference-17"&gt;[13]&lt;/a&gt; &lt;a class="footnote-reference" href="#latex2e-unoff" id="footnote-reference-18"&gt;[9]&lt;/a&gt;
For example:&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;article&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[X2,T1]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fontenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
“&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\fontencoding&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;X2&lt;span class="nb"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; Пролетарии всех стран, соединяйтесь!&lt;span class="nb"&gt;}&lt;/span&gt;” said
Señor Þor.
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Managing encodings this way can get annoying; fortunately, &lt;a class="reference external" href="https://ctan.org/pkg/babel"&gt;the babel package&lt;/a&gt; provides a better way.  Add a
&lt;code class="tx tex"&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[LANGUAGES]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;babel&lt;span class="nb"&gt;}&lt;/span&gt;&lt;/code&gt; command to your preamble, where
&lt;tt class="docutils literal"&gt;LANGUAGES&lt;/tt&gt; is replaced by a comma-separated list of the languages that will
be used in your document; the last language in the list will become the
document’s default language.  Within the document, the language can be changed
with &lt;code class="tx tex"&gt;&lt;span class="k"&gt;\selectlanguage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;LANGUAGE&lt;span class="nb"&gt;}&lt;/span&gt;&lt;/code&gt; (though, for short passages, it’s better
to use &lt;code class="tx tex"&gt;&lt;span class="k"&gt;\foreignlanguage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;LANGUAGE&lt;span class="nb"&gt;}{&lt;/span&gt;TEXT&lt;span class="nb"&gt;}&lt;/span&gt;&lt;/code&gt;), and when it’s set to a
Cyrillic-using language, you can write in Cyrillic. &lt;a class="footnote-reference" href="#babel" id="footnote-reference-19"&gt;[7]&lt;/a&gt; &lt;a class="footnote-reference" href="#cyrguide" id="footnote-reference-20"&gt;[11]&lt;/a&gt;  For
example:&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;article&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;% If we don't explicitly load a Cyrillic font encoding, babel emits a
% warning and defaults to loading T2A.
&lt;/span&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[T2A,T1]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fontenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[russian,english]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;babel&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
“&lt;span class="k"&gt;\foreignlanguage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;russian&lt;span class="nb"&gt;}{&lt;/span&gt;Пролетарии всех стран, соединяйтесь!&lt;span class="nb"&gt;}&lt;/span&gt;” said
Señor Þor.
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="greek-alphabet"&gt;
&lt;h4&gt;Greek Alphabet&lt;/h4&gt;
&lt;p&gt;As with Cyrillic, entering Greek in LaTeX requires setting the font encoding,
in this case to LGR: &lt;a class="footnote-reference" href="#encguide" id="footnote-reference-21"&gt;[4]&lt;/a&gt;&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;article&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[LGR,T1]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fontenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
“&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\fontencoding&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;LGR&lt;span class="nb"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; Ἄνδρα μοι ἔννεπε, Μοῦσα, πολύτροπον, ὃς
μάλα πολλὰ&lt;span class="nb"&gt;}&lt;/span&gt;” said Homer.

“Is he talking about me?” wondered Señor Þor.
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;As before, we can let also choose to let babel take care of the encodings for
us:&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;article&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;% No need to explicitly load LGR!
&lt;/span&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[T1]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fontenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[greek,english]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;babel&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
“&lt;span class="k"&gt;\foreignlanguage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;greek&lt;span class="nb"&gt;}{&lt;/span&gt;Ἄνδρα μοι ἔννεπε, Μοῦσα, πολύτροπον, ὃς μάλα
πολλὰ&lt;span class="nb"&gt;}&lt;/span&gt;” said Homer.

“Is he talking about me?” wondered Señor Þor.
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;As another alternative, &lt;a class="reference external" href="https://ctan.org/pkg/greek-fontenc"&gt;the greek-fontenc package&lt;/a&gt; provides a &lt;tt class="docutils literal"&gt;textalpha&lt;/tt&gt; package that
allows one to write Greek directly without the need for babel or
language-switching: &lt;a class="footnote-reference" href="#greek-utf8" id="footnote-reference-22"&gt;[5]&lt;/a&gt;&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;article&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[T1]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fontenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;textalpha&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
“Ἄνδρα μοι ἔννεπε, Μοῦσα, πολύτροπον, ὃς μάλα πολλὰ” said Homer.

“Is he talking about me?” wondered Señor Þor.
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;greek-fontenc also provides an &lt;tt class="docutils literal"&gt;alphabeta&lt;/tt&gt; package that lets one use Greek
characters directly in math mode. &lt;a class="footnote-reference" href="#greek-utf8" id="footnote-reference-23"&gt;[5]&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="other-alphabets"&gt;
&lt;h4&gt;Other Alphabets&lt;/h4&gt;
&lt;p&gt;LaTeX’s built-in font encodings only cover Latin, Cyrillic, and Greek.
Enabling input in other alphabets is a separate topic for each alphabet with no
easy one-size-fits-all answer.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="xetex-engine-xelatex-and-luatex-engine-lualatex"&gt;
&lt;span id="xetex-and-luatex"&gt;&lt;/span&gt;&lt;h2&gt;XeTeX Engine (XeLaTeX) and LuaTeX Engine (LuaLaTeX)&lt;/h2&gt;
&lt;p&gt;Besides pdfTeX, LaTeX can also run on two major alternative engines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="http://xetex.sourceforge.net"&gt;The XeTeX engine&lt;/a&gt;, on which LaTeX runs as
XeLaTeX&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="http://www.luatex.org"&gt;The LuaTeX engine&lt;/a&gt;, on which LaTeX runs as
LuaLaTeX.  This is a TeX engine with an embedded interpreter for &lt;a class="reference external" href="http://www.lua.org"&gt;the Lua
programming language&lt;/a&gt; that allows developers to extend
the engine by coding in Lua. &lt;a class="footnote-reference" href="#faq-xelua" id="footnote-reference-24"&gt;[12]&lt;/a&gt; &lt;a class="footnote-reference" href="#wiki-luatex" id="footnote-reference-25"&gt;[15]&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both engines fully support Unicode input and support modern font technologies,
including being able to use fonts from the operating system.  &lt;a class="footnote-reference" href="#xetex" id="footnote-reference-26"&gt;[16]&lt;/a&gt;
&lt;a class="footnote-reference" href="#faq-xelua" id="footnote-reference-27"&gt;[12]&lt;/a&gt;  When it comes to Unicode support, the major differences between
pdfLaTeX and XeLaTeX/LuaLaTeX are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;XeLaTeX and LuaLaTeX documents must always be written in UTF-8, while
pdfLaTeX accepts document in various input encodings. &lt;a class="footnote-reference" href="#lshort" id="footnote-reference-28"&gt;[10]&lt;/a&gt; &lt;a class="footnote-reference" href="#minimal" id="footnote-reference-29"&gt;[13]&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The &lt;tt class="docutils literal"&gt;fontenc&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;inputenc&lt;/tt&gt; commands used in pdfLaTeX should be omitted
when working with XeLaTeX/LuaLaTeX; the Unicode engines ignore (and give a
warning about) &lt;tt class="docutils literal"&gt;inputenc&lt;/tt&gt;, while setting &lt;tt class="docutils literal"&gt;fontenc&lt;/tt&gt; can actually cause
some characters (like smart quotes) to not be recognized.  Instead, you can
just start entering Unicode characters directly into your document without
having to include any packages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The set of available Unicode characters in XeLaTeX/LuaLaTeX is determined by
what characters are defined in the current font. &lt;a class="footnote-reference" href="#minimal" id="footnote-reference-30"&gt;[13]&lt;/a&gt;  The default
font in both XeLaTeX and LuaLaTeX is &lt;a class="reference external" href="http://www.gust.org.pl/projects/e-foundry/latin-modern"&gt;Latin Modern&lt;/a&gt;, a derivative of
TeX’s Computer Modern default font that adds many more characters.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If XeLaTeX encounters a Unicode character that does not exist in the current
font, the resulting PDF will show the font’s placeholder character if it has
one; if the font has no placeholder character, nothing will be shown.  Either
way, the &lt;tt class="docutils literal"&gt;.log&lt;/tt&gt; file will contain a line of the form:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Missing character: There is no ☃ in font [lmroman10-regular]:mapping=tex-text;!
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If LuaLaTeX encounters a Unicode character that does not exist in the current
font, the character will be omitted in the resulting PDF.  No warning will be
emitted or logged.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;code class="tx tex"&gt;&lt;span class="k"&gt;\DeclareUnicodeCharacter&lt;/span&gt;&lt;/code&gt; is not a valid command in XeLaTeX or LuaLaTeX;
one must instead write something like:&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;tikzsymbols&lt;span class="nb"&gt;}&lt;/span&gt;  &lt;span class="c"&gt;% provides \Snowman
&lt;/span&gt;&lt;span class="k"&gt;\catcode&lt;/span&gt;`☃=&lt;span class="k"&gt;\active&lt;/span&gt;
&lt;span class="k"&gt;\protected\def&lt;/span&gt; ☃&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\Snowman&lt;/span&gt;&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;code class="tx tex"&gt;&lt;span class="k"&gt;\newunicodechar&lt;/span&gt;&lt;/code&gt; can still be used in place of this method, though.
&lt;a class="footnote-reference" href="#newunicodechar-docs" id="footnote-reference-31"&gt;[2]&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Being able to write in another alphabet is largely a matter of switching to a
font that supports that alphabet.  See &lt;a class="reference external" href="https://ctan.org/pkg/fontspec"&gt;the fontspec package&lt;/a&gt; for how to change fonts in XeLaTeX and
LuaLaTeX.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;While neither XeLaTeX nor LuaLaTeX natively supports combining characters,
the Lua scripting capabilities in the latter can be used to give combining
characters in your source code the desired effect; see
&amp;lt;&lt;a class="reference external" href="https://tex.stackexchange.com/a/149197"&gt;https://tex.stackexchange.com/a/149197&lt;/a&gt;&amp;gt; for an example.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="references"&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;table class="docutils footnote" frame="void" id="inputenc" 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;[1]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-8"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-12"&gt;2&lt;/a&gt;)&lt;/em&gt; Alan Jeffrey and Frank Mittelbach,
&lt;cite&gt;inputenc.sty&lt;/cite&gt;.
Version 1.3c.
Last modified 2018 August 11,
&amp;lt;&lt;a class="reference external" href="http://mirrors.ctan.org/macros/latex/base/inputenc.pdf"&gt;http://mirrors.ctan.org/macros/latex/base/inputenc.pdf&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="newunicodechar-docs" 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;[2]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-13"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-31"&gt;2&lt;/a&gt;)&lt;/em&gt; Enrico Gregorio,
&lt;cite&gt;The newunicodechar package&lt;/cite&gt;.
Last modified 2018 April 8,
&amp;lt;&lt;a class="reference external" href="http://mirrors.ctan.org/macros/latex/contrib/newunicodechar/newunicodechar.pdf"&gt;http://mirrors.ctan.org/macros/latex/contrib/newunicodechar/newunicodechar.pdf&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="fontenc-vs-inputenc" 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;[3]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;“fontenc vs inputenc”,
&lt;cite&gt;TeX - LaTeX Stack Exchange&lt;/cite&gt;.
Last modified 2018 April 3,
&amp;lt;&lt;a class="reference external" href="https://tex.stackexchange.com/q/44694"&gt;https://tex.stackexchange.com/q/44694&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="encguide" 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;[4]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-1"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-14"&gt;2&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-21"&gt;3&lt;/a&gt;)&lt;/em&gt; Frank Mittelbach, Robin Fairbairns, Werner Lemberg, and LaTeX3 Project Team,
&lt;cite&gt;LaTeX font encodings&lt;/cite&gt;.
Last modified 2016 February 18,
&amp;lt;&lt;a class="reference external" href="https://www.latex-project.org/help/documentation/encguide.pdf"&gt;https://www.latex-project.org/help/documentation/encguide.pdf&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="greek-utf8" 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;[5]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-22"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-23"&gt;2&lt;/a&gt;)&lt;/em&gt; Günter Milde,
&lt;cite&gt;Greek Unicode with 8-bit TeX and inputenc&lt;/cite&gt;.
Last modified 2019 July 11,
&amp;lt;&lt;a class="reference external" href="http://mirrors.ctan.org/language/greek/greek-inputenc/greek-utf8.pdf"&gt;http://mirrors.ctan.org/language/greek/greek-inputenc/greek-utf8.pdf&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="source2e" 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;[6]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-5"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-16"&gt;2&lt;/a&gt;)&lt;/em&gt; Johannes Braams, David Carlisle, Alan Jeffrey, Leslie Lamport, Frank
Mittelbach, Chris Rowley, and Rainer Schöpf,
&lt;cite&gt;The LaTeX2e Sources&lt;/cite&gt;.
Last modified 2020 February 2,
&amp;lt;&lt;a class="reference external" href="http://mirrors.ibiblio.org/CTAN/macros/latex/base/source2e.pdf"&gt;http://mirrors.ibiblio.org/CTAN/macros/latex/base/source2e.pdf&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="babel" 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-19"&gt;[7]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Johannes L. Braams and Javier Bezos,
&lt;cite&gt;Babel: Localization and internationalization&lt;/cite&gt;.
Version 3.47.
Last modified 2020 July 13,
&amp;lt;&lt;a class="reference external" href="http://mirrors.ctan.org/macros/latex/required/babel/base/babel.pdf"&gt;http://mirrors.ctan.org/macros/latex/required/babel/base/babel.pdf&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="ltnews28" 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;[8]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-10"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-11"&gt;2&lt;/a&gt;)&lt;/em&gt; &lt;cite&gt;LaTeX News&lt;/cite&gt;, issue 28, 2018 April.
&amp;lt;&lt;a class="reference external" href="https://www.latex-project.org/news/latex2e-news/ltnews28.pdf"&gt;https://www.latex-project.org/news/latex2e-news/ltnews28.pdf&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="latex2e-unoff" 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;[9]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-7"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-18"&gt;2&lt;/a&gt;)&lt;/em&gt; &lt;cite&gt;LaTeX2e unofficial reference manual&lt;/cite&gt;.
Last modified 2018 October,
&amp;lt;&lt;a class="reference external" href="http://tug.org/texinfohtml/latex2e.html"&gt;http://tug.org/texinfohtml/latex2e.html&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="lshort" 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-28"&gt;[10]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Tobias Oetiker, Hubert Partl, Irene Hyna, and Elisabeth Schlegl,
&lt;cite&gt;The Not So Short Introduction to LaTeX2ε&lt;/cite&gt;.
Version 6.2.
Last modified 2018 February 28,
&amp;lt;&lt;a class="reference external" href="http://tug.ctan.org/info/lshort/english/lshort.pdf"&gt;http://tug.ctan.org/info/lshort/english/lshort.pdf&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="cyrguide" 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;[11]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-15"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-20"&gt;2&lt;/a&gt;)&lt;/em&gt; Vladimir Volovich, Werner Lemberg, and LaTeX3 Project Team,
&lt;cite&gt;Cyrillic languages support in LaTeX&lt;/cite&gt;.
Last modified 1999 March 12,
&amp;lt;&lt;a class="reference external" href="https://www.latex-project.org/help/documentation/cyrguide.pdf"&gt;https://www.latex-project.org/help/documentation/cyrguide.pdf&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="faq-xelua" 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;[12]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-24"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-27"&gt;2&lt;/a&gt;)&lt;/em&gt; “What are XeTeX and LuaTeX?”,
&lt;cite&gt;The TeX Frequently Asked Question List&lt;/cite&gt;.
&amp;lt;&lt;a class="reference external" href="https://www.texfaq.org/FAQ-xetex-luatex"&gt;https://www.texfaq.org/FAQ-xetex-luatex&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="minimal" 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;[13]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-6"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-9"&gt;2&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-17"&gt;3&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-29"&gt;4&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-30"&gt;5&lt;/a&gt;)&lt;/em&gt; “What Unicode characters does pdfLaTeX support with a minimal preamble?”,
&lt;cite&gt;TeX - LaTeX Stack Exchange&lt;/cite&gt;.
Last modified 2020 July 27,
&amp;lt;&lt;a class="reference external" href="https://tex.stackexchange.com/q/555199"&gt;https://tex.stackexchange.com/q/555199&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="use-fontenc" 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;[14]&lt;/td&gt;&lt;td&gt;&lt;em&gt;(&lt;a class="fn-backref" href="#footnote-reference-3"&gt;1&lt;/a&gt;, &lt;a class="fn-backref" href="#footnote-reference-4"&gt;2&lt;/a&gt;)&lt;/em&gt; “Why should I use \usepackage[T1]{fontenc}?”,
&lt;cite&gt;TeX - LaTeX Stack Exchange&lt;/cite&gt;.
Last modified 2017 April 13,
&amp;lt;&lt;a class="reference external" href="https://tex.stackexchange.com/a/677"&gt;https://tex.stackexchange.com/a/677&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="wiki-luatex" 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-25"&gt;[15]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Wikipedia contributors,
“LuaTeX,”
&lt;cite&gt;Wikipedia, The Free Encyclopedia&lt;/cite&gt;.
&amp;lt;&lt;a class="reference external" href="https://en.wikipedia.org/w/index.php?title=LuaTeX&amp;amp;oldid=965669811"&gt;https://en.wikipedia.org/w/index.php?title=LuaTeX&amp;amp;oldid=965669811&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table class="docutils footnote" frame="void" id="xetex" 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-26"&gt;[16]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;cite&gt;XeTeX - Unicode-based TeX&lt;/cite&gt;.
&amp;lt;&lt;a class="reference external" href="http://xetex.sourceforge.net"&gt;http://xetex.sourceforge.net&lt;/a&gt;&amp;gt;
(accessed 2020 July 27).&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</content><category term="Software"></category><category term="markup"></category><category term="LaTeX"></category><category term="XeLaTeX"></category><category term="LuaLaTeX"></category><category term="Unicode"></category><category term="UTF-8"></category><category term="encoding"></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>