CINXE.COM

PEP 262 – A Database of Installed Python Packages | peps.python.org

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 262 – A Database of Installed Python Packages | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0262/"> <link rel="stylesheet" href="../_static/style.css" type="text/css"> <link rel="stylesheet" href="../_static/mq.css" type="text/css"> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light"> <link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark"> <link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss"> <meta property="og:title" content='PEP 262 – A Database of Installed Python Packages | peps.python.org'> <meta property="og:description" content="This PEP describes a format for a database of the Python software installed on a system."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0262/"> <meta property="og:site_name" content="Python Enhancement Proposals (PEPs)"> <meta property="og:image" content="https://peps.python.org/_static/og-image.png"> <meta property="og:image:alt" content="Python PEPs"> <meta property="og:image:width" content="200"> <meta property="og:image:height" content="200"> <meta name="description" content="This PEP describes a format for a database of the Python software installed on a system."> <meta name="theme-color" content="#3776ab"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all"> <title>Following system colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="9"></circle> <path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path> </svg> </symbol> <symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all"> <title>Selected dark colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path> </svg> </symbol> <symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all"> <title>Selected light colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </symbol> </svg> <script> document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto" </script> <section id="pep-page-section"> <header> <h1>Python Enhancement Proposals</h1> <ul class="breadcrumbs"> <li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li> <li><a href="../pep-0000/">PEP Index</a> &raquo; </li> <li>PEP 262</li> </ul> <button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())"> <svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg> <span class="visually-hidden">Toggle light / dark / auto colour theme</span> </button> </header> <article> <section id="pep-content"> <h1 class="page-title">PEP 262 – A Database of Installed Python Packages</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">A.M. Kuchling &lt;amk&#32;&#97;t&#32;amk.ca&gt;</dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Topic<span class="colon">:</span></dt> <dd class="field-even"><a class="reference external" href="../topic/packaging/">Packaging</a></dd> <dt class="field-odd">Created<span class="colon">:</span></dt> <dd class="field-odd">08-Jul-2001</dd> <dt class="field-even">Post-History<span class="colon">:</span></dt> <dd class="field-even">27-Mar-2002</dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#introduction">Introduction</a></li> <li><a class="reference internal" href="#requirements">Requirements</a></li> <li><a class="reference internal" href="#database-location">Database Location</a></li> <li><a class="reference internal" href="#database-contents">Database Contents</a><ul> <li><a class="reference internal" href="#pkg-info-section">PKG-INFO section</a></li> <li><a class="reference internal" href="#files-section">FILES section</a></li> <li><a class="reference internal" href="#requires-section">REQUIRES section</a></li> <li><a class="reference internal" href="#provides-section">PROVIDES section</a></li> </ul> </li> <li><a class="reference internal" href="#api-description">API Description</a></li> <li><a class="reference internal" href="#deliverables">Deliverables</a></li> <li><a class="reference internal" href="#open-issues">Open Issues</a></li> <li><a class="reference internal" href="#rejected-suggestions">Rejected Suggestions</a></li> <li><a class="reference internal" href="#references">References</a></li> <li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <div class="admonition note"> <p class="admonition-title">Note</p> <p>This PEP was superseded by <a class="pep reference internal" href="../pep-0345/" title="PEP 345 – Metadata for Python Software Packages 1.2">PEP 345</a> and <a class="pep reference internal" href="../pep-0376/" title="PEP 376 – Database of Installed Python Distributions">PEP 376</a>, which were accepted. Therefore, this PEP is (by implication) rejected.</p> </div> <section id="introduction"> <h2><a class="toc-backref" href="#introduction" role="doc-backlink">Introduction</a></h2> <p>This PEP describes a format for a database of the Python software installed on a system.</p> <p>(In this document, the term “distribution” is used to mean a set of code that’s developed and distributed together. A “distribution” is the same as a Red Hat or Debian package, but the term “package” already has a meaning in Python terminology, meaning “a directory with an <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code> file in it.”)</p> </section> <section id="requirements"> <h2><a class="toc-backref" href="#requirements" role="doc-backlink">Requirements</a></h2> <p>We need a way to figure out what distributions, and what versions of those distributions, are installed on a system. We want to provide features similar to CPAN, APT, or RPM. Required use cases that should be supported are:</p> <ul class="simple"> <li>Is distribution X on a system?</li> <li>What version of distribution X is installed?</li> <li>Where can the new version of distribution X be found? (This can be defined as either “a home page where the user can go and find a download link”, or “a place where a program can find the newest version?” Both should probably be supported.)</li> <li>What files did distribution X put on my system?</li> <li>What distribution did the file x/y/z.py come from?</li> <li>Has anyone modified x/y/z.py locally?</li> <li>What other distributions does this software need?</li> <li>What Python modules does this distribution provide?</li> </ul> </section> <section id="database-location"> <h2><a class="toc-backref" href="#database-location" role="doc-backlink">Database Location</a></h2> <p>The database lives in a bunch of files under &lt;prefix&gt;/lib/python&lt;version&gt;/install-db/. This location will be called INSTALLDB through the remainder of this PEP.</p> <p>The structure of the database is deliberately kept simple; each file in this directory or its subdirectories (if any) describes a single distribution. Binary packagings of Python software such as RPMs can then update Python’s database by just installing the corresponding file into the INSTALLDB directory.</p> <p>The rationale for scanning subdirectories is that we can move to a directory-based indexing scheme if the database directory contains too many entries. For example, this would let us transparently switch from INSTALLDB/Numeric to INSTALLDB/N/Nu/Numeric or some similar hashing scheme.</p> </section> <section id="database-contents"> <h2><a class="toc-backref" href="#database-contents" role="doc-backlink">Database Contents</a></h2> <p>Each file in INSTALLDB or its subdirectories describes a single distribution, and has the following contents:</p> <p>An initial line listing the sections in this file, separated by whitespace. Currently this will always be ‘PKG-INFO FILES REQUIRES PROVIDES’. This is for future-proofing; if we add a new section, for example to list documentation files, then we’d add a DOCS section and list it in the contents. Sections are always separated by blank lines.</p> <p>A distribution that uses the Distutils for installation should automatically update the database. Distributions that roll their own installation will have to use the database’s API to manually add or update their own entry. System package managers such as RPM or pkgadd can just create the new file in the INSTALLDB directory.</p> <p>Each section of the file is used for a different purpose.</p> <section id="pkg-info-section"> <h3><a class="toc-backref" href="#pkg-info-section" role="doc-backlink">PKG-INFO section</a></h3> <p>An initial set of <span class="target" id="index-0"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc822.html"><strong>RFC 822</strong></a> headers containing the distribution information for a file, as described in <a class="pep reference internal" href="../pep-0241/" title="PEP 241 – Metadata for Python Software Packages">PEP 241</a>, “Metadata for Python Software Packages”.</p> </section> <section id="files-section"> <h3><a class="toc-backref" href="#files-section" role="doc-backlink">FILES section</a></h3> <p>An entry for each file installed by the distribution. Generated files such as .pyc and .pyo files are on this list as well as the original .py files installed by a distribution; their checksums won’t be stored or checked, though.</p> <p>Each file’s entry is a single tab-delimited line that contains the following fields:</p> <ul class="simple"> <li>The file’s full path, as installed on the system.</li> <li>The file’s size</li> <li>The file’s permissions. On Windows, this field will always be ‘unknown’</li> <li>The owner and group of the file, separated by a tab. On Windows, these fields will both be ‘unknown’.</li> <li>A SHA1 digest of the file, encoded in hex. For generated files such as *.pyc files, this field must contain the string “-“, which indicates that the file’s checksum should not be verified.</li> </ul> </section> <section id="requires-section"> <h3><a class="toc-backref" href="#requires-section" role="doc-backlink">REQUIRES section</a></h3> <p>This section is a list of strings giving the services required for this module distribution to run properly. This list includes the distribution name (“python-stdlib”) and module names (“rfc822”, “htmllib”, “email”, “email.Charset”). It will be specified by an extra ‘requires’ argument to the <code class="docutils literal notranslate"><span class="pre">distutils.core.setup()</span></code> function. For example:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">setup</span><span class="p">(</span><span class="o">...</span><span class="p">,</span> <span class="n">requires</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;xml.utils.iso8601&#39;</span><span class="p">,</span> </pre></div> </div> <p>Eventually there may be automated tools that look through all of the code and produce a list of requirements, but it’s unlikely that these tools can handle all possible cases; a manual way to specify requirements will always be necessary.</p> </section> <section id="provides-section"> <h3><a class="toc-backref" href="#provides-section" role="doc-backlink">PROVIDES section</a></h3> <p>This section is a list of strings giving the services provided by an installed distribution. This list includes the distribution name (“python-stdlib”) and module names (“rfc822”, “htmllib”, “email”, “email.Charset”).</p> <p>XXX should files be listed? e.g. $PREFIX/lib/color-table.txt, to pick up data files, required scripts, etc.</p> <p>Eventually there may be an option to let module developers add their own strings to this section. For example, you might add “XML parser” to this section, and other module distributions could then list “XML parser” as one of their dependencies to indicate that multiple different XML parsers can be used. For now this ability isn’t supported because it raises too many issues: do we need a central registry of legal strings, or just let people put whatever they like? Etc., etc…</p> </section> </section> <section id="api-description"> <h2><a class="toc-backref" href="#api-description" role="doc-backlink">API Description</a></h2> <p>There’s a single fundamental class, InstallationDatabase. The code for it lives in distutils/install_db.py. (XXX any suggestions for alternate locations in the standard library, or an alternate module name?)</p> <p>The InstallationDatabase returns instances of Distribution that contain all the information about an installed distribution.</p> <p>XXX Several of the fields in Distribution are duplicates of ones in distutils.dist.Distribution. Probably they should be factored out into the Distribution class proposed here, but can this be done in a backward-compatible way?</p> <p>InstallationDatabase has the following interface:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">InstallationDatabase</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;InstallationDatabase(path:string)</span> <span class="sd"> Read the installation database rooted at the specified path.</span> <span class="sd"> If path is None, INSTALLDB is used as the default.</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_distribution</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">distribution_name</span><span class="p">):</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;get_distribution(distribution_name:string) : Distribution</span> <span class="sd"> Get the object corresponding to a single distribution.</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="k">def</span><span class="w"> </span><span class="nf">list_distributions</span> <span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;list_distributions() : [Distribution]</span> <span class="sd"> Return a list of all distributions installed on the system,</span> <span class="sd"> enumerated in no particular order.</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="k">def</span><span class="w"> </span><span class="nf">find_distribution</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;find_file(path:string) : Distribution</span> <span class="sd"> Search and return the distribution containing the file &#39;path&#39;.</span> <span class="sd"> Returns None if the file doesn&#39;t belong to any distribution</span> <span class="sd"> that the InstallationDatabase knows about.</span> <span class="sd"> XXX should this work for directories?</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="k">class</span><span class="w"> </span><span class="nc">Distribution</span><span class="p">:</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;Instance attributes:</span> <span class="sd"> name : string</span> <span class="sd"> Distribution name</span> <span class="sd"> files : {string : (size:int, perms:int, owner:string, group:string,</span> <span class="sd"> digest:string)}</span> <span class="sd"> Dictionary mapping the path of a file installed by this distribution</span> <span class="sd"> to information about the file.</span> <span class="sd"> The following fields all come from PEP 241.</span> <span class="sd"> version : distutils.version.Version</span> <span class="sd"> Version of this distribution</span> <span class="sd"> platform : [string]</span> <span class="sd"> summary : string</span> <span class="sd"> description : string</span> <span class="sd"> keywords : string</span> <span class="sd"> home_page : string</span> <span class="sd"> author : string</span> <span class="sd"> author_email : string</span> <span class="sd"> license : string</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="k">def</span><span class="w"> </span><span class="nf">add_file</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;add_file(path:string):None</span> <span class="sd"> Record the size, ownership, &amp;c., information for an installed file.</span> <span class="sd"> XXX as written, this would stat() the file. Should the size/perms/</span> <span class="sd"> checksum all be provided as parameters to this method instead?</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="k">def</span><span class="w"> </span><span class="nf">has_file</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;has_file(path:string) : Boolean</span> <span class="sd"> Returns true if the specified path belongs to a file in this</span> <span class="sd"> distribution.</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="k">def</span><span class="w"> </span><span class="nf">check_file</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;check_file(path:string) : Boolean</span> <span class="sd"> Checks whether the file&#39;s size, checksum, and ownership match,</span> <span class="sd"> returning true if they do.</span> <span class="sd"> &quot;&quot;&quot;</span> </pre></div> </div> </section> <section id="deliverables"> <h2><a class="toc-backref" href="#deliverables" role="doc-backlink">Deliverables</a></h2> <p>A description of the database API, to be added to this PEP.</p> <p>Patches to the Distutils that 1) implement an InstallationDatabase class, 2) Update the database when a new distribution is installed. 3) add a simple package management tool, features to be added to this PEP. (Or should that be a separate PEP?) See <a class="footnote-reference brackets" href="#id2" id="id1">[2]</a> for the current patch.</p> </section> <section id="open-issues"> <h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2> <p>PJE suggests the installation database “be potentially present on every directory in sys.path, with the contents merged in sys.path order. This would allow home-directory or other alternate-location installs to work, and ease the process of a distutils install command writing the file.” Nice feature: it does mean that package manager tools can take into account Python packages that a user has privately installed.</p> <p>AMK wonders: what does setup.py do if it’s told to install packages to a directory not on sys.path? Does it write an install-db directory to the directory it’s told to write to, or does it do nothing?</p> <p>Should the package-database file itself be included in the files list? (PJE would think yes, but of course it can’t contain its own checksum. AMK can’t think of a use case where including the DB file matters.)</p> <p>PJE wonders about writing the package DB file <strong>first</strong>, before installing any other files, so that failed partial installations can both be backed out, and recognized as broken. This PEP may have to specify some algorithm for recognizing this situation.</p> <p>Should we guarantee the format of installation databases remains compatible across Python versions, or is it subject to arbitrary change? Probably we need to guarantee compatibility.</p> </section> <section id="rejected-suggestions"> <h2><a class="toc-backref" href="#rejected-suggestions" role="doc-backlink">Rejected Suggestions</a></h2> <p>Instead of using one text file per distribution, one large text file or an anydbm file could be used. This has been rejected for a few reasons. First, performance is probably not an extremely pressing concern as the database is only used when installing or removing software, a relatively infrequent task. Scalability also likely isn’t a problem, as people may have hundreds of Python packages installed, but thousands or tens of thousands seems unlikely. Finally, individual text files are compatible with installers such as RPM or DPKG because a binary packager can just drop the new database file into the database directory. If one large text file or a binary file were used, the Python database would then have to be updated by running a postinstall script.</p> <p>On Windows, the permissions and owner/group of a file aren’t stored. Windows does in fact support ownership and access permissions, but reading and setting them requires the win32all extensions, and they aren’t present in the basic Python installer for Windows.</p> </section> <section id="references"> <h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2> <p>[1] Michael Muller’s patch (posted to the Distutils-SIG around 28 Dec 1999) generates a list of installed files.</p> <aside class="footnote-list brackets"> <aside class="footnote brackets" id="id2" role="doc-footnote"> <dt class="label" id="id2">[<a href="#id1">2</a>]</dt> <dd>A patch to implement this PEP will be tracked as patch #562100 on SourceForge. <a class="reference external" href="https://bugs.python.org/issue562100">https://bugs.python.org/issue562100</a> . Code implementing the installation database is currently in Python CVS in the nondist/sandbox/pep262 directory.</aside> </aside> </section> <section id="acknowledgements"> <h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2> <p>Ideas for this PEP originally came from postings by Greg Ward, Fred L. Drake Jr., Thomas Heller, Mats Wichmann, Phillip J. Eby, and others.</p> <p>Many changes and rewrites to this document were suggested by the readers of the Distutils SIG.</p> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document has been placed in the public domain.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0262.rst">https://github.com/python/peps/blob/main/peps/pep-0262.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0262.rst">2025-02-01 08:55:40 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#introduction">Introduction</a></li> <li><a class="reference internal" href="#requirements">Requirements</a></li> <li><a class="reference internal" href="#database-location">Database Location</a></li> <li><a class="reference internal" href="#database-contents">Database Contents</a><ul> <li><a class="reference internal" href="#pkg-info-section">PKG-INFO section</a></li> <li><a class="reference internal" href="#files-section">FILES section</a></li> <li><a class="reference internal" href="#requires-section">REQUIRES section</a></li> <li><a class="reference internal" href="#provides-section">PROVIDES section</a></li> </ul> </li> <li><a class="reference internal" href="#api-description">API Description</a></li> <li><a class="reference internal" href="#deliverables">Deliverables</a></li> <li><a class="reference internal" href="#open-issues">Open Issues</a></li> <li><a class="reference internal" href="#rejected-suggestions">Rejected Suggestions</a></li> <li><a class="reference internal" href="#references">References</a></li> <li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0262.rst">Page Source (GitHub)</a> </nav> </section> <script src="../_static/colour_scheme.js"></script> <script src="../_static/wrap_tables.js"></script> <script src="../_static/sticky_banner.js"></script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10