<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Knowledge Bits - Python packaging</title><link href="https://jwodder.github.io/kbits/" rel="alternate"></link><link href="https://jwodder.github.io/kbits/feeds/tag.python-packaging.atom.xml" rel="self"></link><id>https://jwodder.github.io/kbits/</id><updated>2022-06-10T00:00:00-04:00</updated><subtitle>References I wish I'd already found</subtitle><entry><title>Using Package Data in Python Projects with Setuptools</title><link href="https://jwodder.github.io/kbits/posts/pypkg-data/" rel="alternate"></link><published>2020-12-29T00:00:00-05:00</published><updated>2022-06-10T00:00:00-04:00</updated><author><name>John T. Wodder II</name></author><id>tag:jwodder.github.io,2020-12-29:/kbits/posts/pypkg-data/</id><summary type="html">&lt;p class="first last"&gt;When creating a Python project, you may want to include a number of
non-Python files in the project that the code can then access at runtime,
such as templates, images, and data.  These files are called &lt;em&gt;package
data&lt;/em&gt;, and this article describes how to include them in &amp;amp; access them from
your project.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;When creating a Python project, you may want to include a number of non-Python
files in the project that the code can then access at runtime, such as
templates, images, and data.  These files are called &lt;em&gt;package data&lt;/em&gt; &lt;a class="footnote-reference" href="#f1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;, and
they are included in &amp;amp; accessed from your project as follows.&lt;/p&gt;
&lt;div class="contents topic" id="contents"&gt;
&lt;p class="topic-title"&gt;Contents&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#including-package-data-in-projects" id="toc-entry-1"&gt;Including Package Data in Projects&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#including-package-data-via-manifest-in" id="toc-entry-2"&gt;Including Package Data via &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#including-package-data-via-setup-py-setup-cfg" id="toc-entry-3"&gt;Including Package Data via &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#excluding-package-data-via-setup-py-setup-cfg" id="toc-entry-4"&gt;Excluding Package Data via &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#including-package-data-via-setuptools-plugins" id="toc-entry-5"&gt;Including Package Data via Setuptools Plugins&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#accessing-package-data-at-runtime" id="toc-entry-6"&gt;Accessing Package Data at Runtime&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#installing-importing-importlib-resources" id="toc-entry-7"&gt;Installing &amp;amp; Importing &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#the-importlib-resources-api" id="toc-entry-8"&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; API&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference internal" href="#footnotes" id="toc-entry-9"&gt;Footnotes&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="including-package-data-in-projects"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Including Package Data in Projects&lt;/a&gt;&lt;/h2&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;The following section only pertains to projects built with setuptools.
Users of flit, Poetry, and other tools must consult their respective
backend’s documentation to see how to include package data.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The first requirement for being able to include package data in your &lt;a class="reference external" href="https://docs.python.org/3/tutorial/modules.html#packages"&gt;package&lt;/a&gt;
&lt;a class="footnote-reference" href="#f2" id="footnote-reference-2"&gt;[2]&lt;/a&gt; is for the files to be located somewhere inside the actual package
directory.  If your project is a single-file &lt;tt class="docutils literal"&gt;.py&lt;/tt&gt; module, you must convert
it to a directory/package layout before you can store package data in it.&lt;/p&gt;
&lt;p&gt;Once your package data is inside the package, you must tell setuptools to
include the files in both the project’s wheel (so that the files will be
installed when your package is installed) and sdist (so that the files can be
included in the wheel when building from an sdist).  There are two different
major ways to do this: a blanket “include all” method that uses a
&lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; file and a fine-grained method that configures one package &amp;amp;
subpackage at time via the &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt; file.&lt;/p&gt;
&lt;div class="admonition important"&gt;
&lt;p class="first admonition-title"&gt;Important&lt;/p&gt;
&lt;p class="last"&gt;In addition to the configurations described here, you also need to ensure
that all folders within your package that contain package data (even if
they contain no Python source code) are listed in the &lt;tt class="docutils literal"&gt;packages&lt;/tt&gt; option
in &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;.  This can be done automatically by using the
&lt;tt class="docutils literal"&gt;setuptools.find_namespace_packages()&lt;/tt&gt; function instead of
&lt;tt class="docutils literal"&gt;find_packages()&lt;/tt&gt;.  If you don’t do this, setuptools will emit a
warning message starting in version 62.3.0, and later versions will cease
to include such packages in your distribution at all.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="including-package-data-via-manifest-in"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Including Package Data via &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are two steps to this method:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Create or edit your project’s &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; file with the proper commands
to tell setuptools to include all of your package data file in the project’s
sdists.  See &lt;a class="reference external" href="https://packaging.python.org/guides/using-manifest-in/"&gt;the Python Packaging User Guide&lt;/a&gt; for information on how to
do this.&lt;/p&gt;
&lt;p&gt;In the simplest case — in which you want all non-Python files in your
package to be treated as package data — you can simply include your entire
package in your sdist with the &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; command “&lt;tt class="docutils literal"&gt;graft
packagename&lt;/tt&gt;” (or “&lt;tt class="docutils literal"&gt;graft src&lt;/tt&gt;” if you’re using a &lt;a class="reference external" href="https://hynek.me/articles/testing-packaging/"&gt;&lt;tt class="docutils literal"&gt;src/&lt;/tt&gt; layout&lt;/a&gt;).  If
you use this command, you should also follow it with “&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;global-exclude&lt;/span&gt;
*.py[cod]&lt;/tt&gt;” so that compiled Python bytecode files are not included in the
sdist.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;In your &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;, pass &lt;tt class="docutils literal"&gt;include_package_data=True&lt;/tt&gt; to the &lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt;
function.   If you are placing your project configuration in &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;
instead, set &lt;tt class="docutils literal"&gt;include_package_data = True&lt;/tt&gt; in the &lt;tt class="docutils literal"&gt;[options]&lt;/tt&gt; section of
&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Doing this tells setuptools that any non-Python files found inside your
package that are included in the sdist should also be included in the wheel.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="including-package-data-via-setup-py-setup-cfg"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Including Package Data via &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This method allows you to specify package data file patterns on a per-package
basis through the &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; argument to &lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt;.  &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt;
must be a &lt;tt class="docutils literal"&gt;dict&lt;/tt&gt; mapping package or subpackage names (or the empty string, to
specify all packages &amp;amp; subpackages) to lists of glob patterns indicating which
files within those packages to include in the sdist and wheel.&lt;/p&gt;
&lt;p&gt;A sample &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; looks like this:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;package_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# If any package or subpackage contains *.txt or *.rst files, include&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# them:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.txt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;*.rst&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# Include any *.msg files found in the &amp;quot;hello&amp;quot; package (but not in its&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# subpackages):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.msg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# Include any *.csv files found in the &amp;quot;hello.utils&amp;quot; package:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;hello.utils&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*.csv&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# Include any *.dat files found in the &amp;quot;data&amp;quot; subdirectory of the&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="c1"&gt;# &amp;quot;mypkg&amp;quot; package:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;mypkg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data/*.dat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you are placing your project configuration in &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;, you must
instead specify &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; via an &lt;tt class="docutils literal"&gt;[options.package_data]&lt;/tt&gt; section in
which the keys are the package &amp;amp; subpackage names — using &lt;tt class="docutils literal"&gt;*&lt;/tt&gt; instead of the
empty string to signify all packages — and the values are comma-separated glob
patterns.  The above &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt; sample translates to &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt; as
follows:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[options.package_data]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# If any package or subpackage contains *.txt or *.rst files, include them:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;*.txt, *.rst&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# Include any *.msg files found in the &amp;quot;hello&amp;quot; package (but not in its&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# subpackages):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;*.msg&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# Include any *.csv files found in the &amp;quot;hello.utils&amp;quot; package:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;hello.utils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;*.csv&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# Include any *.dat files found in the &amp;quot;data&amp;quot; subdirectory of the &amp;quot;mypkg&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# package:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="na"&gt;mypkg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;data/*.dat&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note that glob patterns only select files located directly within the given
package (or in the given subdirectory of the package, if the pattern includes a
directory path); e.g., &lt;tt class="docutils literal"&gt;&amp;quot;hello&amp;quot;: &lt;span class="pre"&gt;[&amp;quot;*.msg&amp;quot;]&lt;/span&gt;&lt;/tt&gt; selects &lt;tt class="docutils literal"&gt;*.msg&lt;/tt&gt; files in the
&lt;tt class="docutils literal"&gt;hello&lt;/tt&gt; package but not in any of its subpackages.  To select files in
subpackages, you must either include an entry for each subpackage or else use
the empty string key (or asterisk key in &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;) to specify a pattern
for all packages &amp;amp; subpackages.&lt;/p&gt;
&lt;p&gt;If a pattern contains any directory components, the forward slash (&lt;tt class="docutils literal"&gt;/&lt;/tt&gt;) must
be used as the directory separator, even on Windows.&lt;/p&gt;
&lt;p&gt;If a package data file is located in a directory that does not have an
&lt;tt class="docutils literal"&gt;__init__.py&lt;/tt&gt; file (say, a &lt;tt class="docutils literal"&gt;data/&lt;/tt&gt; directory inside
&lt;tt class="docutils literal"&gt;package.subpackage&lt;/tt&gt;), that directory does not count as a package, and the
file must be listed in &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; in the form &lt;tt class="docutils literal"&gt;&amp;quot;package.subpackage&amp;quot;:
[&amp;quot;data/PATTERN&amp;quot;]&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="first admonition-title"&gt;Warning&lt;/p&gt;
&lt;p class="last"&gt;If you use both &lt;tt class="docutils literal"&gt;include_package_data&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt;, files
specified with &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt; will not be automatically included in
sdists; you must instead list them in your &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="excluding-package-data-via-setup-py-setup-cfg"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Excluding Package Data via &lt;tt class="docutils literal"&gt;setup.py&lt;/tt&gt;/&lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;exclude_package_data&lt;/tt&gt; argument to &lt;tt class="docutils literal"&gt;setup()&lt;/tt&gt; can be used in conjunction
with either of the above methods to prevent one or more files from being
treated as package data.  &lt;tt class="docutils literal"&gt;exclude_package_data&lt;/tt&gt; takes a &lt;tt class="docutils literal"&gt;dict&lt;/tt&gt; with the
same structure as &lt;tt class="docutils literal"&gt;package_data&lt;/tt&gt;, and any matched files are excluded from
wheels.  Matched files are also excluded from sdists if they are not already
matched by the project’s &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;In a &lt;tt class="docutils literal"&gt;setup.cfg&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;exclude_package_data&lt;/tt&gt; becomes an
&lt;tt class="docutils literal"&gt;[options.exclude_package_data]&lt;/tt&gt; section whose contents have the same
structure as &lt;tt class="docutils literal"&gt;[options.package_data]&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="including-package-data-via-setuptools-plugins"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Including Package Data via Setuptools Plugins&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As an alternative to the above methods, you can use a plugin for setuptools
that automatically recognizes &amp;amp; includes package data in sdists &amp;amp; wheels,
usually based on what files in the project directory are under version control.
One example of such a plugin is &lt;a class="reference external" href="https://github.com/pypa/setuptools_scm"&gt;setuptools_scm&lt;/a&gt;, which automatically finds all
files under version control in a Git or Mercurial repository and augments the
project’s &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; (if any) with the found files.  This eliminates the
need to write a &lt;tt class="docutils literal"&gt;MANIFEST.in&lt;/tt&gt; manually (unless there are files under version
control that you want to exclude from sdists or wheels), though you still need
to set &lt;tt class="docutils literal"&gt;include_package_data&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;True&lt;/tt&gt; for files in your package directory
to be included in wheels.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="accessing-package-data-at-runtime"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#contents"&gt;Accessing Package Data at Runtime&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There have been multiple ways to access package data over the years, from
&lt;a class="reference external" href="https://setuptools.readthedocs.io/en/latest/pkg_resources.html#resourcemanager-api"&gt;&lt;tt class="docutils literal"&gt;pkg_resources&lt;/tt&gt;’ &lt;tt class="docutils literal"&gt;ResourceManager&lt;/tt&gt; API&lt;/a&gt; to &lt;a class="reference external" href="https://docs.python.org/3/library/pkgutil.html#pkgutil.get_data"&gt;&lt;tt class="docutils literal"&gt;pkgutil.get_data()&lt;/tt&gt;&lt;/a&gt;, but the most
recent and currently-recommended way is with the &lt;a class="reference external" href="http://importlib-resources.readthedocs.io"&gt;importlib-resources&lt;/a&gt;
package.&lt;/p&gt;
&lt;div class="section" id="installing-importing-importlib-resources"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#contents"&gt;Installing &amp;amp; Importing &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are two versions of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://pypi.org/project/importlib-resources/"&gt;The one on PyPI&lt;/a&gt; that is installed with &lt;tt class="docutils literal"&gt;pip install
&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; and imported with &lt;tt class="docutils literal"&gt;import importlib_resources&lt;/tt&gt; (note
underscore)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://docs.python.org/3/library/importlib.html#module-importlib.resources"&gt;The one in the Python standard library&lt;/a&gt; starting with Python 3.7 that is
imported with &lt;tt class="docutils literal"&gt;import importlib.resources&lt;/tt&gt; (note period)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Development of the PyPI version tends to be ahead of whatever’s in the latest
Python version.  In particular, the new &lt;tt class="docutils literal"&gt;files()&lt;/tt&gt;-based API described here
was only introduced in version 1.1.0 of the PyPI project and was only added to
the Python standard library in Python 3.9.  In order to be guaranteed a version
of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; that supports this API, you should add the following
to your project’s &lt;tt class="docutils literal"&gt;install_requires&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
importlib-resources&amp;gt;=1.1.0; python_version &amp;lt; '3.9'
&lt;/pre&gt;
&lt;p&gt;and import &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importlib-resources&lt;/span&gt;&lt;/tt&gt; in your code as follows:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="w"&gt;

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

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

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