diff --git a/info/pythonpackagingguide-figures/py_pkg_applications.png b/info/pythonpackagingguide-figures/py_pkg_applications.png new file mode 100644 index 00000000..bc3187db Binary files /dev/null and b/info/pythonpackagingguide-figures/py_pkg_applications.png differ diff --git a/info/pythonpackagingguide-figures/py_pkg_tools_and_libs.png b/info/pythonpackagingguide-figures/py_pkg_tools_and_libs.png new file mode 100644 index 00000000..707f1081 Binary files /dev/null and b/info/pythonpackagingguide-figures/py_pkg_tools_and_libs.png differ diff --git a/info/pythonpackagingguide.info b/info/pythonpackagingguide.info new file mode 100644 index 00000000..ef78adc8 --- /dev/null +++ b/info/pythonpackagingguide.info @@ -0,0 +1,17948 @@ +This is pythonpackagingguide.info, produced by makeinfo version 6.8 from +pythonpackagingguide.texi. + + Python Packaging User Guide , May 28, 2022 + + Python Packaging Authority + + Copyright © 2013–2020, PyPA + +INFO-DIR-SECTION Miscellaneous +START-INFO-DIR-ENTRY +* pythonpackagingguide: (pythonpackagingguide.info). One line description of project. +END-INFO-DIR-ENTRY + + + Generated by Sphinx 4.3.1. + + +File: pythonpackagingguide.info, Node: Top, Next: An Overview of Packaging for Python, Up: (dir) + +Python Packaging User Guide +*************************** + + Python Packaging User Guide , May 28, 2022 + + Python Packaging Authority + + Copyright © 2013–2020, PyPA + +* Menu: + +* An Overview of Packaging for Python:: +* Tutorials:: +* Guides:: +* Discussions:: +* PyPA specifications:: +* Project Summaries:: +* Glossary:: +* How to Get Support:: +* Contribute to this guide:: +* News:: +* Get started:: +* Learn more:: +* Index:: + + — The Detailed Node Listing — + +An Overview of Packaging for Python + +* Thinking about deployment:: +* Packaging Python libraries and tools:: +* Packaging Python applications:: +* What about…:: +* Wrap up:: + +Packaging Python libraries and tools + +* Python modules:: +* Python source distributions:: +* Python binary distributions:: + +Packaging Python applications + +* Depending on a framework:: +* Depending on a pre-installed Python:: +* Depending on a separate software distribution ecosystem:: +* Bringing your own Python executable:: +* Bringing your own userspace:: +* Bringing your own kernel:: +* Bringing your own hardware:: + +Depending on a framework + +* Service platforms:: +* Web browsers and mobile applications:: + +What about… + +* Operating system packages:: +* virtualenv:: +* Security:: + +Tutorials + +* Installing Packages:: +* Managing Application Dependencies:: +* Packaging Python Projects:: +* Creating Documentation:: + +Installing Packages + +* Requirements for Installing Packages:: +* Creating Virtual Environments:: +* Use pip for Installing:: +* Installing from PyPI:: +* Source Distributions vs Wheels:: +* Upgrading packages:: +* Installing to the User Site:: +* Requirements files:: +* Installing from VCS:: +* Installing from other Indexes:: +* Installing from a local src tree:: +* Installing from local archives:: +* Installing from other sources:: +* Installing Prereleases:: +* Installing Setuptools “Extras”:: + +Requirements for Installing Packages + +* Ensure you can run Python from the command line:: +* Ensure you can run pip from the command line:: +* Ensure pip, setuptools, and wheel are up to date: Ensure pip setuptools and wheel are up to date. +* Optionally, create a virtual environment: Optionally create a virtual environment. + +Managing Application Dependencies + +* Installing Pipenv:: +* Installing packages for your project:: +* Using installed packages:: +* Next steps:: +* Other Tools for Application Dependency Management:: + +Packaging Python Projects + +* A simple project:: +* Creating the package files:: +* Creating a test directory:: +* Creating pyproject.toml: Creating pyproject toml. +* Configuring metadata:: +* Creating README.md: Creating README md. +* Creating a LICENSE:: +* Including other files:: +* Generating distribution archives:: +* Uploading the distribution archives:: +* Installing your newly uploaded package:: +* Next steps: Next steps<2>. + +Creating Documentation + +* Installing Sphinx:: +* Getting Started With Sphinx:: +* Other Sources:: + +Guides + +* Installing packages using pip and virtual environments:: +* Installing stand alone command line tools:: +* Installing pip/setuptools/wheel with Linux Package Managers:: +* Installing scientific packages:: +* Multi-version installs:: +* Package index mirrors and caches:: +* Hosting your own simple repository:: +* Packaging and distributing projects:: +* Including files in source distributions with MANIFEST.in: Including files in source distributions with MANIFEST in. +* Single-sourcing the package version:: +* Supporting multiple Python versions:: +* Dropping support for older Python versions:: +* Packaging binary extensions:: +* Supporting Windows using Appveyor:: +* Packaging namespace packages:: +* Creating and discovering plugins:: +* Migrating to PyPI.org: Migrating to PyPI org. +* Using TestPyPI: Using TestPyPI<2>. +* Making a PyPI-friendly README:: +* Publishing package distribution releases using GitHub Actions CI/CD workflows:: +* Tool recommendations:: +* Analyzing PyPI package downloads:: + +Installing packages using pip and virtual environments + +* Installing pip:: +* Installing virtualenv:: +* Creating a virtual environment:: +* Activating a virtual environment:: +* Leaving the virtual environment:: +* Installing packages:: +* Installing specific versions:: +* Installing extras:: +* Installing from source:: +* Installing from version control systems:: +* Installing from local archives: Installing from local archives<2>. +* Using other package indexes:: +* Upgrading packages: Upgrading packages<2>. +* Using requirements files:: +* Freezing dependencies:: + +Installing pip/setuptools/wheel with Linux Package Managers + +* Fedora:: +* CentOS/RHEL:: +* openSUSE:: +* Debian/Ubuntu:: +* Arch Linux:: + +Installing scientific packages + +* Building from source:: +* Linux distribution packages:: +* Windows installers:: +* macOS installers and package managers:: +* SciPy distributions:: +* Spack:: +* The conda cross-platform package manager:: + +Package index mirrors and caches + +* Caching with pip:: +* Caching with devpi:: +* Complete mirror with bandersnatch:: + +Hosting your own simple repository + +* “Manual” repository:: + +Packaging and distributing projects + +* Requirements for packaging and distributing:: +* Configuring your project:: +* Working in “development mode”:: +* Packaging your project:: +* Uploading your Project to PyPI:: + +Configuring your project + +* Initial files:: +* setup() args: setup args. +* Choosing a versioning scheme:: + +Initial files + +* setup.py: setup py. +* setup.cfg: setup cfg. +* README.rst / README.md: README rst / README md. +* MANIFEST.in: MANIFEST in. +* LICENSE.txt: LICENSE txt. +* :: + +setup() args + +* name:: +* version:: +* description:: +* url:: +* author:: +* license:: +* classifiers:: +* keywords:: +* project_urls:: +* packages:: +* py_modules:: +* install_requires:: +* python_requires:: +* package_data:: +* data_files:: +* scripts:: +* entry_points:: + +entry_points + +* console_scripts:: + +Choosing a versioning scheme + +* Standards compliance for interoperability:: +* Scheme choices:: +* Pre-release versioning:: +* Local version identifiers:: + +Scheme choices + +* Semantic versioning (preferred): Semantic versioning preferred. +* Date based versioning:: +* Serial versioning:: +* Hybrid schemes:: + +Packaging your project + +* Source distributions:: +* Wheels:: + +Wheels + +* Pure Python Wheels:: +* Platform Wheels:: + +Uploading your Project to PyPI + +* Create an account:: +* Upload your distributions:: + +Including files in source distributions with MANIFEST.in + +* How files are included in an sdist:: +* MANIFEST.in commands: MANIFEST in commands. + +Supporting multiple Python versions + +* Automated testing and continuous integration:: +* Tools for single-source Python packages:: +* What’s in which Python?:: + +Dropping support for older Python versions + +* Requirements:: +* Dealing with the universal wheels:: +* Defining the Python version required:: +* Dropping a Python release:: + +Defining the Python version required + +* 1. Download the newest version of Setuptools: 1 Download the newest version of Setuptools. +* 2. Specify the version ranges for supported Python distributions: 2 Specify the version ranges for supported Python distributions. +* 3. Validating the Metadata before publishing: 3 Validating the Metadata before publishing. +* 4. Using Twine to publish: 4 Using Twine to publish. + +Packaging binary extensions + +* An overview of binary extensions:: +* Implementing binary extensions:: +* Building binary extensions:: +* Publishing binary extensions:: +* Additional resources:: + +An overview of binary extensions + +* Use cases:: +* Disadvantages:: +* Alternatives to handcoded accelerator modules:: +* Alternatives to handcoded wrapper modules:: +* Alternatives for low level system access:: + +Building binary extensions + +* Building extensions for multiple platforms:: +* Binary extensions for Windows:: +* Binary extensions for Linux:: +* Binary extensions for macOS:: + +Additional resources + +* Cross-platform wheel generation with scikit-build:: +* Introduction to C/C++ extension modules:: + +Supporting Windows using Appveyor + +* Background:: +* Setting up:: +* Adding Appveyor support to your project:: +* Additional notes:: + +Adding Appveyor support to your project + +* appveyor.yml: appveyor yml. +* Support script:: +* Access to the built wheels:: + +Additional notes + +* Testing with tox:: +* Automatically uploading wheels:: +* External dependencies:: +* Support scripts:: + +Packaging namespace packages + +* Creating a namespace package:: + +Creating a namespace package + +* Native namespace packages:: +* pkgutil-style namespace packages:: +* pkg_resources-style namespace packages:: + +Creating and discovering plugins + +* Using naming convention:: +* Using namespace packages:: +* Using package metadata:: + +Migrating to PyPI.org + +* Publishing releases:: +* Registering package names & metadata:: +* Using TestPyPI:: +* Registering new user accounts:: +* Browsing packages:: +* Downloading packages:: +* Managing published packages and releases:: + +Using TestPyPI + +* Registering your account:: +* Using TestPyPI with Twine:: +* Using TestPyPI with pip:: +* Setting up TestPyPI in .pypirc: Setting up TestPyPI in pypirc. + +Making a PyPI-friendly README + +* Creating a README file:: +* Including your README in your package’s metadata:: +* Validating reStructuredText markup:: + +Publishing package distribution releases using GitHub Actions CI/CD workflows + +* Saving credentials on GitHub:: +* Creating a workflow definition:: +* Defining a workflow job environment:: +* Checking out the project and building distributions:: +* Publishing the distribution to PyPI and TestPyPI:: +* That’s all, folks!: That’s all folks!. + +Tool recommendations + +* Application dependency management:: +* Installation tool recommendations:: +* Packaging tool recommendations:: +* Publishing platform migration:: + +Analyzing PyPI package downloads + +* Background: Background<2>. +* Public dataset:: +* Caveats:: +* Additional tools:: +* References:: + +Public dataset + +* Getting set up:: +* Data schema:: +* Useful queries:: + +Useful queries + +* Counting package downloads:: +* Package downloads over time:: +* Python versions over time:: + +Additional tools + +* google-cloud-bigquery:: +* pypinfo:: +* pandas-gbq:: + +Discussions + +* Deploying Python applications:: +* pip vs easy_install:: +* install_requires vs requirements files:: +* Wheel vs Egg:: + +Deploying Python applications + +* Overview:: +* OS packaging & installers:: +* Application bundles:: +* Configuration management:: + +Overview + +* Supporting multiple hardware platforms:: + +OS packaging & installers + +* Windows:: + +Windows + +* Pynsist:: + +Application bundles + +* Windows: Windows<2>. +* macOS:: +* Unix (including Linux and macOS): Unix including Linux and macOS. + +Windows + +* py2exe:: + +macOS + +* py2app:: + +Unix (including Linux and macOS) + +* pex:: + +install_requires vs requirements files + +* install_requires: install_requires<2>. +* Requirements files: Requirements files<2>. + +PyPA specifications + +* Package Distribution Metadata:: +* Package Distribution File Formats:: +* Package Index Interfaces:: + +Package Distribution Metadata + +* Core metadata specifications:: +* Version specifiers:: +* Dependency specifiers:: +* Declaring build system dependencies:: +* Declaring project metadata:: +* Platform compatibility tags:: +* Recording installed projects:: +* Entry points specification:: +* Recording the Direct URL Origin of installed distributions:: + +Core metadata specifications + +* Metadata-Version:: +* Name:: +* Version:: +* Dynamic (multiple use): Dynamic multiple use. +* Platform (multiple use): Platform multiple use. +* Supported-Platform (multiple use): Supported-Platform multiple use. +* Summary:: +* Description:: +* Description-Content-Type:: +* Keywords:: +* Home-page:: +* Download-URL:: +* Author:: +* Author-email:: +* Maintainer:: +* Maintainer-email:: +* License:: +* Classifier (multiple use): Classifier multiple use. +* Requires-Dist (multiple use): Requires-Dist multiple use. +* Requires-Python:: +* Requires-External (multiple use): Requires-External multiple use. +* Project-URL (multiple-use): Project-URL multiple-use. +* Provides-Extra (multiple use): Provides-Extra multiple use. +* Rarely Used Fields:: + +Rarely Used Fields + +* Provides-Dist (multiple use): Provides-Dist multiple use. +* Obsoletes-Dist (multiple use): Obsoletes-Dist multiple use. + +Declaring project metadata + +* name: name<2>. +* version: version<2>. +* description: description<2>. +* readme:: +* requires-python:: +* license: license<2>. +* authors/maintainers:: +* keywords: keywords<2>. +* classifiers: classifiers<2>. +* urls:: +* Entry points:: +* dependencies/optional-dependencies:: +* dynamic:: + +Platform compatibility tags + +* Platform tags for Windows:: +* Platform tags for macOS (Mac OS X): Platform tags for macOS Mac OS X. +* Platform tags for common Linux distributions:: +* Platform tags for other *nix platforms:: + +Platform tags for common Linux distributions + +* Manylinux compatibility support:: + +Recording installed projects + +* History and change workflow:: +* The .dist-info directory: The dist-info directory. +* The METADATA file:: +* The RECORD file:: +* The INSTALLER file:: +* The direct_url.json file: The direct_url json file. + +Entry points specification + +* Data model:: +* File format:: +* Use for scripts:: + +Recording the Direct URL Origin of installed distributions + +* Specification:: +* Registered VCS:: +* Examples:: + +Registered VCS + +* Git:: +* Mercurial:: +* Bazaar:: +* Subversion:: + +Examples + +* Example direct_url.json: Example direct_url json. +* Example pip commands and their effect on direct_url.json: Example pip commands and their effect on direct_url json. + +Package Distribution File Formats + +* Source distribution format:: +* Binary distribution format:: + +Source distribution format + +* Source trees:: +* Source distribution file name:: +* Source distribution file format:: + +Binary distribution format + +* Abstract:: +* PEP Acceptance:: +* Rationale:: +* Details:: +* FAQ:: +* Changes:: +* References: References<2>. +* Appendix:: +* Copyright:: + +Details + +* Installing a wheel ‘distribution-1.0-py32-none-any.whl’: Installing a wheel ‘distribution-1 0-py32-none-any whl’. +* File Format:: +* Signed wheel files:: +* Comparison to .egg: Comparison to egg. + +Installing a wheel ‘distribution-1.0-py32-none-any.whl’ + +* Recommended installer features:: +* Recommended archiver features:: + +File Format + +* File name convention:: +* Escaping and Unicode:: +* File contents:: + +File contents + +* The .dist-info directory: The dist-info directory<2>. +* The .data directory: The data directory. + +FAQ + +* Wheel defines a .data directory. Should I put all my data there?: Wheel defines a data directory Should I put all my data there?. +* Why does wheel include attached signatures?:: +* Why does wheel allow JWS signatures?:: +* Why does wheel also allow S/MIME signatures?:: +* What’s the deal with “purelib” vs. “platlib”?: What’s the deal with “purelib” vs “platlib”?. +* Is it possible to import Python code directly from a wheel file?:: + +Package Index Interfaces + +* The .pypirc file: The pypirc file. +* Simple repository API:: + +The .pypirc file + +* Common configurations:: + +Common configurations + +* Using a PyPI token:: +* Using another package index:: + +Project Summaries + +* PyPA Projects:: +* Non-PyPA Projects:: +* Standard Library Projects:: + +PyPA Projects + +* bandersnatch:: +* build:: +* cibuildwheel:: +* distlib:: +* flit:: +* hatch:: +* packaging:: +* pip:: +* Pipenv:: +* Pipfile:: +* pipx:: +* Python Packaging User Guide: Python Packaging User Guide<2>. +* readme_renderer:: +* setuptools:: +* trove-classifiers:: +* twine:: +* virtualenv: virtualenv<2>. +* Warehouse:: +* wheel:: + +Non-PyPA Projects + +* buildout:: +* conda:: +* devpi:: +* enscons:: +* Hashdist:: +* multibuild:: +* pdm:: +* pex: pex<2>. +* pip-tools:: +* piwheels:: +* poetry:: +* pypiserver:: +* PyScaffold:: +* scikit-build:: +* shiv:: +* Spack: Spack<2>. +* zest.releaser: zest releaser. + +Standard Library Projects + +* ensurepip:: +* distutils:: +* venv:: + +Contribute to this guide + +* Documentation types:: +* Translations:: +* Building the guide locally:: +* Where the guide is deployed:: +* Style guide:: + +Documentation types + +* Tutorials: Tutorials<2>. +* Guides: Guides<2>. +* Discussions: Discussions<2>. +* Specifications:: + +Translations + +* Adding a language:: +* Following reStructuredText syntax:: + +Style guide + +* Purpose:: +* Scope:: +* Audience:: +* Voice and tone:: +* Conventions and mechanics:: + +News + +* September 2019:: +* August 2019:: +* July 2019:: +* June 2019:: +* May 2019:: +* April 2019:: +* March 2019:: +* February 2019:: +* January 2019:: +* December 2018:: +* November 2018:: +* October 2018:: +* September 2018:: +* August 2018:: +* July 2018:: +* June 2018:: +* May 2018:: +* April 2018:: +* March 2018:: +* February 2018:: +* January 2018:: +* December 2017:: +* November 2017:: +* October 2017:: +* September 2017:: +* August 2017:: +* July 2017:: +* June 2017:: +* May 2017:: +* April 2017:: +* March 2017:: +* February 2017:: + + + +File: pythonpackagingguide.info, Node: An Overview of Packaging for Python, Next: Tutorials, Prev: Top, Up: Top + +1 An Overview of Packaging for Python +************************************* + +As a general-purpose programming language, Python is designed to be used +in many ways. You can build web sites or industrial robots or a game +for your friends to play, and much more, all using the same core +technology. + +Python’s flexibility is why the first step in every Python project must +be to think about the project’s audience and the corresponding +environment where the project will run. It might seem strange to think +about packaging before writing code, but this process does wonders for +avoiding future headaches. + +This overview provides a general-purpose decision tree for reasoning +about Python’s plethora of packaging options. Read on to choose the +best technology for your next project. + +* Menu: + +* Thinking about deployment:: +* Packaging Python libraries and tools:: +* Packaging Python applications:: +* What about…:: +* Wrap up:: + + +File: pythonpackagingguide.info, Node: Thinking about deployment, Next: Packaging Python libraries and tools, Up: An Overview of Packaging for Python + +1.1 Thinking about deployment +============================= + +Packages exist to be installed (or `deployed'), so before you package +anything, you’ll want to have some answers to the deployment questions +below: + + * Who are your software’s users? Will your software be installed by + other developers doing software development, operations people in a + datacenter, or a less software-savvy group? + + * Is your software intended to run on servers, desktops, mobile + clients (phones, tablets, etc.), or embedded in dedicated devices? + + * Is your software installed individually, or in large deployment + batches? + +Packaging is all about target environment and deployment experience. +There are many answers to the questions above and each combination of +circumstances has its own solutions. With this information, the +following overview will guide you to the packaging technologies best +suited to your project. + + +File: pythonpackagingguide.info, Node: Packaging Python libraries and tools, Next: Packaging Python applications, Prev: Thinking about deployment, Up: An Overview of Packaging for Python + +1.2 Packaging Python libraries and tools +======================================== + +You may have heard about PyPI, ‘setup.py’, and ‘wheel’ files. These are +just a few of the tools Python’s ecosystem provides for distributing +Python code to developers, which you can read about in *note Packaging +and distributing projects: 6. + +The following approaches to packaging are meant for libraries and tools +used by technical audience in a development setting. If you’re looking +for ways to package Python for a non-technical audience and/or a +production setting, skip ahead to *note Packaging Python applications: +7. + +* Menu: + +* Python modules:: +* Python source distributions:: +* Python binary distributions:: + + +File: pythonpackagingguide.info, Node: Python modules, Next: Python source distributions, Up: Packaging Python libraries and tools + +1.2.1 Python modules +-------------------- + +A Python file, provided it only relies on the standard library, can be +redistributed and reused. You will also need to ensure it’s written for +the right version of Python, and only relies on the standard library. + +This is great for sharing simple scripts and snippets between people who +both have compatible Python versions (such as via email, StackOverflow, +or GitHub gists). There are even some entire Python libraries that +offer this as an option, such as bottle.py(1) and boltons(2). + +However, this pattern won’t scale for projects that consist of multiple +files, need additional libraries, or need a specific version of Python, +hence the options below. + + ---------- Footnotes ---------- + + (1) https://bottlepy.org/docs/dev/ + + (2) https://boltons.readthedocs.io/en/latest/architecture.html + + +File: pythonpackagingguide.info, Node: Python source distributions, Next: Python binary distributions, Prev: Python modules, Up: Packaging Python libraries and tools + +1.2.2 Python source distributions +--------------------------------- + +If your code consists of multiple Python files, it’s usually organized +into a directory structure. Any directory containing Python files can +comprise an *note Import Package: a. + +Because packages consist of multiple files, they are harder to +distribute. Most protocols support transferring only one file at a time +(when was the last time you clicked a link and it downloaded multiple +files?). It’s easier to get incomplete transfers, and harder to +guarantee code integrity at the destination. + +So long as your code contains nothing but pure Python code, and you know +your deployment environment supports your version of Python, then you +can use Python’s native packaging tools to create a `source' *note +Distribution Package: b, or `sdist' for short. + +Python’s `sdists' are compressed archives (‘.tar.gz’ files) containing +one or more packages or modules. If your code is pure-Python, and you +only depend on other Python packages, you can go here to learn more(1). + +If you rely on any non-Python code, or non-Python packages (such as +libxml2(2) in the case of lxml(3), or BLAS libraries in the case of +numpy(4)), you will need to use the format detailed in the next section, +which also has many advantages for pure-Python libraries. + + Note: Python and PyPI support multiple distributions providing + different implementations of the same package. For instance the + unmaintained-but-seminal PIL distribution(5) provides the PIL + package, and so does Pillow(6), an actively-maintained fork of PIL! + + This Python packaging superpower makes it possible for Pillow to be + a drop-in replacement for PIL, just by changing your project’s + ‘install_requires’ or ‘requirements.txt’. + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/distutils/sourcedist.html + + (2) https://en.wikipedia.org/wiki/Libxml2 + + (3) https://pypi.org/project/lxml/ + + (4) https://pypi.org/project/numpy + + (5) https://pypi.org/project/PIL/ + + (6) https://pypi.org/project/Pillow/ + + +File: pythonpackagingguide.info, Node: Python binary distributions, Prev: Python source distributions, Up: Packaging Python libraries and tools + +1.2.3 Python binary distributions +--------------------------------- + +So much of Python’s practical power comes from its ability to integrate +with the software ecosystem, in particular libraries written in C, C++, +Fortran, Rust, and other languages. + +Not all developers have the right tools or experiences to build these +components written in these compiled languages, so Python created the +*note Wheel: d, a package format designed to ship libraries with +compiled artifacts. In fact, Python’s package installer, ‘pip’, always +prefers wheels because installation is always faster, so even +pure-Python packages work better with wheels. + +Binary distributions are best when they come with source distributions +to match. Even if you don’t upload wheels of your code for every +operating system, by uploading the sdist, you’re enabling users of other +platforms to still build it for themselves. Default to publishing both +sdist and wheel archives together, `unless' you’re creating artifacts +for a very specific use case where you know the recipient only needs one +or the other. + +Python and PyPI make it easy to upload both wheels and sdists together. +Just follow the *note Packaging Python Projects: e. tutorial. + +[image src="pythonpackagingguide-figures/py_pkg_tools_and_libs.png" alt="A summary of Python's packaging capabilities for tools and libraries."] + + + +Figure: Python’s recommended built-in library and tool packaging +technologies. Excerpted from The Packaging Gradient (2017)(1). + + ---------- Footnotes ---------- + + (1) https://www.youtube.com/watch?v=iLVNWfPWAC8 + + +File: pythonpackagingguide.info, Node: Packaging Python applications, Next: What about…, Prev: Packaging Python libraries and tools, Up: An Overview of Packaging for Python + +1.3 Packaging Python applications +================================= + +So far we’ve only discussed Python’s native distribution tools. Based +on our introduction, you would be correct to infer these built-in +approaches only target environments which have Python, and an audience +who knows how to install Python packages. + +With the variety of operating systems, configurations, and people out +there, this assumption is only safe when targeting a developer audience. + +Python’s native packaging is mostly built for distributing reusable +code, called libraries, between developers. You can piggyback `tools', +or basic applications for developers, on top of Python’s library +packaging, using technologies like setuptools entry_points(1). + +Libraries are building blocks, not complete applications. For +distributing applications, there’s a whole new world of technologies out +there. + +The next few sections organize these application packaging options +according to their dependencies on the target environment, so you can +choose the right one for your project. + +* Menu: + +* Depending on a framework:: +* Depending on a pre-installed Python:: +* Depending on a separate software distribution ecosystem:: +* Bringing your own Python executable:: +* Bringing your own userspace:: +* Bringing your own kernel:: +* Bringing your own hardware:: + + ---------- Footnotes ---------- + + (1) https://setuptools.pypa.io/en/latest/userguide/entry_point.html + + +File: pythonpackagingguide.info, Node: Depending on a framework, Next: Depending on a pre-installed Python, Up: Packaging Python applications + +1.3.1 Depending on a framework +------------------------------ + +Some types of Python applications, like web site backends and other +network services, are common enough that they have frameworks to enable +their development and packaging. Other types of applications, like +dynamic web frontends and mobile clients, are complex enough to target +that a framework becomes more than a convenience. + +In all these cases, it makes sense to work backwards, from the +framework’s packaging and deployment story. Some frameworks include a +deployment system which wraps the technologies outlined in the rest of +the guide. In these cases, you’ll want to defer to your framework’s +packaging guide for the easiest and most reliable production experience. + +If you ever wonder how these platforms and frameworks work under the +hood, you can always read the sections beyond. + +* Menu: + +* Service platforms:: +* Web browsers and mobile applications:: + + +File: pythonpackagingguide.info, Node: Service platforms, Next: Web browsers and mobile applications, Up: Depending on a framework + +1.3.1.1 Service platforms +......................... + +If you’re developing for a “Platform-as-a-Service” or “PaaS” like Heroku +or Google App Engine, you are going to want to follow their respective +packaging guides. + + * Heroku(1) + + * Google App Engine(2) + + * PythonAnywhere(3) + + * OpenShift(4) + + * “Serverless” frameworks like Zappa(5) + +In all these setups, the platform takes care of packaging and +deployment, as long as you follow their patterns. Most software does +not fit one of these templates, hence the existence of all the other +options below. + +If you’re developing software that will be deployed to machines you own, +users’ personal computers, or any other arrangement, read on. + + ---------- Footnotes ---------- + + (1) https://devcenter.heroku.com/articles/getting-started-with-python + + (2) https://cloud.google.com/appengine/docs/python/ + + (3) https://www.pythonanywhere.com/ + + (4) https://blog.openshift.com/getting-started-python/ + + (5) https://github.com/zappa/Zappa + + +File: pythonpackagingguide.info, Node: Web browsers and mobile applications, Prev: Service platforms, Up: Depending on a framework + +1.3.1.2 Web browsers and mobile applications +............................................ + +Python’s steady advances are leading it into new spaces. These days you +can write a mobile app or web application frontend in Python. While the +language may be familiar, the packaging and deployment practices are +brand new. + +If you’re planning on releasing to these new frontiers, you’ll want to +check out the following frameworks, and refer to their packaging guides: + + * Kivy(1) + + * Beeware(2) + + * Brython(3) + + * Flexx(4) + +If you are `not' interested in using a framework or platform, or just +wonder about some of the technologies and techniques utilized by the +frameworks above, continue reading below. + + ---------- Footnotes ---------- + + (1) https://kivy.org/ + + (2) https://pybee.org/ + + (3) https://brython.info/ + + (4) https://flexx.readthedocs.io/en/latest/ + + +File: pythonpackagingguide.info, Node: Depending on a pre-installed Python, Next: Depending on a separate software distribution ecosystem, Prev: Depending on a framework, Up: Packaging Python applications + +1.3.2 Depending on a pre-installed Python +----------------------------------------- + +Pick an arbitrary computer, and depending on the context, there’s a very +good chance Python is already installed. Included by default in most +Linux and Mac operating systems for many years now, you can reasonably +depend on Python preexisting in your data centers or on the personal +machines of developers and data scientists. + +Technologies which support this model: + + * PEX(1) (Python EXecutable) + + * zipapp(2) (does not help manage dependencies, requires Python 3.5+) + + * shiv(3) (requires Python 3) + + Note: Of all the approaches here, depending on a pre-installed + Python relies the most on the target environment. Of course, this + also makes for the smallest package, as small as single-digit + megabytes, or even kilobytes. + + In general, decreasing the dependency on the target system + increases the size of our package, so the solutions here are + roughly arranged by increasing size of output. + + ---------- Footnotes ---------- + + (1) https://github.com/pantsbuild/pex#user-content-pex + + (2) https://docs.python.org/3/library/zipapp.html + + (3) https://github.com/linkedin/shiv#user-content-shiv + + +File: pythonpackagingguide.info, Node: Depending on a separate software distribution ecosystem, Next: Bringing your own Python executable, Prev: Depending on a pre-installed Python, Up: Packaging Python applications + +1.3.3 Depending on a separate software distribution ecosystem +------------------------------------------------------------- + +For a long time many operating systems, including Mac and Windows, +lacked built-in package management. Only recently did these OSes gain +so-called “app stores”, but even those focus on consumer applications +and offer little for developers. + +Developers long sought remedies, and in this struggle, emerged with +their own package management solutions, such as Homebrew(1). The most +relevant alternative for Python developers is a package ecosystem called +Anaconda(2). Anaconda is built around Python and is increasingly common +in academic, analytical, and other data-oriented environments, even +making its way into server-oriented environments(3). + +Instructions on building and publishing for the Anaconda ecosystem: + + * Building libraries and applications with conda(4) + + * Transitioning a native Python package to Anaconda(5) + +A similar model involves installing an alternative Python distribution, +but does not support arbitrary operating system-level packages: + + * ActiveState ActivePython(6) + + * WinPython(7) + + ---------- Footnotes ---------- + + (1) https://brew.sh/ + + (2) https://en.wikipedia.org/wiki/Anaconda_(Python_distribution) + + (3) +https://web.archive.org/web/20190403064038/https://www.paypal-engineering.com/2016/09/07/python-packaging-at-paypal/ + + (4) +https://conda.io/projects/conda-build/en/latest/user-guide/tutorials/index.html + + (5) +https://conda.io/projects/conda-build/en/latest/user-guide/tutorials/build-pkgs-skeleton.html + + (6) https://www.activestate.com/activepython + + (7) http://winpython.github.io/ + + +File: pythonpackagingguide.info, Node: Bringing your own Python executable, Next: Bringing your own userspace, Prev: Depending on a separate software distribution ecosystem, Up: Packaging Python applications + +1.3.4 Bringing your own Python executable +----------------------------------------- + +Computing as we know it is defined by the ability to execute programs. +Every operating system natively supports one or more formats of program +they can natively execute. + +There are many techniques and technologies which turn your Python +program into one of these formats, most of which involve embedding the +Python interpreter and any other dependencies into a single executable +file. + +This approach, called `freezing', offers wide compatibility and seamless +user experience, though often requires multiple technologies, and a good +amount of effort. + +A selection of Python freezers: + + * pyInstaller(1) - Cross-platform + + * cx_Freeze(2) - Cross-platform + + * constructor(3) - For command-line installers + + * py2exe(4) - Windows only + + * py2app(5) - Mac only + + * osnap(6) - Windows and Mac + + * pynsist(7) - Windows only + +Most of the above imply single-user deployments. For multi-component +server applications, see Chef Omnibus(8). + + ---------- Footnotes ---------- + + (1) https://pyinstaller.readthedocs.io/en/stable/ + + (2) https://marcelotduarte.github.io/cx_Freeze/ + + (3) https://github.com/conda/constructor + + (4) http://www.py2exe.org/ + + (5) https://py2app.readthedocs.io/en/latest/ + + (6) https://github.com/jamesabel/osnap + + (7) https://pypi.org/project/pynsist/ + + (8) https://github.com/chef/omnibus#user-content–omnibus + + +File: pythonpackagingguide.info, Node: Bringing your own userspace, Next: Bringing your own kernel, Prev: Bringing your own Python executable, Up: Packaging Python applications + +1.3.5 Bringing your own userspace +--------------------------------- + +An increasing number of operating systems – including Linux, Mac OS, and +Windows – can be set up to run applications packaged as lightweight +images, using a relatively modern arrangement often referred to as +operating-system-level virtualization(1), or `containerization'. + +These techniques are mostly Python agnostic, because they package whole +OS filesystems, not just Python or Python packages. + +Adoption is most extensive among Linux servers, where the technology +originated and where the technologies below work best: + + * AppImage(2) + + * Docker(3) + + * Flatpak(4) + + * Snapcraft(5) + + ---------- Footnotes ---------- + + (1) +https://en.wikipedia.org/wiki/Operating-system-level_virtualization + + (2) https://appimage.org/ + + (3) https://www.fullstackpython.com/docker.html + + (4) https://flatpak.org/ + + (5) https://snapcraft.io/ + + +File: pythonpackagingguide.info, Node: Bringing your own kernel, Next: Bringing your own hardware, Prev: Bringing your own userspace, Up: Packaging Python applications + +1.3.6 Bringing your own kernel +------------------------------ + +Most operating systems support some form of classical virtualization, +running applications packaged as images containing a full operating +system of their own. Running these virtual machines, or VMs, is a +mature approach, widespread in data center environments. + +These techniques are mostly reserved for larger scale deployments in +data centers, though certain complex applications can benefit from this +packaging. Technologies are Python agnostic, and include: + + * Vagrant(1) + + * VHD(2), AMI(3), and other formats(4) + + * OpenStack(5) - A cloud management system in Python, with extensive + VM support + + ---------- Footnotes ---------- + + (1) https://www.vagrantup.com/ + + (2) https://en.wikipedia.org/wiki/VHD_(file_format) + + (3) https://en.wikipedia.org/wiki/Amazon_Machine_Image + + (4) https://docs.openstack.org/glance/latest/user/formats.html + + (5) https://www.redhat.com/en/topics/openstack + + +File: pythonpackagingguide.info, Node: Bringing your own hardware, Prev: Bringing your own kernel, Up: Packaging Python applications + +1.3.7 Bringing your own hardware +-------------------------------- + +The most all-encompassing way to ship your software would be to ship it +already-installed on some hardware. This way, your software’s user +would require only electricity. + +Whereas the virtual machines described above are primarily reserved for +the tech-savvy, you can find hardware appliances being used by everyone +from the most advanced data centers to the youngest children. + +Embed your code on an Adafruit(1), MicroPython(2), or more-powerful +hardware running Python, then ship it to the datacenter or your users’ +homes. They plug and play, and you can call it a day. + +[image src="pythonpackagingguide-figures/py_pkg_applications.png" alt="A summary of technologies used to package Python applications."] + + + +Figure: The simplified gamut of technologies used to package Python +applications. + + ---------- Footnotes ---------- + + (1) https://github.com/adafruit/circuitpython + + (2) https://micropython.org/ + + +File: pythonpackagingguide.info, Node: What about…, Next: Wrap up, Prev: Packaging Python applications, Up: An Overview of Packaging for Python + +1.4 What about… +=============== + +The sections above can only summarize so much, and you might be +wondering about some of the more conspicuous gaps. + +* Menu: + +* Operating system packages:: +* virtualenv:: +* Security:: + + +File: pythonpackagingguide.info, Node: Operating system packages, Next: virtualenv, Up: What about… + +1.4.1 Operating system packages +------------------------------- + +As mentioned in *note Depending on a separate software distribution +ecosystem: 14. above, some operating systems have package managers of +their own. If you’re very sure of the operating system you’re +targeting, you can depend directly on a format like deb(1) (for Debian, +Ubuntu, etc.) or RPM(2) (for Red Hat, Fedora, etc.), and use that +built-in package manager to take care of installation, and even +deployment. You can even use FPM(3) to generate both deb and RPMs from +the same source. + +In most deployment pipelines, the OS package manager is just one piece +of the puzzle. + + ---------- Footnotes ---------- + + (1) https://en.wikipedia.org/wiki/Deb_(file_format) + + (2) https://en.wikipedia.org/wiki/RPM_Package_Manager + + (3) +https://fpm.readthedocs.io/en/latest/cli-reference.html#virtualenv + + +File: pythonpackagingguide.info, Node: virtualenv, Next: Security, Prev: Operating system packages, Up: What about… + +1.4.2 virtualenv +---------------- + +Virtualenvs(1) have been an indispensable tool for multiple generations +of Python developer, but are slowly fading from view, as they are being +wrapped by higher-level tools. With packaging in particular, +virtualenvs are used as a primitive in the dh-virtualenv tool(2) and +osnap(3), both of which wrap virtualenvs in a self-contained way. + +For production deployments, do not rely on running ‘python -m pip +install’ from the Internet into a virtualenv, as one might do in a +development environment. The overview above is full of much better +solutions. + + ---------- Footnotes ---------- + + (1) https://docs.python-guide.org/dev/virtualenvs/ + + (2) https://dh-virtualenv.readthedocs.io/en/latest/tutorial.html + + (3) https://github.com/jamesabel/osnap + + +File: pythonpackagingguide.info, Node: Security, Prev: virtualenv, Up: What about… + +1.4.3 Security +-------------- + +The further down the gradient you come, the harder it gets to update +components of your package. Everything is more tightly bound together. + +For example, if a kernel security issue emerges, and you’re deploying +containers, the host system’s kernel can be updated without requiring a +new build on behalf of the application. If you deploy VM images, you’ll +need a new build. Whether or not this dynamic makes one option more +secure is still a bit of an old debate, going back to the +still-unsettled matter of static versus dynamic linking(1). + + ---------- Footnotes ---------- + + (1) +https://www.google.com/search?channel=fs&q=static+vs+dynamic+linking + + +File: pythonpackagingguide.info, Node: Wrap up, Prev: What about…, Up: An Overview of Packaging for Python + +1.5 Wrap up +=========== + +Packaging in Python has a bit of a reputation for being a bumpy ride. +This impression is mostly a byproduct of Python’s versatility. Once you +understand the natural boundaries between each packaging solution, you +begin to realize that the varied landscape is a small price Python +programmers pay for using one of the most balanced, flexible languages +available. + + +File: pythonpackagingguide.info, Node: Tutorials, Next: Guides, Prev: An Overview of Packaging for Python, Up: Top + +2 Tutorials +*********** + +`Tutorials' are opinionated step-by-step guides to help you get familiar +with packaging concepts. For more detailed information on specific +packaging topics, see *note Guides: 22. + +* Menu: + +* Installing Packages:: +* Managing Application Dependencies:: +* Packaging Python Projects:: +* Creating Documentation:: + + +File: pythonpackagingguide.info, Node: Installing Packages, Next: Managing Application Dependencies, Up: Tutorials + +2.1 Installing Packages +======================= + +This section covers the basics of how to install Python *note packages: +b. + +It’s important to note that the term “package” in this context is being +used to describe a bundle of software to be installed (i.e. as a +synonym for a *note distribution: b.). It does not to refer to the kind +of *note package: a. that you import in your Python source code (i.e. a +container of modules). It is common in the Python community to refer to +a *note distribution: b. using the term “package”. Using the term +“distribution” is often not preferred, because it can easily be confused +with a Linux distribution, or another larger software distribution like +Python itself. + +* Menu: + +* Requirements for Installing Packages:: +* Creating Virtual Environments:: +* Use pip for Installing:: +* Installing from PyPI:: +* Source Distributions vs Wheels:: +* Upgrading packages:: +* Installing to the User Site:: +* Requirements files:: +* Installing from VCS:: +* Installing from other Indexes:: +* Installing from a local src tree:: +* Installing from local archives:: +* Installing from other sources:: +* Installing Prereleases:: +* Installing Setuptools “Extras”:: + + +File: pythonpackagingguide.info, Node: Requirements for Installing Packages, Next: Creating Virtual Environments, Up: Installing Packages + +2.1.1 Requirements for Installing Packages +------------------------------------------ + +This section describes the steps to follow before installing other +Python packages. + +* Menu: + +* Ensure you can run Python from the command line:: +* Ensure you can run pip from the command line:: +* Ensure pip, setuptools, and wheel are up to date: Ensure pip setuptools and wheel are up to date. +* Optionally, create a virtual environment: Optionally create a virtual environment. + + +File: pythonpackagingguide.info, Node: Ensure you can run Python from the command line, Next: Ensure you can run pip from the command line, Up: Requirements for Installing Packages + +2.1.1.1 Ensure you can run Python from the command line +....................................................... + +Before you go any further, make sure you have Python and that the +expected version is available from your command line. You can check +this by running: (Unix/macOS) + python3 --version +(Windows) + py --version + +You should get some output like ‘Python 3.6.3’. If you do not have +Python, please install the latest 3.x version from python.org(1) or +refer to the Installing Python(2) section of the Hitchhiker’s Guide to +Python. + + Note: If you’re a newcomer and you get an error like this: + + >>> python --version + Traceback (most recent call last): + File "", line 1, in + NameError: name 'python' is not defined + + It’s because this command and other suggested commands in this + tutorial are intended to be run in a `shell' (also called a + `terminal' or `console'). See the Python for Beginners getting + started tutorial(3) for an introduction to using your operating + system’s shell and interacting with Python. + + Note: If you’re using an enhanced shell like IPython or the Jupyter + notebook, you can run system commands like those in this tutorial + by prefacing them with a ‘!’ character: + + In [1]: import sys + !{sys.executable} --version + Python 3.6.3 + + It’s recommended to write ‘{sys.executable}’ rather than plain + ‘python’ in order to ensure that commands are run in the Python + installation matching the currently running notebook (which may not + be the same Python installation that the ‘python’ command refers + to). + + Note: Due to the way most Linux distributions are handling the + Python 3 migration, Linux users using the system Python without + creating a virtual environment first should replace the ‘python’ + command in this tutorial with ‘python3’ and the ‘python -m pip’ + command with ‘python3 -m pip --user’. Do `not' run any of the + commands in this tutorial with ‘sudo’: if you get a permissions + error, come back to the section on creating virtual environments, + set one up, and then continue with the tutorial as written. + + ---------- Footnotes ---------- + + (1) https://www.python.org + + (2) https://docs.python-guide.org/starting/installation/#installation + + (3) +https://opentechschool.github.io/python-beginners/en/getting_started.html#what-is-python-exactly + + +File: pythonpackagingguide.info, Node: Ensure you can run pip from the command line, Next: Ensure pip setuptools and wheel are up to date, Prev: Ensure you can run Python from the command line, Up: Requirements for Installing Packages + +2.1.1.2 Ensure you can run pip from the command line +.................................................... + +Additionally, you’ll need to make sure you have *note pip: 2b. +available. You can check this by running: (Unix/macOS) + python3 -m pip --version +(Windows) + py -m pip --version + +If you installed Python from source, with an installer from +python.org(1), or via Homebrew(2) you should already have pip. If +you’re on Linux and installed using your OS package manager, you may +have to install pip separately, see *note Installing +pip/setuptools/wheel with Linux Package Managers: 2c. + +If ‘pip’ isn’t already installed, then first try to bootstrap it from +the standard library: (Unix/macOS) + python3 -m ensurepip --default-pip +(Windows) + py -m ensurepip --default-pip + +If that still doesn’t allow you to run ‘python -m pip’: + + * Securely Download get-pip.py(3) (4) + + * Run ‘python get-pip.py’. (5) This will install or upgrade + pip. Additionally, it will install *note setuptools: 2d. and + *note wheel: 2e. if they’re not installed already. + + Warning: Be cautious if you’re using a Python install + that’s managed by your operating system or another + package manager. get-pip.py does not coordinate with + those tools, and may leave your system in an inconsistent + state. You can use ‘python get-pip.py + --prefix=/usr/local/’ to install in ‘/usr/local’ which is + designed for locally-installed software. + + ---------- Footnotes ---------- + + (1) https://www.python.org + + (2) https://brew.sh + + (3) https://bootstrap.pypa.io/get-pip.py + + (4) (1) “Secure” in this context means using a modern browser or a +tool like ‘curl’ that verifies SSL certificates when downloading from +https URLs. + + (5) (2) Depending on your platform, this may require root or +Administrator access. *note pip: 2b. is currently considering changing +this by making user installs the default behavior +(https://github.com/pypa/pip/issues/1668). + + +File: pythonpackagingguide.info, Node: Ensure pip setuptools and wheel are up to date, Next: Optionally create a virtual environment, Prev: Ensure you can run pip from the command line, Up: Requirements for Installing Packages + +2.1.1.3 Ensure pip, setuptools, and wheel are up to date +........................................................ + +While ‘pip’ alone is sufficient to install from pre-built binary +archives, up to date copies of the ‘setuptools’ and ‘wheel’ projects are +useful to ensure you can also install from source archives: (Unix/macOS) + python3 -m pip install --upgrade pip setuptools wheel +(Windows) + py -m pip install --upgrade pip setuptools wheel + + +File: pythonpackagingguide.info, Node: Optionally create a virtual environment, Prev: Ensure pip setuptools and wheel are up to date, Up: Requirements for Installing Packages + +2.1.1.4 Optionally, create a virtual environment +................................................ + +See *note section below: 31. for details, but here’s the basic venv(1) +(2) command to use on a typical Linux system: (Unix/macOS) + python3 -m venv tutorial_env + source tutorial_env/bin/activate +(Windows) + py -m venv tutorial_env + tutorial_env\Scripts\activate + +This will create a new virtual environment in the ‘tutorial_env’ +subdirectory, and configure the current shell to use it as the default +‘python’ environment. + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/library/venv.html + + (2) (3) Beginning with Python 3.4, ‘venv’ (a stdlib alternative to +*note virtualenv: 32.) will create virtualenv environments with ‘pip’ +pre-installed, thereby making it an equal alternative to *note +virtualenv: 32. + + +File: pythonpackagingguide.info, Node: Creating Virtual Environments, Next: Use pip for Installing, Prev: Requirements for Installing Packages, Up: Installing Packages + +2.1.2 Creating Virtual Environments +----------------------------------- + +Python “Virtual Environments” allow Python *note packages: b. to be +installed in an isolated location for a particular application, rather +than being installed globally. If you are looking to safely install +global command line tools, see *note Installing stand alone command line +tools: 34. + +Imagine you have an application that needs version 1 of LibFoo, but +another application requires version 2. How can you use both these +applications? If you install everything into +/usr/lib/python3.6/site-packages (or whatever your platform’s standard +location is), it’s easy to end up in a situation where you +unintentionally upgrade an application that shouldn’t be upgraded. + +Or more generally, what if you want to install an application and leave +it be? If an application works, any change in its libraries or the +versions of those libraries can break the application. + +Also, what if you can’t install *note packages: b. into the global +site-packages directory? For instance, on a shared host. + +In all these cases, virtual environments can help you. They have their +own installation directories and they don’t share libraries with other +virtual environments. + +Currently, there are two common tools for creating Python virtual +environments: + + * venv(1) is available by default in Python 3.3 and later, and + installs *note pip: 2b. and *note setuptools: 2d. into created + virtual environments in Python 3.4 and later. + + * *note virtualenv: 32. needs to be installed separately, but + supports Python 2.7+ and Python 3.3+, and *note pip: 2b, *note + setuptools: 2d. and *note wheel: 2e. are always installed into + created virtual environments by default (regardless of Python + version). + +The basic usage is like so: + +Using venv(2): (Unix/macOS) + python3 -m venv + source /bin/activate +(Windows) + py -m venv + \Scripts\activate + +Using *note virtualenv: 32.: (Unix/macOS) + python3 -m virtualenv + source /bin/activate +(Windows) + virtualenv + \Scripts\activate + +For more information, see the venv(3) docs or the virtualenv(4) docs. + +The use of ‘source’ under Unix shells ensures that the virtual +environment’s variables are set within the current shell, and not in a +subprocess (which then disappears, having no useful effect). + +In both of the above cases, Windows users should _not_ use the ‘source’ +command, but should rather run the ‘activate’ script directly from the +command shell like so: + + \Scripts\activate + +Managing multiple virtual environments directly can become tedious, so +the *note dependency management tutorial: 35. introduces a higher level +tool, *note Pipenv: 36, that automatically manages a separate virtual +environment for each project and application that you work on. + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/library/venv.html + + (2) https://docs.python.org/3/library/venv.html + + (3) https://docs.python.org/3/library/venv.html + + (4) https://virtualenv.pypa.io/en/stable/index.html + + +File: pythonpackagingguide.info, Node: Use pip for Installing, Next: Installing from PyPI, Prev: Creating Virtual Environments, Up: Installing Packages + +2.1.3 Use pip for Installing +---------------------------- + +*note pip: 2b. is the recommended installer. Below, we’ll cover the +most common usage scenarios. For more detail, see the pip docs(1), +which includes a complete Reference Guide(2). + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/ + + (2) https://pip.pypa.io/en/latest/cli/ + + +File: pythonpackagingguide.info, Node: Installing from PyPI, Next: Source Distributions vs Wheels, Prev: Use pip for Installing, Up: Installing Packages + +2.1.4 Installing from PyPI +-------------------------- + +The most common usage of *note pip: 2b. is to install from the *note +Python Package Index: 39. using a *note requirement specifier: 3a. +Generally speaking, a requirement specifier is composed of a project +name followed by an optional *note version specifier: 3b. PEP 440(1) +contains a full specification(2) of the currently supported specifiers. +Below are some examples. + +To install the latest version of “SomeProject”: (Unix/macOS) + python3 -m pip install "SomeProject" +(Windows) + py -m pip install "SomeProject" + +To install a specific version: (Unix/macOS) + python3 -m pip install "SomeProject==1.4" +(Windows) + py -m pip install "SomeProject==1.4" + +To install greater than or equal to one version and less than another: +(Unix/macOS) + python3 -m pip install "SomeProject>=1,<2" +(Windows) + py -m pip install "SomeProject>=1,<2" + +To install a version that’s “compatible”(3) with a certain version: (4) +(Unix/macOS) + python3 -m pip install "SomeProject~=1.4.2" +(Windows) + py -m pip install "SomeProject~=1.4.2" + +In this case, this means to install any version “==1.4.*” version that’s +also “>=1.4.2”. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0440 + + (2) https://www.python.org/dev/peps/pep-0440#version-specifiers + + (3) https://www.python.org/dev/peps/pep-0440#compatible-release + + (4) (4) The compatible release specifier was accepted in PEP 440 +(https://www.python.org/dev/peps/pep-0440) and support was released in +*note setuptools: 2d. v8.0 and *note pip: 2b. v6.0 + + +File: pythonpackagingguide.info, Node: Source Distributions vs Wheels, Next: Upgrading packages, Prev: Installing from PyPI, Up: Installing Packages + +2.1.5 Source Distributions vs Wheels +------------------------------------ + +*note pip: 2b. can install from either *note Source Distributions +(sdist): 3d. or *note Wheels: d, but if both are present on PyPI, pip +will prefer a compatible *note wheel: d. You can override pip‘s default +behavior by e.g. using its –no-binary(1) option. + +*note Wheels: d. are a pre-built *note distribution: b. format that +provides faster installation compared to *note Source Distributions +(sdist): 3d, especially when a project contains compiled extensions. + +If *note pip: 2b. does not find a wheel to install, it will locally +build a wheel and cache it for future installs, instead of rebuilding +the source distribution in the future. + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/cli/pip_install/#install-no-binary + + +File: pythonpackagingguide.info, Node: Upgrading packages, Next: Installing to the User Site, Prev: Source Distributions vs Wheels, Up: Installing Packages + +2.1.6 Upgrading packages +------------------------ + +Upgrade an already installed ‘SomeProject’ to the latest from PyPI. +(Unix/macOS) + python3 -m pip install --upgrade SomeProject +(Windows) + py -m pip install --upgrade SomeProject + + +File: pythonpackagingguide.info, Node: Installing to the User Site, Next: Requirements files, Prev: Upgrading packages, Up: Installing Packages + +2.1.7 Installing to the User Site +--------------------------------- + +To install *note packages: b. that are isolated to the current user, use +the ‘--user’ flag: (Unix/macOS) + python3 -m pip install --user SomeProject +(Windows) + py -m pip install --user SomeProject + +For more information see the User Installs(1) section from the pip docs. + +Note that the ‘--user’ flag has no effect when inside a virtual +environment - all installation commands will affect the virtual +environment. + +If ‘SomeProject’ defines any command-line scripts or console entry +points, ‘--user’ will cause them to be installed inside the user +base(2)’s binary directory, which may or may not already be present in +your shell’s ‘PATH’. (Starting in version 10, pip displays a warning +when installing any scripts to a directory outside ‘PATH’.) If the +scripts are not available in your shell after installation, you’ll need +to add the directory to your ‘PATH’: + + - On Linux and macOS you can find the user base binary directory by + running ‘python -m site --user-base’ and adding ‘bin’ to the end. + For example, this will typically print ‘~/.local’ (with ‘~’ + expanded to the absolute path to your home directory) so you’ll + need to add ‘~/.local/bin’ to your ‘PATH’. You can set your ‘PATH’ + permanently by modifying ~/.profile(3). + + - On Windows you can find the user base binary directory by running + ‘py -m site --user-site’ and replacing ‘site-packages’ with + ‘Scripts’. For example, this could return + ‘C:\Users\Username\AppData\Roaming\Python36\site-packages’ so you + would need to set your ‘PATH’ to include + ‘C:\Users\Username\AppData\Roaming\Python36\Scripts’. You can set + your user ‘PATH’ permanently in the Control Panel(4). You may need + to log out for the ‘PATH’ changes to take effect. + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/user_guide/#user-installs + + (2) https://docs.python.org/3/library/site.html#site.USER_BASE + + (3) https://stackoverflow.com/a/14638025 + + (4) +https://docs.microsoft.com/en-us/windows/win32/shell/user-environment-variables?redirectedfrom=MSDN + + +File: pythonpackagingguide.info, Node: Requirements files, Next: Installing from VCS, Prev: Installing to the User Site, Up: Installing Packages + +2.1.8 Requirements files +------------------------ + +Install a list of requirements specified in a Requirements File(1). +(Unix/macOS) + python3 -m pip install -r requirements.txt +(Windows) + py -m pip install -r requirements.txt + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/user_guide/#requirements-files + + +File: pythonpackagingguide.info, Node: Installing from VCS, Next: Installing from other Indexes, Prev: Requirements files, Up: Installing Packages + +2.1.9 Installing from VCS +------------------------- + +Install a project from VCS in “editable” mode. For a full breakdown of +the syntax, see pip’s section on VCS Support(1). (Unix/macOS) + python3 -m pip install -e git+https://git.repo/some_pkg.git#egg=SomeProject # from git + python3 -m pip install -e hg+https://hg.repo/some_pkg#egg=SomeProject # from mercurial + python3 -m pip install -e svn+svn://svn.repo/some_pkg/trunk/#egg=SomeProject # from svn + python3 -m pip install -e git+https://git.repo/some_pkg.git@feature#egg=SomeProject # from a branch +(Windows) + py -m pip install -e git+https://git.repo/some_pkg.git#egg=SomeProject # from git + py -m pip install -e hg+https://hg.repo/some_pkg#egg=SomeProject # from mercurial + py -m pip install -e svn+svn://svn.repo/some_pkg/trunk/#egg=SomeProject # from svn + py -m pip install -e git+https://git.repo/some_pkg.git@feature#egg=SomeProject # from a branch + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/cli/pip_install/#vcs-support + + +File: pythonpackagingguide.info, Node: Installing from other Indexes, Next: Installing from a local src tree, Prev: Installing from VCS, Up: Installing Packages + +2.1.10 Installing from other Indexes +------------------------------------ + +Install from an alternate index (Unix/macOS) + python3 -m pip install --index-url http://my.package.repo/simple/ SomeProject +(Windows) + py -m pip install --index-url http://my.package.repo/simple/ SomeProject + +Search an additional index during install, in addition to *note PyPI: +39. (Unix/macOS) + python3 -m pip install --extra-index-url http://my.package.repo/simple SomeProject +(Windows) + py -m pip install --extra-index-url http://my.package.repo/simple SomeProject + + +File: pythonpackagingguide.info, Node: Installing from a local src tree, Next: Installing from local archives, Prev: Installing from other Indexes, Up: Installing Packages + +2.1.11 Installing from a local src tree +--------------------------------------- + +Installing from local src in Development Mode(1), i.e. in such a way +that the project appears to be installed, but yet is still editable from +the src tree. (Unix/macOS) + python3 -m pip install -e +(Windows) + py -m pip install -e + +You can also install normally from src (Unix/macOS) + python3 -m pip install +(Windows) + py -m pip install + + ---------- Footnotes ---------- + + (1) +https://setuptools.pypa.io/en/latest/userguide/development_mode.html + + +File: pythonpackagingguide.info, Node: Installing from local archives, Next: Installing from other sources, Prev: Installing from a local src tree, Up: Installing Packages + +2.1.12 Installing from local archives +------------------------------------- + +Install a particular source archive file. (Unix/macOS) + python3 -m pip install ./downloads/SomeProject-1.0.4.tar.gz +(Windows) + py -m pip install ./downloads/SomeProject-1.0.4.tar.gz + +Install from a local directory containing archives (and don’t check +*note PyPI: 39.) (Unix/macOS) + python3 -m pip install --no-index --find-links=file:///local/dir/ SomeProject + python3 -m pip install --no-index --find-links=/local/dir/ SomeProject + python3 -m pip install --no-index --find-links=relative/dir/ SomeProject +(Windows) + py -m pip install --no-index --find-links=file:///local/dir/ SomeProject + py -m pip install --no-index --find-links=/local/dir/ SomeProject + py -m pip install --no-index --find-links=relative/dir/ SomeProject + + +File: pythonpackagingguide.info, Node: Installing from other sources, Next: Installing Prereleases, Prev: Installing from local archives, Up: Installing Packages + +2.1.13 Installing from other sources +------------------------------------ + +To install from other data sources (for example Amazon S3 storage) you +can create a helper application that presents the data in a PEP 503(1) +compliant index format, and use the ‘--extra-index-url’ flag to direct +pip to use that index. + + ./s3helper --port=7777 + python -m pip install --extra-index-url http://localhost:7777 SomeProject + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0503 + + +File: pythonpackagingguide.info, Node: Installing Prereleases, Next: Installing Setuptools “Extras”, Prev: Installing from other sources, Up: Installing Packages + +2.1.14 Installing Prereleases +----------------------------- + +Find pre-release and development versions, in addition to stable +versions. By default, pip only finds stable versions. (Unix/macOS) + python3 -m pip install --pre SomeProject +(Windows) + py -m pip install --pre SomeProject + + +File: pythonpackagingguide.info, Node: Installing Setuptools “Extras”, Prev: Installing Prereleases, Up: Installing Packages + +2.1.15 Installing Setuptools “Extras” +------------------------------------- + +Install setuptools extras(1). (Unix/macOS) + python3 -m pip install SomePackage[PDF] + python3 -m pip install SomePackage[PDF]==3.0 + python3 -m pip install -e .[PDF] # editable project in current directory +(Windows) + py -m pip install SomePackage[PDF] + py -m pip install SomePackage[PDF]==3.0 + py -m pip install -e .[PDF] # editable project in current directory + +__________________________________________________________________ + + ---------- Footnotes ---------- + + (1) +https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#optional-dependencies + + +File: pythonpackagingguide.info, Node: Managing Application Dependencies, Next: Packaging Python Projects, Prev: Installing Packages, Up: Tutorials + +2.2 Managing Application Dependencies +===================================== + +The *note package installation tutorial: 25. covered the basics of +getting set up to install and update Python packages. + +However, running these commands interactively can get tedious even for +your own personal projects, and things get even more difficult when +trying to set up development environments automatically for projects +with multiple contributors. + +This tutorial walks you through the use of *note Pipenv: 36. to manage +dependencies for an application. It will show you how to install and +use the necessary tools and make strong recommendations on best +practices. + +Keep in mind that Python is used for a great many different purposes, +and precisely how you want to manage your dependencies may change based +on how you decide to publish your software. The guidance presented here +is most directly applicable to the development and deployment of network +services (including web applications), but is also very well suited to +managing development and testing environments for any kind of project. + +For alternatives, see *note Other Tools for Application Dependency +Management: 4d. + +* Menu: + +* Installing Pipenv:: +* Installing packages for your project:: +* Using installed packages:: +* Next steps:: +* Other Tools for Application Dependency Management:: + + +File: pythonpackagingguide.info, Node: Installing Pipenv, Next: Installing packages for your project, Up: Managing Application Dependencies + +2.2.1 Installing Pipenv +----------------------- + +*note Pipenv: 36. is a dependency manager for Python projects. If +you’re familiar with Node.js’ npm(1) or Ruby’s bundler(2), it is similar +in spirit to those tools. While *note pip: 2b. alone is often +sufficient for personal use, Pipenv is recommended for collaborative +projects as it’s a higher-level tool that simplifies dependency +management for common use cases. + +Use ‘pip’ to install Pipenv: (Unix/macOS) + python3 -m pip install --user pipenv +(Windows) + py -m pip install --user pipenv + Note: This does a user installation(3) to prevent breaking any + system-wide packages. If ‘pipenv’ isn’t available in your shell + after installation, you’ll need to add the user base(4)’s binary + directory to your ‘PATH’. See *note Installing to the User Site: + 40. for more information. + + ---------- Footnotes ---------- + + (1) https://www.npmjs.com/ + + (2) https://bundler.io/ + + (3) https://pip.pypa.io/en/stable/user_guide/#user-installs + + (4) https://docs.python.org/3/library/site.html#site.USER_BASE + + +File: pythonpackagingguide.info, Node: Installing packages for your project, Next: Using installed packages, Prev: Installing Pipenv, Up: Managing Application Dependencies + +2.2.2 Installing packages for your project +------------------------------------------ + +Pipenv manages dependencies on a per-project basis. To install +packages, change into your project’s directory (or just an empty +directory for this tutorial) and run: + + cd myproject + pipenv install requests + +Pipenv will install the Requests(1) library and create a ‘Pipfile’ for +you in your project’s directory. The *note Pipfile: 52. is used to +track which dependencies your project needs in case you need to +re-install them, such as when you share your project with others. You +should get output similar to this (although the exact paths shown will +vary): + + Creating a Pipfile for this project... + Creating a virtualenv for this project... + Using base prefix '/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6' + New python executable in ~/.local/share/virtualenvs/tmp-agwWamBd/bin/python3.6 + Also creating executable in ~/.local/share/virtualenvs/tmp-agwWamBd/bin/python + Installing setuptools, pip, wheel...done. + + Virtualenv location: ~/.local/share/virtualenvs/tmp-agwWamBd + Installing requests... + Collecting requests + Using cached requests-2.18.4-py2.py3-none-any.whl + Collecting idna<2.7,>=2.5 (from requests) + Using cached idna-2.6-py2.py3-none-any.whl + Collecting urllib3<1.23,>=1.21.1 (from requests) + Using cached urllib3-1.22-py2.py3-none-any.whl + Collecting chardet<3.1.0,>=3.0.2 (from requests) + Using cached chardet-3.0.4-py2.py3-none-any.whl + Collecting certifi>=2017.4.17 (from requests) + Using cached certifi-2017.7.27.1-py2.py3-none-any.whl + Installing collected packages: idna, urllib3, chardet, certifi, requests + Successfully installed certifi-2017.7.27.1 chardet-3.0.4 idna-2.6 requests-2.18.4 urllib3-1.22 + + Adding requests to Pipfile's [packages]... + + ---------- Footnotes ---------- + + (1) https://pypi.org/project/requests/ + + +File: pythonpackagingguide.info, Node: Using installed packages, Next: Next steps, Prev: Installing packages for your project, Up: Managing Application Dependencies + +2.2.3 Using installed packages +------------------------------ + +Now that Requests is installed you can create a simple ‘main.py’ file to +use it: + + import requests + + response = requests.get('https://httpbin.org/ip') + + print('Your IP is {0}'.format(response.json()['origin'])) + +Then you can run this script using ‘pipenv run’: + + pipenv run python main.py + +You should get output similar to this: + + Your IP is 8.8.8.8 + +Using ‘pipenv run’ ensures that your installed packages are available to +your script. It’s also possible to spawn a new shell that ensures all +commands have access to your installed packages with ‘pipenv shell’. + + +File: pythonpackagingguide.info, Node: Next steps, Next: Other Tools for Application Dependency Management, Prev: Using installed packages, Up: Managing Application Dependencies + +2.2.4 Next steps +---------------- + +Congratulations, you now know how to effectively manage dependencies and +development environments on a collaborative Python project! ✨ 🍰 ✨ + +If you’re interested in creating and distributing your own Python +packages, see the *note tutorial on packaging and distributing packages: +56. + +Note that when your application includes definitions of Python source +packages, they (and their dependencies) can be added to your ‘pipenv’ +environment with ‘pipenv install -e ’ +(e.g. ‘pipenv install -e .’ or ‘pipenv install -e src’). + + +File: pythonpackagingguide.info, Node: Other Tools for Application Dependency Management, Prev: Next steps, Up: Managing Application Dependencies + +2.2.5 Other Tools for Application Dependency Management +------------------------------------------------------- + +If you find this particular approach to managing application +dependencies isn’t working well for you or your use case, you may want +to explore these other tools and techniques, listed in alphabetical +order, to see if one of them is a better fit: + + * hatch(1) for opinionated coverage of even more steps in the project + management workflow, such as incrementing versions and creating new + skeleton projects from project templates. + + * micropipenv(2) for a lightweight wrapper around pip that supports + ‘requirements.txt’, Pipenv and Poetry lock files, or converting + them to pip-tools compatible output. Designed for containerized + Python applications, but not limited to them. + + * PDM(3) for a modern Python package management tool supporting PEP + 582(4) (replacing virtual environments with ‘__pypackages__’ + directory for package installation) and relying on standards such + as PEP 517(5) and PEP 621(6). + + * pip-tools(7) for creating a lock file of all dependencies from a + list of packages directly used in a project, and ensuring that only + those dependencies are installed. + + * Poetry(8) for a tool comparable in scope to Pipenv that focuses + more directly on use cases where the project being managed is + structured as a distributable Python package with a valid + ‘pyproject.toml’ file. By contrast, Pipenv explicitly avoids + making the assumption that the application being worked on will + support distribution as a ‘pip’-installable Python package. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/hatch + + (2) https://github.com/thoth-station/micropipenv + + (3) https://github.com/pdm-project/pdm + + (4) https://www.python.org/dev/peps/pep-0582 + + (5) https://www.python.org/dev/peps/pep-0517 + + (6) https://www.python.org/dev/peps/pep-0621 + + (7) https://github.com/jazzband/pip-tools + + (8) https://github.com/python-poetry/poetry + + +File: pythonpackagingguide.info, Node: Packaging Python Projects, Next: Creating Documentation, Prev: Managing Application Dependencies, Up: Tutorials + +2.3 Packaging Python Projects +============================= + +This tutorial walks you through how to package a simple Python project. +It will show you how to add the necessary files and structure to create +the package, how to build the package, and how to upload it to the +Python Package Index. + + Tip: If you have trouble running the commands in this tutorial, + please copy the command and its output, then open an issue(1) on + the packaging-problems(2) repository on GitHub. We’ll do our best + to help you! + +Some of the commands require a newer version of *note pip: 2b, so start +by making sure you have the latest version installed: (Unix/macOS) + python3 -m pip install --upgrade pip +(Windows) + py -m pip install --upgrade pip + +* Menu: + +* A simple project:: +* Creating the package files:: +* Creating a test directory:: +* Creating pyproject.toml: Creating pyproject toml. +* Configuring metadata:: +* Creating README.md: Creating README md. +* Creating a LICENSE:: +* Including other files:: +* Generating distribution archives:: +* Uploading the distribution archives:: +* Installing your newly uploaded package:: +* Next steps: Next steps<2>. + + ---------- Footnotes ---------- + + (1) +https://github.com/pypa/packaging-problems/issues/new?template=packaging_tutorial.yml&title=Trouble+with+the+packaging+tutorial&guide=https://packaging.python.org/tutorials/packaging-projects + + (2) https://github.com/pypa/packaging-problems + + +File: pythonpackagingguide.info, Node: A simple project, Next: Creating the package files, Up: Packaging Python Projects + +2.3.1 A simple project +---------------------- + +This tutorial uses a simple project named ‘example_package’. We +recommend following this tutorial as-is using this project, before +packaging your own project. + +Create the following file structure locally: + + packaging_tutorial/ + └── src/ + └── example_package/ + ├── __init__.py + └── example.py + +‘__init__.py’ is required to import the directory as a package, and +should be empty. + +‘example.py’ is an example of a module within the package that could +contain the logic (functions, classes, constants, etc.) of your +package. Open that file and enter the following content: + + def add_one(number): + return number + 1 + +If you are unfamiliar with Python’s *note modules: 5a. and *note import +packages: a, take a few minutes to read over the Python documentation +for packages and modules(1). + +Once you create this structure, you’ll want to run all of the commands +in this tutorial within the ‘packaging_tutorial’ directory. + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/tutorial/modules.html#packages + + +File: pythonpackagingguide.info, Node: Creating the package files, Next: Creating a test directory, Prev: A simple project, Up: Packaging Python Projects + +2.3.2 Creating the package files +-------------------------------- + +You will now add files that are used to prepare the project for +distribution. When you’re done, the project structure will look like +this: + + packaging_tutorial/ + ├── LICENSE + ├── pyproject.toml + ├── README.md + ├── setup.cfg + ├── src/ + │   └── example_package/ + │   ├── __init__.py + │   └── example.py + └── tests/ + + +File: pythonpackagingguide.info, Node: Creating a test directory, Next: Creating pyproject toml, Prev: Creating the package files, Up: Packaging Python Projects + +2.3.3 Creating a test directory +------------------------------- + +‘tests/’ is a placeholder for test files. Leave it empty for now. + + +File: pythonpackagingguide.info, Node: Creating pyproject toml, Next: Configuring metadata, Prev: Creating a test directory, Up: Packaging Python Projects + +2.3.4 Creating pyproject.toml +----------------------------- + +‘pyproject.toml’ tells build tools (like *note pip: 2b. and *note build: +5f.) what is required to build your project. This tutorial uses *note +setuptools: 2d, so open ‘pyproject.toml’ and enter the following +content: + + [build-system] + requires = ["setuptools>=42"] + build-backend = "setuptools.build_meta" + +‘build-system.requires’ gives a list of packages that are needed to +build your package. Listing something here will `only' make it +available during the build, not after it is installed. + +‘build-system.build-backend’ is the name of Python object that will be +used to perform the build. If you were to use a different build system, +such as *note flit: 60. or *note poetry: 61, those would go here, and +the configuration details would be completely different than the *note +setuptools: 2d. configuration described below. + +See PEP 517(1) and PEP 518(2) for background and details. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0517 + + (2) https://www.python.org/dev/peps/pep-0518 + + +File: pythonpackagingguide.info, Node: Configuring metadata, Next: Creating README md, Prev: Creating pyproject toml, Up: Packaging Python Projects + +2.3.5 Configuring metadata +-------------------------- + +There are two types of metadata: static and dynamic. + + * Static metadata (‘setup.cfg’): guaranteed to be the same every + time. This is simpler, easier to read, and avoids many common + errors, like encoding errors. + + * Dynamic metadata (‘setup.py’): possibly non-deterministic. Any + items that are dynamic or determined at install-time, as well as + extension modules or extensions to setuptools, need to go into + ‘setup.py’. + +Static metadata (‘setup.cfg’) should be preferred. Dynamic metadata +(‘setup.py’) should be used only as an escape hatch when absolutely +necessary. ‘setup.py’ used to be required, but can be omitted with +newer versions of setuptools and pip. (‘setup.cfg’ (static)) +‘setup.cfg’ is the configuration file for *note setuptools: 2d. It +tells setuptools about your package (such as the name and version) as +well as which code files to include. Eventually much of this +configuration may be able to move to ‘pyproject.toml’. + +Open ‘setup.cfg’ and enter the following content. Change the ‘name’ to +include your username; this ensures that you have a unique package name +and that your package doesn’t conflict with packages uploaded by other +people following this tutorial. + + [metadata] + name = example-package-YOUR-USERNAME-HERE + version = 0.0.1 + author = Example Author + author_email = author@example.com + description = A small example package + long_description = file: README.md + long_description_content_type = text/markdown + url = https://github.com/pypa/sampleproject + project_urls = + Bug Tracker = https://github.com/pypa/sampleproject/issues + classifiers = + Programming Language :: Python :: 3 + License :: OSI Approved :: MIT License + Operating System :: OS Independent + + [options] + package_dir = + = src + packages = find: + python_requires = >=3.6 + + [options.packages.find] + where = src + +There are a variety of metadata and options(1) supported here. This is +in configparser(2) format; do not place quotes around values. This +example package uses a relatively minimal set of ‘metadata’: + + - ‘name’ is the `distribution name' of your package. This can be any + name as long as it only contains letters, numbers, ‘_’ , and ‘-’. + It also must not already be taken on pypi.org. `Be sure to update + this with your username,' as this ensures you won’t try to upload a + package with the same name as one which already exists. + + - ‘version’ is the package version. See PEP 440(3) for more details + on versions. You can use ‘file:’ or ‘attr:’ directives to read + from a file or package attribute. + + - ‘author’ and ‘author_email’ are used to identify the author of the + package. + + - ‘description’ is a short, one-sentence summary of the package. + + - ‘long_description’ is a detailed description of the package. This + is shown on the package detail page on the Python Package Index. + In this case, the long description is loaded from ‘README.md’ + (which is a common pattern) using the ‘file:’ directive. + + - ‘long_description_content_type’ tells the index what type of markup + is used for the long description. In this case, it’s Markdown. + + - ‘url’ is the URL for the homepage of the project. For many + projects, this will just be a link to GitHub, GitLab, Bitbucket, or + similar code hosting service. + + - ‘project_urls’ lets you list any number of extra links to show on + PyPI. Generally this could be to documentation, issue trackers, + etc. + + - ‘classifiers’ gives the index and *note pip: 2b. some additional + metadata about your package. In this case, the package is only + compatible with Python 3, is licensed under the MIT license, and is + OS-independent. You should always include at least which + version(s) of Python your package works on, which license your + package is available under, and which operating systems your + package will work on. For a complete list of classifiers, see + ‘https://pypi.org/classifiers/’. + +In the ‘options’ category, we have controls for setuptools itself: + + - ‘package_dir’ is a mapping of package names and directories. An + empty package name represents the “root package” — the directory in + the project that contains all Python source files for the package — + so in this case the ‘src’ directory is designated the root package. + + - ‘packages’ is a list of all Python *note import packages: a. that + should be included in the *note distribution package: b. Instead + of listing each package manually, we can use the ‘find:’ directive + to automatically discover all packages and subpackages and + ‘options.packages.find’ to specify the ‘package_dir’ to use. In + this case, the list of packages will be ‘example_package’ as that’s + the only package present. + + - ‘python_requires’ gives the versions of Python supported by your + project. Installers like *note pip: 2b. will look back through + older versions of packages until it finds one that has a matching + Python version. + +There are many more than the ones mentioned here. See *note Packaging +and distributing projects: 6. for more details. (‘setup.py’ (dynamic)) +‘setup.py’ is the build script for *note setuptools: 2d. It tells +setuptools about your package (such as the name and version) as well as +which code files to include. + +Open ‘setup.py’ and enter the following content. Change the ‘name’ to +include your username; this ensures that you have a unique package name +and that your package doesn’t conflict with packages uploaded by other +people following this tutorial. + + import setuptools + + with open("README.md", "r", encoding="utf-8") as fh: + long_description = fh.read() + + setuptools.setup( + name="example-package-YOUR-USERNAME-HERE", + version="0.0.1", + author="Example Author", + author_email="author@example.com", + description="A small example package", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://github.com/pypa/sampleproject", + project_urls={ + "Bug Tracker": "https://github.com/pypa/sampleproject/issues", + }, + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], + package_dir={"": "src"}, + packages=setuptools.find_packages(where="src"), + python_requires=">=3.6", + ) + +‘setup()’ takes several arguments. This example package uses a +relatively minimal set: + + - ‘name’ is the `distribution name' of your package. This can be any + name as long as it only contains letters, numbers, ‘_’ , and ‘-’. + It also must not already be taken on pypi.org. `Be sure to update + this with your username,' as this ensures you won’t try to upload a + package with the same name as one which already exists. + + - ‘version’ is the package version. See PEP 440(4) for more details + on versions. + + - ‘author’ and ‘author_email’ are used to identify the author of the + package. + + - ‘description’ is a short, one-sentence summary of the package. + + - ‘long_description’ is a detailed description of the package. This + is shown on the package detail page on the Python Package Index. + In this case, the long description is loaded from ‘README.md’, + which is a common pattern. + + - ‘long_description_content_type’ tells the index what type of markup + is used for the long description. In this case, it’s Markdown. + + - ‘url’ is the URL for the homepage of the project. For many + projects, this will just be a link to GitHub, GitLab, Bitbucket, or + similar code hosting service. + + - ‘project_urls’ lets you list any number of extra links to show on + PyPI. Generally this could be to documentation, issue trackers, + etc. + + - ‘classifiers’ gives the index and *note pip: 2b. some additional + metadata about your package. In this case, the package is only + compatible with Python 3, is licensed under the MIT license, and is + OS-independent. You should always include at least which + version(s) of Python your package works on, which license your + package is available under, and which operating systems your + package will work on. For a complete list of classifiers, see + ‘https://pypi.org/classifiers/’. + + - ‘package_dir’ is a dictionary with package names for keys and + directories for values. An empty package name represents the “root + package” — the directory in the project that contains all Python + source files for the package — so in this case the ‘src’ directory + is designated the root package. + + - ‘packages’ is a list of all Python *note import packages: a. that + should be included in the *note distribution package: b. Instead + of listing each package manually, we can use ‘find_packages()’ to + automatically discover all packages and subpackages under + ‘package_dir’. In this case, the list of packages will be + ‘example_package’ as that’s the only package present. + + - ‘python_requires’ gives the versions of Python supported by your + project. Installers like *note pip: 2b. will look back though + older versions of packages until it finds one that has a matching + Python version. + +There are many more than the ones mentioned here. See *note Packaging +and distributing projects: 6. for more details. + + Warning: You may see some existing projects or other Python + packaging tutorials that import their ‘setup’ function from + ‘distutils.core’ rather than ‘setuptools’. This is a legacy + approach that installers support for backwards compatibility + purposes (5), but using the legacy ‘distutils’ API directly in new + projects is strongly discouraged, since ‘distutils’ is deprecated + as per PEP 632(6) and will be removed from the standard library in + Python 3.12. + + ---------- Footnotes ---------- + + (1) +https://setuptools.readthedocs.io/en/latest/userguide/declarative_config.html + + (2) https://docs.python.org/3/library/configparser.html + + (3) https://www.python.org/dev/peps/pep-0440 + + (4) https://www.python.org/dev/peps/pep-0440 + + (5) (1) Some legacy Python environments may not have ‘setuptools’ +pre-installed, and the operators of those environments may still be +requiring users to install packages by running ‘setup.py install’ +commands, rather than providing an installer like ‘pip’ that +automatically installs required build dependendencies. These +environments will not be able to use many published packages until the +environment is updated to provide an up to date Python package +installation client (e.g. by running ‘python -m ensurepip’). + + (6) https://www.python.org/dev/peps/pep-0632 + + +File: pythonpackagingguide.info, Node: Creating README md, Next: Creating a LICENSE, Prev: Configuring metadata, Up: Packaging Python Projects + +2.3.6 Creating README.md +------------------------ + +Open ‘README.md’ and enter the following content. You can customize +this if you’d like. + + # Example Package + + This is a simple example package. You can use + [Github-flavored Markdown](https://guides.github.com/features/mastering-markdown/) + to write your content. + +Because our configuration loads ‘README.md’ to provide a +‘long_description’, ‘README.md’ must be included along with your code +when you *note generate a source distribution: 64. Newer versions of +*note setuptools: 2d. will do this automatically. + + +File: pythonpackagingguide.info, Node: Creating a LICENSE, Next: Including other files, Prev: Creating README md, Up: Packaging Python Projects + +2.3.7 Creating a LICENSE +------------------------ + +It’s important for every package uploaded to the Python Package Index to +include a license. This tells users who install your package the terms +under which they can use your package. For help picking a license, see +‘https://choosealicense.com/’. Once you have chosen a license, open +‘LICENSE’ and enter the license text. For example, if you had chosen +the MIT license: + + Copyright (c) 2018 The Python Packaging Authority + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + +File: pythonpackagingguide.info, Node: Including other files, Next: Generating distribution archives, Prev: Creating a LICENSE, Up: Packaging Python Projects + +2.3.8 Including other files +--------------------------- + +The files listed above will be included automatically in your *note +source distribution: 3d. If you want to control what goes in this +explicitly, see *note Including files in source distributions with +MANIFEST.in: 67. + +The final *note built distribution: 68. will have the Python files in +the discovered or listed Python packages. If you want to control what +goes here, such as to add data files, see Including Data Files(1) from +the setuptools docs(2). + + ---------- Footnotes ---------- + + (1) https://setuptools.pypa.io/en/latest/userguide/datafiles.html + + (2) https://setuptools.pypa.io/en/latest/index.html + + +File: pythonpackagingguide.info, Node: Generating distribution archives, Next: Uploading the distribution archives, Prev: Including other files, Up: Packaging Python Projects + +2.3.9 Generating distribution archives +-------------------------------------- + +The next step is to generate *note distribution packages: b. for the +package. These are archives that are uploaded to the Python Package +Index and can be installed by *note pip: 2b. + +Make sure you have the latest version of PyPA’s *note build: 5f. +installed: (Unix/macOS) + python3 -m pip install --upgrade build +(Windows) + py -m pip install --upgrade build + + Tip: If you have trouble installing these, see the *note Installing + Packages: 23. tutorial. + +Now run this command from the same directory where ‘pyproject.toml’ is +located: (Unix/macOS) + python3 -m build +(Windows) + py -m build + +This command should output a lot of text and once completed should +generate two files in the ‘dist’ directory: + + dist/ + example-package-YOUR-USERNAME-HERE-0.0.1-py3-none-any.whl + example-package-YOUR-USERNAME-HERE-0.0.1.tar.gz + +The ‘tar.gz’ file is a *note source archive: 6a. whereas the ‘.whl’ file +is a *note built distribution: 68. Newer *note pip: 2b. versions +preferentially install built distributions, but will fall back to source +archives if needed. You should always upload a source archive and +provide built archives for the platforms your project is compatible +with. In this case, our example package is compatible with Python on +any platform so only one built distribution is needed. + + +File: pythonpackagingguide.info, Node: Uploading the distribution archives, Next: Installing your newly uploaded package, Prev: Generating distribution archives, Up: Packaging Python Projects + +2.3.10 Uploading the distribution archives +------------------------------------------ + +Finally, it’s time to upload your package to the Python Package Index! + +The first thing you’ll need to do is register an account on TestPyPI, +which is a separate instance of the package index intended for testing +and experimentation. It’s great for things like this tutorial where we +don’t necessarily want to upload to the real index. To register an +account, go to ‘https://test.pypi.org/account/register/’ and complete +the steps on that page. You will also need to verify your email address +before you’re able to upload any packages. For more details, see *note +Using TestPyPI: 6c. + +To securely upload your project, you’ll need a PyPI API token(1). +Create one at ‘https://test.pypi.org/manage/account/#api-tokens’, +setting the “Scope” to “Entire account”. `Don’t close the page until +you have copied and saved the token — you won’t see that token again.' + +Now that you are registered, you can use *note twine: 6d. to upload the +distribution packages. You’ll need to install Twine: (Unix/macOS) + python3 -m pip install --upgrade twine +(Windows) + py -m pip install --upgrade twine + +Once installed, run Twine to upload all of the archives under ‘dist’: +(Unix/macOS) + python3 -m twine upload --repository testpypi dist/* +(Windows) + py -m twine upload --repository testpypi dist/* + +You will be prompted for a username and password. For the username, use +‘__token__’. For the password, use the token value, including the +‘pypi-’ prefix. + +After the command completes, you should see output similar to this: + + Uploading distributions to https://test.pypi.org/legacy/ + Enter your username: [your username] + Enter your password: + Uploading example-package-YOUR-USERNAME-HERE-0.0.1-py3-none-any.whl + 100%|█████████████████████| 4.65k/4.65k [00:01<00:00, 2.88kB/s] + Uploading example-package-YOUR-USERNAME-HERE-0.0.1.tar.gz + 100%|█████████████████████| 4.25k/4.25k [00:01<00:00, 3.05kB/s] + +Once uploaded your package should be viewable on TestPyPI, for example, +‘https://test.pypi.org/project/example-package-YOUR-USERNAME-HERE’ + + ---------- Footnotes ---------- + + (1) https://test.pypi.org/help/#apitoken + + +File: pythonpackagingguide.info, Node: Installing your newly uploaded package, Next: Next steps<2>, Prev: Uploading the distribution archives, Up: Packaging Python Projects + +2.3.11 Installing your newly uploaded package +--------------------------------------------- + +You can use *note pip: 2b. to install your package and verify that it +works. Create a *note virtual environment: 31. and install your package +from TestPyPI: (Unix/macOS) + python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps example-package-YOUR-USERNAME-HERE +(Windows) + py -m pip install --index-url https://test.pypi.org/simple/ --no-deps example-package-YOUR-USERNAME-HERE + +Make sure to specify your username in the package name! + +pip should install the package from TestPyPI and the output should look +something like this: + + Collecting example-package-YOUR-USERNAME-HERE + Downloading https://test-files.pythonhosted.org/packages/.../example-package-YOUR-USERNAME-HERE-0.0.1-py3-none-any.whl + Installing collected packages: example-package-YOUR-USERNAME-HERE + Successfully installed example-package-YOUR-USERNAME-HERE-0.0.1 + + Note: This example uses ‘--index-url’ flag to specify TestPyPI + instead of live PyPI. Additionally, it specifies ‘--no-deps’. + Since TestPyPI doesn’t have the same packages as the live PyPI, + it’s possible that attempting to install dependencies may fail or + install something unexpected. While our example package doesn’t + have any dependencies, it’s a good practice to avoid installing + dependencies when using TestPyPI. + +You can test that it was installed correctly by importing the package. +Make sure you’re still in your virtual environment, then run Python: +(Unix/macOS) + python3 +(Windows) + py + +and import the package: + + >>> from example_package import example + >>> example.add_one(2) + 3 + +Note that the *note import package: a. is ‘example_package’ regardless +of what ‘name’ you gave your *note distribution package: b. in +‘setup.cfg’ or ‘setup.py’ (in this case, +‘example-package-YOUR-USERNAME-HERE’). + + +File: pythonpackagingguide.info, Node: Next steps<2>, Prev: Installing your newly uploaded package, Up: Packaging Python Projects + +2.3.12 Next steps +----------------- + +`Congratulations, you’ve packaged and distributed a Python project!' ✨ +🍰 ✨ + +Keep in mind that this tutorial showed you how to upload your package to +Test PyPI, which isn’t a permanent storage. The Test system +occasionally deletes packages and accounts. It is best to use TestPyPI +for testing and experiments like this tutorial. + +When you are ready to upload a real package to the Python Package Index +you can do much the same as you did in this tutorial, but with these +important differences: + + * Choose a memorable and unique name for your package. You don’t + have to append your username as you did in the tutorial. + + * Register an account on ‘https://pypi.org’ - note that these are two + separate servers and the login details from the test server are not + shared with the main server. + + * Use ‘twine upload dist/*’ to upload your package and enter your + credentials for the account you registered on the real PyPI. Now + that you’re uploading the package in production, you don’t need to + specify ‘--repository’; the package will upload to + ‘https://pypi.org/’ by default. + + * Install your package from the real PyPI using ‘python3 -m pip + install [your-package]’. + +At this point if you want to read more on packaging Python libraries +here are some things you can do: + + * Read more about using *note setuptools: 2d. to package libraries in + *note Packaging and distributing projects: 6. + + * Read about *note Packaging binary extensions: 70. + + * Consider alternatives to *note setuptools: 2d. such as *note flit: + 60, *note hatch: 71, and *note poetry: 61. + +__________________________________________________________________ + + +File: pythonpackagingguide.info, Node: Creating Documentation, Prev: Packaging Python Projects, Up: Tutorials + +2.4 Creating Documentation +========================== + +This section covers the basics of how to create documentation using +Sphinx(1) and host the documentation for free in Read The Docs(2). + +* Menu: + +* Installing Sphinx:: +* Getting Started With Sphinx:: +* Other Sources:: + + ---------- Footnotes ---------- + + (1) https://www.sphinx-doc.org + + (2) https://readthedocs.org/ + + +File: pythonpackagingguide.info, Node: Installing Sphinx, Next: Getting Started With Sphinx, Up: Creating Documentation + +2.4.1 Installing Sphinx +----------------------- + +Use ‘pip’ to install Sphinx: (Unix/macOS) + python3 -m pip install -U sphinx +(Windows) + py -m pip install -U sphinx + +For other installation methods, see this installation guide(1) by +Sphinx. + + ---------- Footnotes ---------- + + (1) https://www.sphinx-doc.org/en/master/usage/installation.html + + +File: pythonpackagingguide.info, Node: Getting Started With Sphinx, Next: Other Sources, Prev: Installing Sphinx, Up: Creating Documentation + +2.4.2 Getting Started With Sphinx +--------------------------------- + +Create a ‘docs’ directory inside your project to hold your +documentation: + + cd /path/to/project + mkdir docs + +Run ‘sphinx-quickstart’ inside the ‘docs’ directory: + + cd docs + sphinx-quickstart + +This sets up a source directory, walks you through some basic +configurations, and creates an ‘index.rst’ file as well as a ‘conf.py’ +file. + +You can add some information about your project in ‘index.rst’, then +build them: + + make html + +For more details on the build process, see this guide(1) by Read The +Docs. + + ---------- Footnotes ---------- + + (1) https://docs.readthedocs.io/en/latest/intro/import-guide.html + + +File: pythonpackagingguide.info, Node: Other Sources, Prev: Getting Started With Sphinx, Up: Creating Documentation + +2.4.3 Other Sources +------------------- + +For a more detailed guide on how to use Sphinx and reStructuredText, +please see this documentation tutorial(1) on Hitchhiker’s Guide to +Python. + + ---------- Footnotes ---------- + + (1) https://docs.python-guide.org/writing/documentation/ + + +File: pythonpackagingguide.info, Node: Guides, Next: Discussions, Prev: Tutorials, Up: Top + +3 Guides +******** + +`Guides' are focused on accomplishing a specific task and assume that +you are already familiar with the basics of Python packaging. If you’re +looking for an introduction to packaging, see *note Tutorials: 20. + +* Menu: + +* Installing packages using pip and virtual environments:: +* Installing stand alone command line tools:: +* Installing pip/setuptools/wheel with Linux Package Managers:: +* Installing scientific packages:: +* Multi-version installs:: +* Package index mirrors and caches:: +* Hosting your own simple repository:: +* Packaging and distributing projects:: +* Including files in source distributions with MANIFEST.in: Including files in source distributions with MANIFEST in. +* Single-sourcing the package version:: +* Supporting multiple Python versions:: +* Dropping support for older Python versions:: +* Packaging binary extensions:: +* Supporting Windows using Appveyor:: +* Packaging namespace packages:: +* Creating and discovering plugins:: +* Migrating to PyPI.org: Migrating to PyPI org. +* Using TestPyPI: Using TestPyPI<2>. +* Making a PyPI-friendly README:: +* Publishing package distribution releases using GitHub Actions CI/CD workflows:: +* Tool recommendations:: +* Analyzing PyPI package downloads:: + + +File: pythonpackagingguide.info, Node: Installing packages using pip and virtual environments, Next: Installing stand alone command line tools, Up: Guides + +3.1 Installing packages using pip and virtual environments +========================================================== + +This guide discusses how to install packages using *note pip: 2b. and a +virtual environment manager: either *note venv: 7e. for Python 3 or +*note virtualenv: 32. for Python 2. These are the lowest-level tools +for managing Python packages and are recommended if higher-level tools +do not suit your needs. + + Note: This doc uses the term `package' to refer to a *note + Distribution Package: b. which is different from an *note Import + Package: a. that which is used to import modules in your Python + source code. + +* Menu: + +* Installing pip:: +* Installing virtualenv:: +* Creating a virtual environment:: +* Activating a virtual environment:: +* Leaving the virtual environment:: +* Installing packages:: +* Installing specific versions:: +* Installing extras:: +* Installing from source:: +* Installing from version control systems:: +* Installing from local archives: Installing from local archives<2>. +* Using other package indexes:: +* Upgrading packages: Upgrading packages<2>. +* Using requirements files:: +* Freezing dependencies:: + + +File: pythonpackagingguide.info, Node: Installing pip, Next: Installing virtualenv, Up: Installing packages using pip and virtual environments + +3.1.1 Installing pip +-------------------- + +*note pip: 2b. is the reference Python package manager. It’s used to +install and update packages. You’ll need to make sure you have the +latest version of pip installed. (Unix/macOS) Debian and most other +distributions include a python-pip(1) package; if you want to use the +Linux distribution-provided versions of pip, see *note Installing +pip/setuptools/wheel with Linux Package Managers: 2c. + +You can also install pip yourself to ensure you have the latest version. +It’s recommended to use the system pip to bootstrap a user installation +of pip: + + python3 -m pip install --user --upgrade pip + + python3 -m pip --version + +Afterwards, you should have the latest version of pip installed in your +user site: + + pip 21.1.3 from $HOME/.local/lib/python3.9/site-packages (python 3.9) +(Windows) The Python installers for Windows include pip. You can make +sure that pip is up-to-date by running: + + py -m pip install --upgrade pip + + py -m pip --version + +Afterwards, you should have the latest version of pip: + + pip 21.1.3 from c:\python39\lib\site-packages (Python 3.9.4) + + ---------- Footnotes ---------- + + (1) https://packages.debian.org/stable/python/python3-pip + + +File: pythonpackagingguide.info, Node: Installing virtualenv, Next: Creating a virtual environment, Prev: Installing pip, Up: Installing packages using pip and virtual environments + +3.1.2 Installing virtualenv +--------------------------- + + Note: If you are using Python 3.3 or newer, the venv(1) module is + the preferred way to create and manage virtual environments. venv + is included in the Python standard library and requires no + additional installation. If you are using venv, you may skip this + section. + +*note virtualenv: 32. is used to manage Python packages for different +projects. Using virtualenv allows you to avoid installing Python +packages globally which could break system tools or other projects. You +can install virtualenv using pip. (Unix/macOS) + python3 -m pip install --user virtualenv +(Windows) + py -m pip install --user virtualenv + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/library/venv.html#module-venv + + +File: pythonpackagingguide.info, Node: Creating a virtual environment, Next: Activating a virtual environment, Prev: Installing virtualenv, Up: Installing packages using pip and virtual environments + +3.1.3 Creating a virtual environment +------------------------------------ + +*note venv: 7e. (for Python 3) and *note virtualenv: 32. (for Python 2) +allow you to manage separate package installations for different +projects. They essentially allow you to create a “virtual” isolated +Python installation and install packages into that virtual installation. +When you switch projects, you can simply create a new virtual +environment and not have to worry about breaking the packages installed +in the other environments. It is always recommended to use a virtual +environment while developing Python applications. + +To create a virtual environment, go to your project’s directory and run +venv. If you are using Python 2, replace ‘venv’ with ‘virtualenv’ in +the below commands. (Unix/macOS) + python3 -m venv env +(Windows) + py -m venv env + +The second argument is the location to create the virtual environment. +Generally, you can just create this in your project and call it ‘env’. + +venv will create a virtual Python installation in the ‘env’ folder. + + Note: You should exclude your virtual environment directory from + your version control system using ‘.gitignore’ or similar. + + +File: pythonpackagingguide.info, Node: Activating a virtual environment, Next: Leaving the virtual environment, Prev: Creating a virtual environment, Up: Installing packages using pip and virtual environments + +3.1.4 Activating a virtual environment +-------------------------------------- + +Before you can start installing or using packages in your virtual +environment you’ll need to `activate' it. Activating a virtual +environment will put the virtual environment-specific ‘python’ and ‘pip’ +executables into your shell’s ‘PATH’. (Unix/macOS) + source env/bin/activate +(Windows) + .\env\Scripts\activate + +You can confirm you’re in the virtual environment by checking the +location of your Python interpreter: (Unix/macOS) + which python +(Windows) + where python + +It should be in the ‘env’ directory: (Unix/macOS) + .../env/bin/python +(Windows) + ...\env\Scripts\python.exe + +As long as your virtual environment is activated pip will install +packages into that specific environment and you’ll be able to import and +use packages in your Python application. + + +File: pythonpackagingguide.info, Node: Leaving the virtual environment, Next: Installing packages, Prev: Activating a virtual environment, Up: Installing packages using pip and virtual environments + +3.1.5 Leaving the virtual environment +------------------------------------- + +If you want to switch projects or otherwise leave your virtual +environment, simply run: + + deactivate + +If you want to re-enter the virtual environment just follow the same +instructions above about activating a virtual environment. There’s no +need to re-create the virtual environment. + + +File: pythonpackagingguide.info, Node: Installing packages, Next: Installing specific versions, Prev: Leaving the virtual environment, Up: Installing packages using pip and virtual environments + +3.1.6 Installing packages +------------------------- + +Now that you’re in your virtual environment you can install packages. +Let’s install the Requests(1) library from the *note Python Package +Index (PyPI): 39.: (Unix/macOS) + python3 -m pip install requests +(Windows) + py -m pip install requests + +pip should download requests and all of its dependencies and install +them: + + Collecting requests + Using cached requests-2.18.4-py2.py3-none-any.whl + Collecting chardet<3.1.0,>=3.0.2 (from requests) + Using cached chardet-3.0.4-py2.py3-none-any.whl + Collecting urllib3<1.23,>=1.21.1 (from requests) + Using cached urllib3-1.22-py2.py3-none-any.whl + Collecting certifi>=2017.4.17 (from requests) + Using cached certifi-2017.7.27.1-py2.py3-none-any.whl + Collecting idna<2.7,>=2.5 (from requests) + Using cached idna-2.6-py2.py3-none-any.whl + Installing collected packages: chardet, urllib3, certifi, idna, requests + Successfully installed certifi-2017.7.27.1 chardet-3.0.4 idna-2.6 requests-2.18.4 urllib3-1.22 + + ---------- Footnotes ---------- + + (1) https://pypi.org/project/requests/ + + +File: pythonpackagingguide.info, Node: Installing specific versions, Next: Installing extras, Prev: Installing packages, Up: Installing packages using pip and virtual environments + +3.1.7 Installing specific versions +---------------------------------- + +pip allows you to specify which version of a package to install using +*note version specifiers: 3b. For example, to install a specific +version of ‘requests’: (Unix/macOS) + python3 -m pip install requests==2.18.4 +(Windows) + py -m pip install requests==2.18.4 + +To install the latest ‘2.x’ release of requests: (Unix/macOS) + python3 -m pip install requests>=2.0.0,<3.0.0 +(Windows) + py -m pip install requests>=2.0.0,<3.0.0 + +To install pre-release versions of packages, use the ‘--pre’ flag: +(Unix/macOS) + python3 -m pip install --pre requests +(Windows) + py -m pip install --pre requests + + +File: pythonpackagingguide.info, Node: Installing extras, Next: Installing from source, Prev: Installing specific versions, Up: Installing packages using pip and virtual environments + +3.1.8 Installing extras +----------------------- + +Some packages have optional extras(1). You can tell pip to install +these by specifying the extra in brackets: (Unix/macOS) + python3 -m pip install requests[security] +(Windows) + py -m pip install requests[security] + + ---------- Footnotes ---------- + + (1) +https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#optional-dependencies + + +File: pythonpackagingguide.info, Node: Installing from source, Next: Installing from version control systems, Prev: Installing extras, Up: Installing packages using pip and virtual environments + +3.1.9 Installing from source +---------------------------- + +pip can install a package directly from source, for example: +(Unix/macOS) + cd google-auth + python3 -m pip install . +(Windows) + cd google-auth + py -m pip install . + +Additionally, pip can install packages from source in development +mode(1), meaning that changes to the source directory will immediately +affect the installed package without needing to re-install: (Unix/macOS) + python3 -m pip install --editable . +(Windows) + py -m pip install --editable . + + ---------- Footnotes ---------- + + (1) +https://setuptools.pypa.io/en/latest/userguide/development_mode.html + + +File: pythonpackagingguide.info, Node: Installing from version control systems, Next: Installing from local archives<2>, Prev: Installing from source, Up: Installing packages using pip and virtual environments + +3.1.10 Installing from version control systems +---------------------------------------------- + +pip can install packages directly from their version control system. +For example, you can install directly from a git repository: + + git+https://github.com/GoogleCloudPlatform/google-auth-library-python.git#egg=google-auth + +For more information on supported version control systems and syntax, +see pip’s documentation on VCS Support(1). + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/cli/pip_install/#vcs-support + + +File: pythonpackagingguide.info, Node: Installing from local archives<2>, Next: Using other package indexes, Prev: Installing from version control systems, Up: Installing packages using pip and virtual environments + +3.1.11 Installing from local archives +------------------------------------- + +If you have a local copy of a *note Distribution Package: b.’s archive +(a zip, wheel, or tar file) you can install it directly with pip: +(Unix/macOS) + python3 -m pip install requests-2.18.4.tar.gz +(Windows) + py -m pip install requests-2.18.4.tar.gz + +If you have a directory containing archives of multiple packages, you +can tell pip to look for packages there and not to use the *note Python +Package Index (PyPI): 39. at all: (Unix/macOS) + python3 -m pip install --no-index --find-links=/local/dir/ requests +(Windows) + py -m pip install --no-index --find-links=/local/dir/ requests + +This is useful if you are installing packages on a system with limited +connectivity or if you want to strictly control the origin of +distribution packages. + + +File: pythonpackagingguide.info, Node: Using other package indexes, Next: Upgrading packages<2>, Prev: Installing from local archives<2>, Up: Installing packages using pip and virtual environments + +3.1.12 Using other package indexes +---------------------------------- + +If you want to download packages from a different index than the *note +Python Package Index (PyPI): 39, you can use the ‘--index-url’ flag: +(Unix/macOS) + python3 -m pip install --index-url http://index.example.com/simple/ SomeProject +(Windows) + py -m pip install --index-url http://index.example.com/simple/ SomeProject + +If you want to allow packages from both the *note Python Package Index +(PyPI): 39. and a separate index, you can use the ‘--extra-index-url’ +flag instead: (Unix/macOS) + python3 -m pip install --extra-index-url http://index.example.com/simple/ SomeProject +(Windows) + py -m pip install --extra-index-url http://index.example.com/simple/ SomeProject + + +File: pythonpackagingguide.info, Node: Upgrading packages<2>, Next: Using requirements files, Prev: Using other package indexes, Up: Installing packages using pip and virtual environments + +3.1.13 Upgrading packages +------------------------- + +pip can upgrade packages in-place using the ‘--upgrade’ flag. For +example, to install the latest version of ‘requests’ and all of its +dependencies: (Unix/macOS) + python3 -m pip install --upgrade requests +(Windows) + py -m pip install --upgrade requests + + +File: pythonpackagingguide.info, Node: Using requirements files, Next: Freezing dependencies, Prev: Upgrading packages<2>, Up: Installing packages using pip and virtual environments + +3.1.14 Using requirements files +------------------------------- + +Instead of installing packages individually, pip allows you to declare +all dependencies in a Requirements File(1). For example you could +create a ‘requirements.txt’ file containing: + + requests==2.18.4 + google-auth==1.1.0 + +And tell pip to install all of the packages in this file using the ‘-r’ +flag: (Unix/macOS) + python3 -m pip install -r requirements.txt +(Windows) + py -m pip install -r requirements.txt + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/user_guide/#requirements-files + + +File: pythonpackagingguide.info, Node: Freezing dependencies, Prev: Using requirements files, Up: Installing packages using pip and virtual environments + +3.1.15 Freezing dependencies +---------------------------- + +Pip can export a list of all installed packages and their versions using +the ‘freeze’ command: (Unix/macOS) + python3 -m pip freeze +(Windows) + py -m pip freeze + +Which will output a list of package specifiers such as: + + cachetools==2.0.1 + certifi==2017.7.27.1 + chardet==3.0.4 + google-auth==1.1.1 + idna==2.6 + pyasn1==0.3.6 + pyasn1-modules==0.1.4 + requests==2.18.4 + rsa==3.4.2 + six==1.11.0 + urllib3==1.22 + +This is useful for creating Requirements Files(1) that can re-create the +exact versions of all packages installed in an environment. + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/user_guide/#requirements-files + + +File: pythonpackagingguide.info, Node: Installing stand alone command line tools, Next: Installing pip/setuptools/wheel with Linux Package Managers, Prev: Installing packages using pip and virtual environments, Up: Guides + +3.2 Installing stand alone command line tools +============================================= + +Many packages provide command line applications. Examples of such +packages are mypy(1), flake8(2), black(3), and *note Pipenv: 36. + +Usually you want to be able to access these applications from anywhere +on your system, but installing packages and their dependencies to the +same global environment can cause version conflicts and break +dependencies the operating system has on Python packages. + +*note pipx: 91. solves this by creating a virtual environment for each +package, while also ensuring that its applications are accessible +through a directory that is on your ‘$PATH’. This allows each package +to be upgraded or uninstalled without causing conflicts with other +packages, and allows you to safely run the applications from anywhere. + + Note: pipx only works with Python 3.6+. + +pipx is installed with pip: (Unix/macOS) + python3 -m pip install --user pipx + python3 -m pipx ensurepath +(Windows) + py -m pip install --user pipx + py -m pipx ensurepath + + Note: ‘ensurepath’ ensures that the application directory is on + your ‘$PATH’. You may need to restart your terminal for this + update to take effect. + +Now you can install packages with ‘pipx install’ and run the package’s +applications(s) from anywhere. + + $ pipx install PACKAGE + $ PACKAGE_APPLICATION [ARGS] + +For example: + + $ pipx install cowsay + installed package cowsay 2.0, Python 3.6.2+ + These binaries are now globally available + - cowsay + done! ✨ 🌟 ✨ + $ cowsay moo + ___ + < moo > + === + \ + \ + ^__^ + (oo)\_______ + (__)\ )\/ ||----w | + || || + +To see a list of packages installed with pipx and which applications are +available, use ‘pipx list’: + + $ pipx list + venvs are in /Users/user/.local/pipx/venvs + symlinks to binaries are in /Users/user/.local/bin + package black 18.9b0, Python 3.6.2+ + - black + - blackd + package cowsay 2.0, Python 3.6.2+ + - cowsay + package mypy 0.660, Python 3.6.2+ + - dmypy + - mypy + - stubgen + package nox 2018.10.17, Python 3.6.2+ + - nox + - tox-to-nox + +To upgrade or uninstall a package: + + pipx upgrade PACKAGE + pipx uninstall PACKAGE + +pipx can be upgraded or uninstalled with pip: (Unix/macOS) + python3 -m pip install -U pipx + python3 -m pip uninstall pipx +(Windows) + py -m pip install -U pipx + py -m pip uninstall pipx + +pipx also allows you to install and run the latest version of an +application in a temporary, ephemeral environment. For example: + + pipx run cowsay moooo + +To see the full list of commands pipx offers, run: + + pipx --help + +You can learn more about pipx at ‘https://pypa.github.io/pipx/’. + + ---------- Footnotes ---------- + + (1) https://github.com/python/mypy + + (2) https://github.com/PyCQA/flake8 + + (3) https://github.com/psf/black + + +File: pythonpackagingguide.info, Node: Installing pip/setuptools/wheel with Linux Package Managers, Next: Installing scientific packages, Prev: Installing stand alone command line tools, Up: Guides + +3.3 Installing pip/setuptools/wheel with Linux Package Managers +=============================================================== + + +Page Status: Incomplete + + +Last Reviewed: 2021-07-26 + +This section covers how to install *note pip: 2b, *note setuptools: 2d, +and *note wheel: 2e. using Linux package managers. + +If you’re using a Python that was downloaded from python.org(1), then +this section does not apply. See the *note Requirements for Installing +Packages: 26. section instead. + +Note that it’s common for the versions of *note pip: 2b, *note +setuptools: 2d, and *note wheel: 2e. supported by a specific Linux +Distribution to be outdated by the time it’s released to the public, and +updates generally only occur for security reasons, not for feature +updates. For certain Distributions, there are additional repositories +that can be enabled to provide newer versions. The repositories we know +about are explained below. + +Also note that it’s somewhat common for Distributions to apply patches +for the sake of security and normalization to their own standards. In +some cases, this can lead to bugs or unexpected behaviors that vary from +the original unpatched versions. When this is known, we will make note +of it below. + +* Menu: + +* Fedora:: +* CentOS/RHEL:: +* openSUSE:: +* Debian/Ubuntu:: +* Arch Linux:: + + ---------- Footnotes ---------- + + (1) https://www.python.org + + +File: pythonpackagingguide.info, Node: Fedora, Next: CentOS/RHEL, Up: Installing pip/setuptools/wheel with Linux Package Managers + +3.3.1 Fedora +------------ + + sudo dnf install python3-pip python3-wheel + +To learn more about Python in Fedora, please visit the official Fedora +docs(1), Python Classroom(2) or Fedora Loves Python(3). + + ---------- Footnotes ---------- + + (1) +https://developer.fedoraproject.org/tech/languages/python/python-installation.html + + (2) https://labs.fedoraproject.org/en/python-classroom/ + + (3) https://fedoralovespython.org + + +File: pythonpackagingguide.info, Node: CentOS/RHEL, Next: openSUSE, Prev: Fedora, Up: Installing pip/setuptools/wheel with Linux Package Managers + +3.3.2 CentOS/RHEL +----------------- + +CentOS and RHEL don’t offer *note pip: 2b. or *note wheel: 2e. in their +core repositories, although *note setuptools: 2d. is installed by +default. + +To install pip and wheel for the system Python, there are two options: + + 1. Enable the EPEL repository(1) using these instructions(2). On EPEL + 7, you can install pip and wheel like so: + + sudo dnf install python3-pip python3-wheel + + Since EPEL only offers extra, non-conflicting packages, EPEL does + not offer setuptools, since it’s in the core repository. + + 2. Enable the PyPA Copr Repo(3) using these instructions(4) (5). You + can install pip and wheel like so: + + sudo dnf install python3-pip python3-wheel + + To additionally upgrade setuptools, run: + + sudo dnf upgrade python3-setuptools + +To install pip, wheel, and setuptools, in a parallel, non-system +environment (using yum) then there are two options: + + 1. Use the “Software Collections” feature to enable a parallel + collection that includes pip, setuptools, and wheel. + + * For Redhat, see here: + ‘https://developers.redhat.com/products/softwarecollections/overview’ + + * For CentOS, see here: + ‘https://www.softwarecollections.org/en/’ + + Be aware that collections may not contain the most recent versions. + + 2. Enable the IUS repository(6) and install one of the + parallel-installable(7) Pythons, along with pip, setuptools, and + wheel, which are kept fairly up to date. + + For example, for Python 3.4 on CentOS7/RHEL7: + + sudo yum install python34u python34u-wheel + + ---------- Footnotes ---------- + + (1) https://fedoraproject.org/wiki/EPEL + + (2) +https://docs.fedoraproject.org/en-US/epel/#how_can_i_use_these_extra_packages + + (3) https://copr.fedorainfracloud.org/coprs/pypa/pypa/ + + (4) +https://fedoraproject.org/wiki/Infrastructure/Fedorahosted-retirement + + (5) (1) Currently, there is no “copr” yum plugin available for +CentOS/RHEL, so the only option is to manually place the repo files as +described. + + (6) https://ius.io/setup + + (7) https://ius.io/usage#parallel-installable-packages + + +File: pythonpackagingguide.info, Node: openSUSE, Next: Debian/Ubuntu, Prev: CentOS/RHEL, Up: Installing pip/setuptools/wheel with Linux Package Managers + +3.3.3 openSUSE +-------------- + + sudo zypper install python3-pip python3-setuptools python3-wheel + + +File: pythonpackagingguide.info, Node: Debian/Ubuntu, Next: Arch Linux, Prev: openSUSE, Up: Installing pip/setuptools/wheel with Linux Package Managers + +3.3.4 Debian/Ubuntu +------------------- + +Firstly, update and refresh repository lists by running this command: + + sudo apt update + sudo apt install python3-venv python3-pip + + Warning: Recent Debian/Ubuntu versions have modified pip to use the + "User Scheme"(1) by default, which is a significant behavior change + that can be surprising to some users. + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/stable/user_guide/#user-installs + + +File: pythonpackagingguide.info, Node: Arch Linux, Prev: Debian/Ubuntu, Up: Installing pip/setuptools/wheel with Linux Package Managers + +3.3.5 Arch Linux +---------------- + + sudo pacman -S python-pip + +__________________________________________________________________ + + +File: pythonpackagingguide.info, Node: Installing scientific packages, Next: Multi-version installs, Prev: Installing pip/setuptools/wheel with Linux Package Managers, Up: Guides + +3.4 Installing scientific packages +================================== + +Scientific software tends to have more complex dependencies than most, +and it will often have multiple build options to take advantage of +different kinds of hardware, or to interoperate with different pieces of +external software. + +In particular, NumPy(1), which provides the basis for most of the +software in the scientific Python stack(2) can be configured to +interoperate with different FORTRAN libraries, and can take advantage of +different levels of vectorised instructions available in modern CPUs. + +Starting with version 1.10.4 of NumPy and version 1.0.0 of SciPy, +pre-built 32-bit and 64-bit binaries in the ‘wheel’ format are available +for all major operating systems (Windows, macOS, and Linux) on PyPI. +Note, however, that on Windows, NumPy binaries are linked against the +ATLAS(3) BLAS/LAPACK library, restricted to SSE2 instructions, so they +may not provide optimal linear algebra performance. + +There are a number of alternative options for obtaining scientific +Python libraries (or any other Python libraries that require a +compilation environment to install from source and don’t provide +pre-built wheel files on PyPI). + +* Menu: + +* Building from source:: +* Linux distribution packages:: +* Windows installers:: +* macOS installers and package managers:: +* SciPy distributions:: +* Spack:: +* The conda cross-platform package manager:: + + ---------- Footnotes ---------- + + (1) https://numpy.org/ + + (2) https://scientific-python.org + + (3) http://www.netlib.org/atlas/ + + +File: pythonpackagingguide.info, Node: Building from source, Next: Linux distribution packages, Up: Installing scientific packages + +3.4.1 Building from source +-------------------------- + +The same complexity which makes it difficult to distribute NumPy (and +many of the projects that depend on it) as wheel files also make them +difficult to build from source yourself. However, for intrepid folks +that are willing to spend the time wrangling compilers and linkers for +both C and FORTRAN, building from source is always an option. + + +File: pythonpackagingguide.info, Node: Linux distribution packages, Next: Windows installers, Prev: Building from source, Up: Installing scientific packages + +3.4.2 Linux distribution packages +--------------------------------- + +For Linux users, the system package manager will often have pre-compiled +versions of various pieces of scientific software, including NumPy and +other parts of the scientific Python stack. + +If using versions which may be several months old is acceptable, then +this is likely to be a good option (just make sure to allow access to +distributions installed into the system Python when using virtual +environments). + + +File: pythonpackagingguide.info, Node: Windows installers, Next: macOS installers and package managers, Prev: Linux distribution packages, Up: Installing scientific packages + +3.4.3 Windows installers +------------------------ + +Many Python projects that don’t (or can’t) currently publish wheel files +at least publish Windows installers, either on PyPI or on their project +download page. Using these installers allows users to avoid the need to +set up a suitable environment to build extensions locally. + +The extensions provided in these installers are typically compatible +with the CPython Windows installers published on python.org. + +For projects which don’t provide their own Windows installers (and even +some which do), Christoph Gohlke at the University of California +provides a collection of Windows installers(1). Many Python users on +Windows have reported a positive experience with these prebuilt +versions. + +As with Linux system packages, the Windows installers will only install +into a system Python installation - they do not support installation in +virtual environments. Allowing access to distributions installed into +the system Python when using virtual environments is a common approach +to working around this limitation. + +The *note Wheel: d. project also provides a ‘wheel convert’ subcommand +that can convert a Windows ‘bdist_wininst’ installer to a wheel. + + ---------- Footnotes ---------- + + (1) https://www.lfd.uci.edu/~gohlke/pythonlibs/ + + +File: pythonpackagingguide.info, Node: macOS installers and package managers, Next: SciPy distributions, Prev: Windows installers, Up: Installing scientific packages + +3.4.4 macOS installers and package managers +------------------------------------------- + +Similar to the situation on Windows, many projects (including NumPy) +publish macOS installers that are compatible with the macOS CPython +binaries published on python.org. + +macOS users also have access to Linux distribution style package +managers such as ‘Homebrew’. The SciPy site has more details on using +Homebrew to install SciPy on macOS(1). + + ---------- Footnotes ---------- + + (1) https://scipy.org/install/#mac + + +File: pythonpackagingguide.info, Node: SciPy distributions, Next: Spack, Prev: macOS installers and package managers, Up: Installing scientific packages + +3.4.5 SciPy distributions +------------------------- + +The SciPy site lists several distributions(1) that provide the full +SciPy stack to end users in an easy to use and update format. + +Some of these distributions may not be compatible with the standard +‘pip’ and ‘virtualenv’ based toolchain. + + ---------- Footnotes ---------- + + (1) https://scipy.org/install/#distributions + + +File: pythonpackagingguide.info, Node: Spack, Next: The conda cross-platform package manager, Prev: SciPy distributions, Up: Installing scientific packages + +3.4.6 Spack +----------- + +Spack(1) is a flexible package manager designed to support multiple +versions, configurations, platforms, and compilers. It was built to +support the needs of large supercomputing centers and scientific +application teams, who must often build software many different ways. +Spack is not limited to Python; it can install packages for ‘C’, ‘C++’, +‘Fortran’, ‘R’, and other languages. It is non-destructive; installing +a new version of one package does not break existing installations, so +many configurations can coexist on the same system. + +Spack offers a simple but powerful syntax that allows users to specify +versions and configuration options concisely. Package files are written +in pure Python, and they are templated so that it is easy to swap +compilers, dependency implementations (like MPI), versions, and build +options with a single package file. Spack also generates `module' files +so that packages can be loaded and unloaded from the user’s environment. + + ---------- Footnotes ---------- + + (1) https://github.com/spack/spack + + +File: pythonpackagingguide.info, Node: The conda cross-platform package manager, Prev: Spack, Up: Installing scientific packages + +3.4.7 The conda cross-platform package manager +---------------------------------------------- + +Anaconda(1) is a Python distribution published by Anaconda, Inc. It is +a stable collection of Open Source packages for big data and scientific +use. As of the 5.0 release of Anaconda, about 200 packages are +installed by default, and a total of 400-500 can be installed and +updated from the Anaconda repository. + +‘conda’ is an open source (BSD licensed) package management system and +environment management system included in Anaconda that allows users to +install multiple versions of binary software packages and their +dependencies, and easily switch between them. It is a cross-platform +tool working on Windows, macOS, and Linux. Conda can be used to package +up and distribute all kinds of packages, it is not limited to just +Python packages. It has full support for native virtual environments. +Conda makes environments first-class citizens, making it easy to create +independent environments even for C libraries. It is written in Python, +but is Python-agnostic. Conda manages Python itself as a package, so +that ‘conda update python’ is possible, in contrast to pip, which only +manages Python packages. Conda is available in Anaconda and Miniconda +(an easy-to-install download with just Python and conda). + + ---------- Footnotes ---------- + + (1) https://www.anaconda.com/products/individual/ + + +File: pythonpackagingguide.info, Node: Multi-version installs, Next: Package index mirrors and caches, Prev: Installing scientific packages, Up: Guides + +3.5 Multi-version installs +========================== + +easy_install allows simultaneous installation of different versions of +the same project into a single environment shared by multiple programs +which must ‘require’ the appropriate version of the project at run time +(using ‘pkg_resources’). + +For many use cases, virtual environments address this need without the +complication of the ‘require’ directive. However, the advantage of +parallel installations within the same environment is that it works for +an environment shared by multiple applications, such as the system +Python in a Linux distribution. + +The major limitation of ‘pkg_resources’ based parallel installation is +that as soon as you import ‘pkg_resources’ it locks in the `default' +version of everything which is already available on sys.path. This can +cause problems, since ‘setuptools’ created command line scripts use +‘pkg_resources’ to find the entry point to execute. This means that, +for example, you can’t use ‘require’ tests invoked through ‘nose’ or a +WSGI application invoked through ‘gunicorn’ if your application needs a +non-default version of anything that is available on the standard +‘sys.path’ - the script wrapper for the main application will lock in +the version that is available by default, so the subsequent ‘require’ +call in your own code fails with a spurious version conflict. + +This can be worked around by setting all dependencies in +‘__main__.__requires__’ before importing ‘pkg_resources’ for the first +time, but that approach does mean that standard command line invocations +of the affected tools can’t be used - it’s necessary to write a custom +wrapper script or use ‘python -c ''’ to invoke the +application’s main entry point directly. + +Refer to the pkg_resources documentation(1) for more details. + + ---------- Footnotes ---------- + + (1) +https://setuptools.readthedocs.io/en/latest/pkg_resources.html#workingset-objects + + +File: pythonpackagingguide.info, Node: Package index mirrors and caches, Next: Hosting your own simple repository, Prev: Multi-version installs, Up: Guides + +3.6 Package index mirrors and caches +==================================== + + +Page Status: Incomplete + + +Last Reviewed: 2014-12-24 + +Mirroring or caching of PyPI can be used to speed up local package +installation, allow offline work, handle corporate firewalls or just +plain Internet flakiness. + +Three options are available in this area: + + 1. pip provides local caching options, + + 2. devpi provides higher-level caching option, potentially shared + amongst many users or machines, and + + 3. bandersnatch provides a local complete mirror of all PyPI *note + packages: b. + +* Menu: + +* Caching with pip:: +* Caching with devpi:: +* Complete mirror with bandersnatch:: + + +File: pythonpackagingguide.info, Node: Caching with pip, Next: Caching with devpi, Up: Package index mirrors and caches + +3.6.1 Caching with pip +---------------------- + +pip provides a number of facilities for speeding up installation by +using local cached copies of *note packages: b.: + + 1. Fast & local installs(1) by downloading all the requirements for a + project and then pointing pip at those downloaded files instead of + going to PyPI. + + 2. A variation on the above which pre-builds the installation files + for the requirements using python -m pip wheel(2): + + python -m pip wheel --wheel-dir=/tmp/wheelhouse SomeProject + python -m pip install --no-index --find-links=/tmp/wheelhouse SomeProject + + ---------- Footnotes ---------- + + (1) +https://pip.pypa.io/en/latest/user_guide/#installing-from-local-packages + + (2) https://pip.pypa.io/en/latest/cli/pip_wheel/#pip-wheel + + +File: pythonpackagingguide.info, Node: Caching with devpi, Next: Complete mirror with bandersnatch, Prev: Caching with pip, Up: Package index mirrors and caches + +3.6.2 Caching with devpi +------------------------ + +devpi is a caching proxy server which you run on your laptop, or some +other machine you know will always be available to you. See the devpi +documentation for getting started(1). + + ---------- Footnotes ---------- + + (1) +https://devpi.net/docs/devpi/devpi/latest/+d/quickstart-pypimirror.html + + +File: pythonpackagingguide.info, Node: Complete mirror with bandersnatch, Prev: Caching with devpi, Up: Package index mirrors and caches + +3.6.3 Complete mirror with bandersnatch +--------------------------------------- + +bandersnatch will set up a complete local mirror of all PyPI *note +packages: b. (externally-hosted packages are not mirrored). See the +bandersnatch documentation for getting that going(1). + +A benefit of devpi is that it will create a mirror which includes *note +packages: b. that are external to PyPI, unlike bandersnatch which will +only cache *note packages: b. hosted on PyPI. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/bandersnatch/ + + +File: pythonpackagingguide.info, Node: Hosting your own simple repository, Next: Packaging and distributing projects, Prev: Package index mirrors and caches, Up: Guides + +3.7 Hosting your own simple repository +====================================== + +If you wish to host your own simple repository (1), you can either use a +software package like devpi(2) or you can use simply create the proper +directory structure and use any web server that can serve static files +and generate an autoindex. + +In either case, since you’ll be hosting a repository that is likely not +in your user’s default repositories, you should instruct them in your +project’s description to configure their installer appropriately. For +example with pip: (Unix/macOS) + python3 -m pip install --extra-index-url https://python.example.com/ foobar +(Windows) + py -m pip install --extra-index-url https://python.example.com/ foobar + +In addition, it is `highly' recommended that you serve your repository +with valid HTTPS. At this time, the security of your user’s +installations depends on all repositories using a valid HTTPS setup. + +* Menu: + +* “Manual” repository:: + + ---------- Footnotes ---------- + + (1) (1) For complete documentation of the simple repository protocol, +see PEP 503 (https://www.python.org/dev/peps/pep-0503). + + (2) https://devpi.net/docs/devpi/devpi/latest/+doc/index.html + + +File: pythonpackagingguide.info, Node: “Manual” repository, Up: Hosting your own simple repository + +3.7.1 “Manual” repository +------------------------- + +The directory layout is fairly simple, within a root directory you need +to create a directory for each project. This directory should be the +normalized name (as defined by PEP 503(1)) of the project. Within each +of these directories simply place each of the downloadable files. If +you have the projects “Foo” (with the versions 1.0 and 2.0) and “bar” +(with the version 0.1) You should end up with a structure that looks +like: + + . + ├── bar + │   └── bar-0.1.tar.gz + └── foo + ├── Foo-1.0.tar.gz + └── Foo-2.0.tar.gz + +Once you have this layout, simply configure your webserver to serve the +root directory with autoindex enabled. For an example using the built +in Web server in Twisted(2), you would simply run ‘twistd -n web --path +.’ and then instruct users to add the URL to their installer’s +configuration. + +__________________________________________________________________ + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0503 + + (2) https://twistedmatrix.com/ + + +File: pythonpackagingguide.info, Node: Packaging and distributing projects, Next: Including files in source distributions with MANIFEST in, Prev: Hosting your own simple repository, Up: Guides + +3.8 Packaging and distributing projects +======================================= + +This section covers some additional details on configuring, packaging +and distributing Python projects with ‘setuptools’ that aren’t covered +by the introductory tutorial in *note Packaging Python Projects: e. It +still assumes that you are already familiar with the contents of the +*note Installing Packages: 23. page. + +The section does `not' aim to cover best practices for Python project +development as a whole. For example, it does not provide guidance or +tool recommendations for version control, documentation, or testing. + +For more reference material, see Building and Distributing Packages(1) +in the *note setuptools: 2d. docs, but note that some advisory content +there may be outdated. In the event of conflicts, prefer the advice in +the Python Packaging User Guide. + +* Menu: + +* Requirements for packaging and distributing:: +* Configuring your project:: +* Working in “development mode”:: +* Packaging your project:: +* Uploading your Project to PyPI:: + + ---------- Footnotes ---------- + + (1) https://setuptools.pypa.io/en/latest/userguide/index.html + + +File: pythonpackagingguide.info, Node: Requirements for packaging and distributing, Next: Configuring your project, Up: Packaging and distributing projects + +3.8.1 Requirements for packaging and distributing +------------------------------------------------- + + 1. First, make sure you have already fulfilled the *note requirements + for installing packages: 26. + + 2. Install “twine” (1): (Unix/macOS) + python3 -m pip install twine + (Windows) + py -m pip install twine + + You’ll need this to upload your project *note distributions: b. to + *note PyPI: 39. (see *note below: b6.). + + ---------- Footnotes ---------- + + (1) (1) Depending on your platform, this may require root or +Administrator access. *note pip: 2b. is currently considering changing +this by making user installs the default behavior +(https://github.com/pypa/pip/issues/1668). + + +File: pythonpackagingguide.info, Node: Configuring your project, Next: Working in “development mode”, Prev: Requirements for packaging and distributing, Up: Packaging and distributing projects + +3.8.2 Configuring your project +------------------------------ + +* Menu: + +* Initial files:: +* setup() args: setup args. +* Choosing a versioning scheme:: + + +File: pythonpackagingguide.info, Node: Initial files, Next: setup args, Up: Configuring your project + +3.8.2.1 Initial files +..................... + +* Menu: + +* setup.py: setup py. +* setup.cfg: setup cfg. +* README.rst / README.md: README rst / README md. +* MANIFEST.in: MANIFEST in. +* LICENSE.txt: LICENSE txt. +* :: + + +File: pythonpackagingguide.info, Node: setup py, Next: setup cfg, Up: Initial files + +3.8.2.2 setup.py +................ + +The most important file is ‘setup.py’ which exists at the root of your +project directory. For an example, see the setup.py(1) in the PyPA +sample project(2). + +‘setup.py’ serves two primary functions: + + 1. It’s the file where various aspects of your project are configured. + The primary feature of ‘setup.py’ is that it contains a global + ‘setup()’ function. The keyword arguments to this function are how + specific details of your project are defined. The most relevant + arguments are explained in *note the section below: ba. + + 2. It’s the command line interface for running various commands that + relate to packaging tasks. To get a listing of available commands, + run ‘python setup.py --help-commands’. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/sampleproject/blob/main/setup.py + + (2) https://github.com/pypa/sampleproject + + +File: pythonpackagingguide.info, Node: setup cfg, Next: README rst / README md, Prev: setup py, Up: Initial files + +3.8.2.3 setup.cfg +................. + +‘setup.cfg’ is an ini file that contains option defaults for ‘setup.py’ +commands. For an example, see the setup.cfg(1) in the PyPA sample +project(2). + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/sampleproject/blob/main/setup.cfg + + (2) https://github.com/pypa/sampleproject + + +File: pythonpackagingguide.info, Node: README rst / README md, Next: MANIFEST in, Prev: setup cfg, Up: Initial files + +3.8.2.4 README.rst / README.md +.............................. + +All projects should contain a readme file that covers the goal of the +project. The most common format is reStructuredText(1) with an “rst” +extension, although this is not a requirement; multiple variants of +Markdown(2) are supported as well (look at ‘setup()’’s *note +long_description_content_type: bd. argument). + +For an example, see README.md(3) from the PyPA sample project(4). + + Note: Projects using *note setuptools: 2d. 0.6.27+ have standard + readme files (‘README.rst’, ‘README.txt’, or ‘README’) included in + source distributions by default. The built-in *note distutils: be. + library adopts this behavior beginning in Python 3.7. + Additionally, *note setuptools: 2d. 36.4.0+ will include a + ‘README.md’ if found. If you are using setuptools, you don’t need + to list your readme file in ‘MANIFEST.in’. Otherwise, include it + to be explicit. + + ---------- Footnotes ---------- + + (1) https://docutils.sourceforge.io/rst.html + + (2) https://daringfireball.net/projects/markdown/ + + (3) https://github.com/pypa/sampleproject/blob/main/README.md + + (4) https://github.com/pypa/sampleproject + + +File: pythonpackagingguide.info, Node: MANIFEST in, Next: LICENSE txt, Prev: README rst / README md, Up: Initial files + +3.8.2.5 MANIFEST.in +................... + +A ‘MANIFEST.in’ is needed when you need to package additional files that +are not automatically included in a source distribution. For details on +writing a ‘MANIFEST.in’ file, including a list of what’s included by +default, see “*note Including files in source distributions with +MANIFEST.in: 67.”. + +However, you may not have to use a ‘MANIFEST.in’. For an example, the +PyPA sample project(1) has removed its manifest file, since all the +necessary files have been included by *note setuptools: 2d. 43.0.0 and +newer. + + Note: ‘MANIFEST.in’ does not affect binary distributions such as + wheels. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/sampleproject + + +File: pythonpackagingguide.info, Node: LICENSE txt, Next: , Prev: MANIFEST in, Up: Initial files + +3.8.2.6 LICENSE.txt +................... + +Every package should include a license file detailing the terms of +distribution. In many jurisdictions, packages without an explicit +license can not be legally used or distributed by anyone other than the +copyright holder. If you’re unsure which license to choose, you can use +resources such as GitHub’s Choose a License(1) or consult a lawyer. + +For an example, see the LICENSE.txt(2) from the PyPA sample project(3). + + ---------- Footnotes ---------- + + (1) https://choosealicense.com/ + + (2) https://github.com/pypa/sampleproject/blob/main/LICENSE.txt + + (3) https://github.com/pypa/sampleproject + + +File: pythonpackagingguide.info, Node: , Prev: LICENSE txt, Up: Initial files + +3.8.2.7 +...................... + +Although it’s not required, the most common practice is to include your +Python modules and packages under a single top-level package that has +the same *note name: c2. as your project, or something very close. + +For an example, see the sample(1) package that’s included in the PyPA +sample project(2). + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/sampleproject/tree/main/src/sample + + (2) https://github.com/pypa/sampleproject + + +File: pythonpackagingguide.info, Node: setup args, Next: Choosing a versioning scheme, Prev: Initial files, Up: Configuring your project + +3.8.2.8 setup() args +.................... + +As mentioned above, the primary feature of ‘setup.py’ is that it +contains a global ‘setup()’ function. The keyword arguments to this +function are how specific details of your project are defined. + +The most relevant arguments are explained below. Most of the snippets +given are taken from the setup.py(1) contained in the PyPA sample +project(2). + +* Menu: + +* name:: +* version:: +* description:: +* url:: +* author:: +* license:: +* classifiers:: +* keywords:: +* project_urls:: +* packages:: +* py_modules:: +* install_requires:: +* python_requires:: +* package_data:: +* data_files:: +* scripts:: +* entry_points:: + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/sampleproject/blob/main/setup.py + + (2) https://github.com/pypa/sampleproject + + +File: pythonpackagingguide.info, Node: name, Next: version, Up: setup args + +3.8.2.9 ‘name’ +.............. + + name='sample', + +This is the name of your project, determining how your project is listed +on *note PyPI: 39. Per PEP 508(1), valid project names must: + + - Consist only of ASCII letters, digits, underscores (‘_’), hyphens + (‘-’), and/or periods (‘.’), and + + - Start & end with an ASCII letter or digit. + +Comparison of project names is case insensitive and treats +arbitrarily-long runs of underscores, hyphens, and/or periods as equal. +For example, if you register a project named ‘cool-stuff’, users will be +able to download it or declare a dependency on it using any of the +following spellings: + + Cool-Stuff + cool.stuff + COOL_STUFF + CoOl__-.-__sTuFF + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0508 + + +File: pythonpackagingguide.info, Node: version, Next: description, Prev: name, Up: setup args + +3.8.2.10 ‘version’ +.................. + + version='1.2.0', + +This is the current version of your project, allowing your users to +determine whether or not they have the latest version, and to indicate +which specific versions they’ve tested their own software against. + +Versions are displayed on *note PyPI: 39. for each release if you +publish your project. + +See *note Choosing a versioning scheme: c6. for more information on ways +to use versions to convey compatibility information to your users. + +If the project code itself needs run-time access to the version, the +simplest way is to keep the version in both ‘setup.py’ and your code. +If you’d rather not duplicate the value, there are a few ways to manage +this. See the “*note Single-sourcing the package version: c7.” Advanced +Topics section. + + +File: pythonpackagingguide.info, Node: description, Next: url, Prev: version, Up: setup args + +3.8.2.11 ‘description’ +...................... + + description='A sample Python project', + long_description=long_description, + long_description_content_type='text/x-rst', + +Give a short and long description for your project. + +These values will be displayed on *note PyPI: 39. if you publish your +project. On ‘pypi.org’, the user interface displays ‘description’ in +the grey banner and ‘long_description’ in the section named “Project +Description”. + +‘description’ is also displayed in lists of projects. For example, it’s +visible in the search results pages such as +‘https://pypi.org/search/?q=jupyter’, the front-page lists of trending +projects and new releases, and the list of projects you maintain within +your account profile (such as ‘https://pypi.org/user/jaraco/’). + +A content type(1) can be specified with the +‘long_description_content_type’ argument, which can be one of +‘text/plain’, ‘text/x-rst’, or ‘text/markdown’, corresponding to no +formatting, reStructuredText (reST)(2), and the Github-flavored Markdown +dialect of Markdown(3) respectively. + + ---------- Footnotes ---------- + + (1) +https://packaging.python.org/specifications/core-metadata/#description-content-type-optional + + (2) +https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#reference-names + + (3) https://daringfireball.net/projects/markdown/ + + +File: pythonpackagingguide.info, Node: url, Next: author, Prev: description, Up: setup args + +3.8.2.12 ‘url’ +.............. + + url='https://github.com/pypa/sampleproject', + +Give a homepage URL for your project. + + +File: pythonpackagingguide.info, Node: author, Next: license, Prev: url, Up: setup args + +3.8.2.13 ‘author’ +................. + + author='A. Random Developer', + author_email='author@example.com', + +Provide details about the author. + + +File: pythonpackagingguide.info, Node: license, Next: classifiers, Prev: author, Up: setup args + +3.8.2.14 ‘license’ +.................. + + license='MIT', + +The ‘license’ argument doesn’t have to indicate the license under which +your package is being released, although you may optionally do so if you +want. If you’re using a standard, well-known license, then your main +indication can and should be via the ‘classifiers’ argument. +Classifiers exist for all major open-source licenses. + +The ‘license’ argument is more typically used to indicate differences +from well-known licenses, or to include your own, unique license. As a +general rule, it’s a good idea to use a standard, well-known license, +both to avoid confusion and because some organizations avoid software +whose license is unapproved. + + +File: pythonpackagingguide.info, Node: classifiers, Next: keywords, Prev: license, Up: setup args + +3.8.2.15 ‘classifiers’ +...................... + + classifiers=[ + # How mature is this project? Common values are + # 3 - Alpha + # 4 - Beta + # 5 - Production/Stable + 'Development Status :: 3 - Alpha', + + # Indicate who your project is intended for + 'Intended Audience :: Developers', + 'Topic :: Software Development :: Build Tools', + + # Pick your license as you wish (should match "license" above) + 'License :: OSI Approved :: MIT License', + + # Specify the Python versions you support here. In particular, ensure + # that you indicate whether you support Python 2, Python 3 or both. + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + ], + +Provide a list of classifiers that categorize your project. For a full +listing, see ‘https://pypi.org/classifiers/’. + +Although the list of classifiers is often used to declare what Python +versions a project supports, this information is only used for searching +& browsing projects on PyPI, not for installing projects. To actually +restrict what Python versions a project can be installed on, use the +*note python_requires: cd. argument. + +To prevent a package from being uploaded to PyPI, use the special +‘'Private :: Do Not Upload'’ classifier. PyPI will always reject +packages with classifiers beginning with ‘"Private ::'’. + + +File: pythonpackagingguide.info, Node: keywords, Next: project_urls, Prev: classifiers, Up: setup args + +3.8.2.16 ‘keywords’ +................... + + keywords='sample setuptools development', + +List keywords that describe your project. + + +File: pythonpackagingguide.info, Node: project_urls, Next: packages, Prev: keywords, Up: setup args + +3.8.2.17 ‘project_urls’ +....................... + + project_urls={ + 'Documentation': 'https://packaging.python.org/tutorials/distributing-packages/', + 'Funding': 'https://donate.pypi.org', + 'Say Thanks!': 'http://saythanks.io/to/example', + 'Source': 'https://github.com/pypa/sampleproject/', + 'Tracker': 'https://github.com/pypa/sampleproject/issues', + }, + +List additional relevant URLs about your project. This is the place to +link to bug trackers, source repositories, or where to support package +development. The string of the key is the exact text that will be +displayed on PyPI. + + +File: pythonpackagingguide.info, Node: packages, Next: py_modules, Prev: project_urls, Up: setup args + +3.8.2.18 ‘packages’ +................... + + packages=find_packages(include=['sample', 'sample.*']), + +Set ‘packages’ to a list of all *note packages: a. in your project, +including their subpackages, sub-subpackages, etc. Although the +packages can be listed manually, ‘setuptools.find_packages()’ finds them +automatically. Use the ‘include’ keyword argument to find only the +given packages. Use the ‘exclude’ keyword argument to omit packages +that are not intended to be released and installed. + + +File: pythonpackagingguide.info, Node: py_modules, Next: install_requires, Prev: packages, Up: setup args + +3.8.2.19 ‘py_modules’ +..................... + + py_modules=["six"], + +If your project contains any single-file Python modules that aren’t part +of a package, set ‘py_modules’ to a list of the names of the modules +(minus the ‘.py’ extension) in order to make *note setuptools: 2d. aware +of them. + + +File: pythonpackagingguide.info, Node: install_requires, Next: python_requires, Prev: py_modules, Up: setup args + +3.8.2.20 ‘install_requires’ +........................... + + install_requires=['peppercorn'], + +“install_requires” should be used to specify what dependencies a project +minimally needs to run. When the project is installed by *note pip: 2b, +this is the specification that is used to install its dependencies. + +For more on using “install_requires” see *note install_requires vs +requirements files: d3. + + +File: pythonpackagingguide.info, Node: python_requires, Next: package_data, Prev: install_requires, Up: setup args + +3.8.2.21 ‘python_requires’ +.......................... + +If your project only runs on certain Python versions, setting the +‘python_requires’ argument to the appropriate PEP 440(1) version +specifier string will prevent *note pip: 2b. from installing the project +on other Python versions. For example, if your package is for Python 3+ +only, write: + + python_requires='>=3', + +If your package is for Python 2.6, 2.7, and all versions of Python 3 +starting with 3.3, write: + + python_requires='>=2.6, !=3.0.*, !=3.1.*, !=3.2.*', + +And so on. + + Note: Support for this feature is relatively recent. Your + project’s source distributions and wheels (see *note Packaging your + project: d5.) must be built using at least version 24.2.0 of *note + setuptools: 2d. in order for the ‘python_requires’ argument to be + recognized and the appropriate metadata generated. + + In addition, only versions 9.0.0 and higher of *note pip: 2b. + recognize the ‘python_requires’ metadata. Users with earlier + versions of pip will be able to download & install projects on any + Python version regardless of the projects’ ‘python_requires’ + values. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0440 + + +File: pythonpackagingguide.info, Node: package_data, Next: data_files, Prev: python_requires, Up: setup args + +3.8.2.22 ‘package_data’ +....................... + + package_data={ + 'sample': ['package_data.dat'], + }, + +Often, additional files need to be installed into a *note package: a. +These files are often data that’s closely related to the package’s +implementation, or text files containing documentation that might be of +interest to programmers using the package. These files are called +“package data”. + +The value must be a mapping from package name to a list of relative path +names that should be copied into the package. The paths are interpreted +as relative to the directory containing the package. + +For more information, see Including Data Files(1) from the setuptools +docs(2). + + ---------- Footnotes ---------- + + (1) https://setuptools.pypa.io/en/latest/userguide/datafiles.html + + (2) https://setuptools.pypa.io/en/latest/index.html + + +File: pythonpackagingguide.info, Node: data_files, Next: scripts, Prev: package_data, Up: setup args + +3.8.2.23 ‘data_files’ +..................... + + data_files=[('my_data', ['data/data_file'])], + +Although configuring *note package_data: d7. is sufficient for most +needs, in some cases you may need to place data files `outside' of your +*note packages: a. The ‘data_files’ directive allows you to do that. +It is mostly useful if you need to install files which are used by other +programs, which may be unaware of Python packages. + +Each ‘(directory, files)’ pair in the sequence specifies the +installation directory and the files to install there. The ‘directory’ +must be a relative path (although this may change in the future, see +wheel Issue #92(1)), and it is interpreted relative to the installation +prefix (Python’s ‘sys.prefix’ for a default installation; +‘site.USER_BASE’ for a user installation). Each file name in ‘files’ is +interpreted relative to the ‘setup.py’ script at the top of the project +source distribution. + +For more information see the distutils section on Installing Additional +Files(2). + + Note: When installing packages as egg, ‘data_files’ is not + supported. So, if your project uses *note setuptools: 2d, you must + use ‘pip’ to install it. Alternatively, if you must use ‘python + setup.py’, then you need to pass the ‘--old-and-unmanageable’ + option. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/wheel/issues/92 + + (2) +https://docs.python.org/3/distutils/setupscript.html#distutils-additional-files + + +File: pythonpackagingguide.info, Node: scripts, Next: entry_points, Prev: data_files, Up: setup args + +3.8.2.24 ‘scripts’ +.................. + +Although ‘setup()’ supports a scripts(1) keyword for pointing to +pre-made scripts to install, the recommended approach to achieve +cross-platform compatibility is to use *note console_scripts: db. entry +points (see below). + + ---------- Footnotes ---------- + + (1) +https://docs.python.org/3/distutils/setupscript.html#distutils-installing-scripts + + +File: pythonpackagingguide.info, Node: entry_points, Prev: scripts, Up: setup args + +3.8.2.25 ‘entry_points’ +....................... + + entry_points={ + ... + }, + +Use this keyword to specify any plugins that your project provides for +any named entry points that may be defined by your project or others +that you depend on. + +For more information, see the section on Advertising Behavior(1) from +the *note setuptools: 2d. docs. + +The most commonly used entry point is “console_scripts” (see below). + +* Menu: + +* console_scripts:: + + ---------- Footnotes ---------- + + (1) +https://setuptools.pypa.io/en/latest/userguide/entry_point.html#dynamic-discovery-of-services-and-plugins + + +File: pythonpackagingguide.info, Node: console_scripts, Up: entry_points + +3.8.2.26 ‘console_scripts’ +.......................... + + entry_points={ + 'console_scripts': [ + 'sample=sample:main', + ], + }, + +Use ‘console_script’ entry points(1) to register your script interfaces. +You can then let the toolchain handle the work of turning these +interfaces into actual scripts (2). The scripts will be generated +during the install of your *note distribution: b. + +For more information, see Automatic Script Creation(3) from the +setuptools docs(4). + + ---------- Footnotes ---------- + + (1) +https://setuptools.pypa.io/en/latest/userguide/entry_point.html#dynamic-discovery-of-services-and-plugins + + (2) (2) Specifically, the “console_script” approach generates ‘.exe’ +files on Windows, which are necessary because the OS special-cases +‘.exe’ files. Script-execution features like ‘PATHEXT’ and the Python +Launcher for Windows (https://www.python.org/dev/peps/pep-0397) allow +scripts to be used in many cases, but not all. + + (3) +https://setuptools.readthedocs.io/en/latest/userguide/quickstart.html#entry-points-and-automatic-script-creation + + (4) https://setuptools.pypa.io/en/latest/index.html + + +File: pythonpackagingguide.info, Node: Choosing a versioning scheme, Prev: setup args, Up: Configuring your project + +3.8.2.27 Choosing a versioning scheme +..................................... + +* Menu: + +* Standards compliance for interoperability:: +* Scheme choices:: +* Pre-release versioning:: +* Local version identifiers:: + + +File: pythonpackagingguide.info, Node: Standards compliance for interoperability, Next: Scheme choices, Up: Choosing a versioning scheme + +3.8.2.28 Standards compliance for interoperability +.................................................. + +Different Python projects may use different versioning schemes based on +the needs of that particular project, but all of them are required to +comply with the flexible public version scheme(1) specified in PEP +440(2) in order to be supported in tools and libraries like ‘pip’ and +‘setuptools’. + +Here are some examples of compliant version numbers: + + 1.2.0.dev1 # Development release + 1.2.0a1 # Alpha Release + 1.2.0b1 # Beta Release + 1.2.0rc1 # Release Candidate + 1.2.0 # Final Release + 1.2.0.post1 # Post Release + 15.10 # Date based release + 23 # Serial release + +To further accommodate historical variations in approaches to version +numbering, PEP 440(3) also defines a comprehensive technique for version +normalisation(4) that maps variant spellings of different version +numbers to a standardised canonical form. + + ---------- Footnotes ---------- + + (1) +https://www.python.org/dev/peps/pep-0440#public-version-identifiers + + (2) https://www.python.org/dev/peps/pep-0440 + + (3) https://www.python.org/dev/peps/pep-0440 + + (4) https://www.python.org/dev/peps/pep-0440#normalization + + +File: pythonpackagingguide.info, Node: Scheme choices, Next: Pre-release versioning, Prev: Standards compliance for interoperability, Up: Choosing a versioning scheme + +3.8.2.29 Scheme choices +....................... + +* Menu: + +* Semantic versioning (preferred): Semantic versioning preferred. +* Date based versioning:: +* Serial versioning:: +* Hybrid schemes:: + + +File: pythonpackagingguide.info, Node: Semantic versioning preferred, Next: Date based versioning, Up: Scheme choices + +3.8.2.30 Semantic versioning (preferred) +........................................ + +For new projects, the recommended versioning scheme is based on Semantic +Versioning(1), but adopts a different approach to handling pre-releases +and build metadata. + +The essence of semantic versioning is a 3-part MAJOR.MINOR.MAINTENANCE +numbering scheme, where the project author increments: + + 1. MAJOR version when they make incompatible API changes, + + 2. MINOR version when they add functionality in a backwards-compatible + manner, and + + 3. MAINTENANCE version when they make backwards-compatible bug fixes. + +Adopting this approach as a project author allows users to make use of +“compatible release”(2) specifiers, where ‘name ~= X.Y’ requires at +least release X.Y, but also allows any later release with a matching +MAJOR version. + +Python projects adopting semantic versioning should abide by clauses 1-8 +of the Semantic Versioning 2.0.0 specification(3). + + ---------- Footnotes ---------- + + (1) https://semver.org/ + + (2) https://www.python.org/dev/peps/pep-0440#compatible-release + + (3) https://semver.org/ + + +File: pythonpackagingguide.info, Node: Date based versioning, Next: Serial versioning, Prev: Semantic versioning preferred, Up: Scheme choices + +3.8.2.31 Date based versioning +.............................. + +Semantic versioning is not a suitable choice for all projects, such as +those with a regular time based release cadence and a deprecation +process that provides warnings for a number of releases prior to removal +of a feature. + +A key advantage of date based versioning is that it is straightforward +to tell how old the base feature set of a particular release is given +just the version number. + +Version numbers for date based projects typically take the form of +YEAR.MONTH (for example, ‘12.04’, ‘15.10’). + + +File: pythonpackagingguide.info, Node: Serial versioning, Next: Hybrid schemes, Prev: Date based versioning, Up: Scheme choices + +3.8.2.32 Serial versioning +.......................... + +This is the simplest possible versioning scheme, and consists of a +single number which is incremented every release. + +While serial versioning is very easy to manage as a developer, it is the +hardest to track as an end user, as serial version numbers convey little +or no information regarding API backwards compatibility. + + +File: pythonpackagingguide.info, Node: Hybrid schemes, Prev: Serial versioning, Up: Scheme choices + +3.8.2.33 Hybrid schemes +....................... + +Combinations of the above schemes are possible. For example, a project +may combine date based versioning with serial versioning to create a +YEAR.SERIAL numbering scheme that readily conveys the approximate age of +a release, but doesn’t otherwise commit to a particular release cadence +within the year. + + +File: pythonpackagingguide.info, Node: Pre-release versioning, Next: Local version identifiers, Prev: Scheme choices, Up: Choosing a versioning scheme + +3.8.2.34 Pre-release versioning +............................... + +Regardless of the base versioning scheme, pre-releases for a given final +release may be published as: + + * zero or more dev releases (denoted with a “.devN” suffix) + + * zero or more alpha releases (denoted with a “.aN” suffix) + + * zero or more beta releases (denoted with a “.bN” suffix) + + * zero or more release candidates (denoted with a “.rcN” suffix) + +‘pip’ and other modern Python package installers ignore pre-releases by +default when deciding which versions of dependencies to install. + + +File: pythonpackagingguide.info, Node: Local version identifiers, Prev: Pre-release versioning, Up: Choosing a versioning scheme + +3.8.2.35 Local version identifiers +.................................. + +Public version identifiers are designed to support distribution via +*note PyPI: 39. Python’s software distribution tools also support the +notion of a local version identifier(1), which can be used to identify +local development builds not intended for publication, or modified +variants of a release maintained by a redistributor. + +A local version identifier takes the form ‘+’. For example: + + 1.2.0.dev1+hg.5.b11e5e6f0b0b # 5th VCS commit since 1.2.0.dev1 release + 1.2.1+fedora.4 # Package with downstream Fedora patches applied + + ---------- Footnotes ---------- + + (1) +https://www.python.org/dev/peps/pep-0440#local-version-identifiers + + +File: pythonpackagingguide.info, Node: Working in “development mode”, Next: Packaging your project, Prev: Configuring your project, Up: Packaging and distributing projects + +3.8.3 Working in “development mode” +----------------------------------- + +You can install a project in “editable” or “develop” mode while you’re +working on it. When installed as editable, a project can be edited +in-place without reinstallation: changes to Python source files in +projects installed as editable will be reflected the next time an +interpreter process is started. + +To install a Python package in “editable”/”development” mode Change +directory to the root of the project directory and run: + + python -m pip install -e . + +The pip command-line flag ‘-e’ is short for ‘--editable’, and ‘.’ refers +to the current working directory, so together, it means to install the +current directory (i.e. your project) in editable mode. This will also +install any dependencies declared with ‘install_requires’ and any +scripts declared with ‘console_scripts’. Dependencies will be installed +in the usual, non-editable mode. + +You may want to install some of your dependencies in editable mode as +well. For example, supposing your project requires “foo” and “bar”, but +you want “bar” installed from VCS in editable mode, then you could +construct a requirements file like so: + + -e . + -e git+https://somerepo/bar.git#egg=bar + +The first line says to install your project and any dependencies. The +second line overrides the “bar” dependency, such that it’s fulfilled +from VCS, not PyPI. + +If, however, you want “bar” installed from a local directory in editable +mode, the requirements file should look like this, with the local paths +at the top of the file: + + -e /path/to/project/bar + -e . + +Otherwise, the dependency will be fulfilled from PyPI, due to the +installation order of the requirements file. For more on requirements +files, see the Requirements File(1) section in the pip docs. For more +on VCS installs, see the VCS Support(2) section of the pip docs. + +Lastly, if you don’t want to install any dependencies at all, you can +run: + + python -m pip install -e . --no-deps + +For more information, see the Development Mode(3) section of the +setuptools docs(4). + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/user_guide/#requirements-files + + (2) https://pip.pypa.io/en/latest/cli/pip_install/#vcs-support + + (3) +https://setuptools.pypa.io/en/latest/userguide/development_mode.html + + (4) https://setuptools.pypa.io/en/latest/setuptools.html + + +File: pythonpackagingguide.info, Node: Packaging your project, Next: Uploading your Project to PyPI, Prev: Working in “development mode”, Up: Packaging and distributing projects + +3.8.4 Packaging your project +---------------------------- + +To have your project installable from a *note Package Index: e9. like +*note PyPI: 39, you’ll need to create a *note Distribution: b. (aka +“*note Package: b.”) for your project. + +Before you can build wheels and sdists for your project, you’ll need to +install the ‘build’ package: (Unix/macOS) + python3 -m pip install build +(Windows) + py -m pip install build + +* Menu: + +* Source distributions:: +* Wheels:: + + +File: pythonpackagingguide.info, Node: Source distributions, Next: Wheels, Up: Packaging your project + +3.8.4.1 Source distributions +............................ + +Minimally, you should create a *note Source Distribution: 3d.: +(Unix/macOS) + python3 -m build --sdist +(Windows) + py -m build --sdist + +A “source distribution” is unbuilt (i.e. it’s not a *note Built +Distribution: 68.), and requires a build step when installed by pip. +Even if the distribution is pure Python (i.e. contains no extensions), +it still involves a build step to build out the installation metadata +from ‘setup.py’ and/or ‘setup.cfg’. + + +File: pythonpackagingguide.info, Node: Wheels, Prev: Source distributions, Up: Packaging your project + +3.8.4.2 Wheels +.............. + +You should also create a wheel for your project. A wheel is a *note +built package: 68. that can be installed without needing to go through +the “build” process. Installing wheels is substantially faster for the +end user than installing from a source distribution. + +If your project is pure Python then you’ll be creating a *note “Pure +Python Wheel” (see section below): ec. + +If your project contains compiled extensions, then you’ll be creating +what’s called a *note *Platform Wheel* (see section below): ed. + + Note: If your project also supports Python 2 `and' contains no C + extensions, then you should create what’s called a `Universal + Wheel' by adding the following to your ‘setup.cfg’ file: + + [bdist_wheel] + universal=1 + + Only use this setting if your project does not have any C + extensions `and' supports Python 2 and 3. + +* Menu: + +* Pure Python Wheels:: +* Platform Wheels:: + + +File: pythonpackagingguide.info, Node: Pure Python Wheels, Next: Platform Wheels, Up: Wheels + +3.8.4.3 Pure Python Wheels +.......................... + +`Pure Python Wheels' contain no compiled extensions, and therefore only +require a single Python wheel. + +To build the wheel: (Unix/macOS) + python -m build --wheel +(Windows) + py -m build --wheel + +The ‘wheel’ package will detect that the code is pure Python, and build +a wheel that’s named such that it’s usable on any Python 3 installation. +For details on the naming of wheel files, see PEP 425(1). + +If you run ‘build’ without ‘--wheel’ or ‘--sdist’, it will build both +files for you; this is useful when you don’t need multiple wheels. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0425 + + +File: pythonpackagingguide.info, Node: Platform Wheels, Prev: Pure Python Wheels, Up: Wheels + +3.8.4.4 Platform Wheels +....................... + +`Platform Wheels' are wheels that are specific to a certain platform +like Linux, macOS, or Windows, usually due to containing compiled +extensions. + +To build the wheel: (Unix/macOS) + python3 -m build --wheel +(Windows) + py -m build --wheel + +The ‘wheel’ package will detect that the code is not pure Python, and +build a wheel that’s named such that it’s only usable on the platform +that it was built on. For details on the naming of wheel files, see PEP +425(1). + + Note: *note PyPI: 39. currently supports uploads of platform wheels + for Windows, macOS, and the multi-distro ‘manylinux*’ ABI. Details + of the latter are defined in PEP 513(2). + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0425 + + (2) https://www.python.org/dev/peps/pep-0513 + + +File: pythonpackagingguide.info, Node: Uploading your Project to PyPI, Prev: Packaging your project, Up: Packaging and distributing projects + +3.8.5 Uploading your Project to PyPI +------------------------------------ + +When you ran the command to create your distribution, a new directory +‘dist/’ was created under your project’s root directory. That’s where +you’ll find your distribution file(s) to upload. + + Note: These files are only created when you run the command to + create your distribution. This means that any time you change the + source of your project or the configuration in your ‘setup.py’ + file, you will need to rebuild these files again before you can + distribute the changes to PyPI. + + Note: Before releasing on main PyPI repo, you might prefer training + with the PyPI test site(1) which is cleaned on a semi regular + basis. See *note Using TestPyPI: f1. on how to setup your + configuration in order to use it. + + Warning: In other resources you may encounter references to using + ‘python setup.py register’ and ‘python setup.py upload’. These + methods of registering and uploading a package are `strongly + discouraged' as it may use a plaintext HTTP or unverified HTTPS + connection on some Python versions, allowing your username and + password to be intercepted during transmission. + + Tip: The reStructuredText parser used on PyPI is `not' Sphinx! + Furthermore, to ensure safety of all users, certain kinds of URLs + and directives are forbidden or stripped out (e.g., the ‘.. raw::’ + directive). `Before' trying to upload your distribution, you + should check to see if your brief / long descriptions provided in + ‘setup.py’ are valid. You can do this by running *note twine + check: 22. on your package files: + + twine check dist/* + +* Menu: + +* Create an account:: +* Upload your distributions:: + + ---------- Footnotes ---------- + + (1) https://test.pypi.org/ + + +File: pythonpackagingguide.info, Node: Create an account, Next: Upload your distributions, Up: Uploading your Project to PyPI + +3.8.5.1 Create an account +......................... + +First, you need a *note PyPI: 39. user account. You can create an +account using the form on the PyPI website(1). + +Now you’ll create a PyPI API token(2) so you will be able to securely +upload your project. + +Go to ‘https://pypi.org/manage/account/#api-tokens’ and create a new API +token(3); don’t limit its scope to a particular project, since you are +creating a new project. + +`Don’t close the page until you have copied and saved the token — you +won’t see that token again.' + + Note: To avoid having to copy and paste the token every time you + upload, you can create a ‘$HOME/.pypirc’ file: + + [pypi] + username = __token__ + password = + + `Be aware that this stores your token in plaintext.' + + For more details, see the *note specification: f3. for ‘.pypirc’. + + ---------- Footnotes ---------- + + (1) https://pypi.org/account/register/ + + (2) https://pypi.org/help/#apitoken + + (3) https://pypi.org/help/#apitoken + + +File: pythonpackagingguide.info, Node: Upload your distributions, Prev: Create an account, Up: Uploading your Project to PyPI + +3.8.5.2 Upload your distributions +................................. + +Once you have an account you can upload your distributions to *note +PyPI: 39. using *note twine: 6d. + +The process for uploading a release is the same regardless of whether or +not the project already exists on PyPI - if it doesn’t exist yet, it +will be automatically created when the first release is uploaded. + +For the second and subsequent releases, PyPI only requires that the +version number of the new release differ from any previous releases. + + twine upload dist/* + +You can see if your package has successfully uploaded by navigating to +the URL ‘https://pypi.org/project/’ where ‘sampleproject’ +is the name of your project that you uploaded. It may take a minute or +two for your project to appear on the site. + +__________________________________________________________________ + + +File: pythonpackagingguide.info, Node: Including files in source distributions with MANIFEST in, Next: Single-sourcing the package version, Prev: Packaging and distributing projects, Up: Guides + +3.9 Including files in source distributions with ‘MANIFEST.in’ +============================================================== + +When building a *note source distribution: 3d. for your package, by +default only a minimal set of files are included. You may find yourself +wanting to include extra files in the source distribution, such as an +authors/contributors file, a ‘docs/’ directory, or a directory of data +files used for testing purposes. There may even be extra files that you +`need' to include; for example, if your ‘setup.py’ computes your +project’s ‘long_description’ by reading from both a README and a +changelog file, you’ll need to include both those files in the sdist so +that people that build or install from the sdist get the correct +results. + +Adding & removing files to & from the source distribution is done by +writing a ‘MANIFEST.in’ file at the project root. + +* Menu: + +* How files are included in an sdist:: +* MANIFEST.in commands: MANIFEST in commands. + + +File: pythonpackagingguide.info, Node: How files are included in an sdist, Next: MANIFEST in commands, Up: Including files in source distributions with MANIFEST in + +3.9.1 How files are included in an sdist +---------------------------------------- + +The following files are included in a source distribution by default: + + - all Python source files implied by the ‘py_modules’ and ‘packages’ + ‘setup()’ arguments + + - all C source files mentioned in the ‘ext_modules’ or ‘libraries’ + ‘setup()’ arguments + + - scripts specified by the ‘scripts’ ‘setup()’ argument + + - all files specified by the ‘package_data’ and ‘data_files’ + ‘setup()’ arguments + + - the file specified by the ‘license_file’ option in ‘setup.cfg’ + (setuptools 40.8.0+) + + - all files specified by the ‘license_files’ option in ‘setup.cfg’ + (setuptools 42.0.0+) + + - all files matching the pattern ‘test/test*.py’ + + - ‘setup.py’ (or whatever you called your setup script) + + - ‘setup.cfg’ + + - ‘README’ + + - ‘README.txt’ + + - ‘README.rst’ (Python 3.7+ or setuptools 0.6.27+) + + - ‘README.md’ (setuptools 36.4.0+) + + - ‘pyproject.toml’ (setuptools 43.0.0+) + + - ‘MANIFEST.in’ + +After adding the above files to the sdist, the commands in ‘MANIFEST.in’ +(if such a file exists) are executed in order to add and remove further +files to and from the sdist. Default files can even be removed from the +sdist with the appropriate ‘MANIFEST.in’ command. + +After processing the ‘MANIFEST.in’ file, setuptools removes the ‘build/’ +directory as well as any directories named ‘RCS’, ‘CVS’, or ‘.svn’ from +the sdist, and it adds a ‘PKG-INFO’ file and an ‘*.egg-info’ directory. +This behavior cannot be changed with ‘MANIFEST.in’. + + +File: pythonpackagingguide.info, Node: MANIFEST in commands, Prev: How files are included in an sdist, Up: Including files in source distributions with MANIFEST in + +3.9.2 ‘MANIFEST.in’ commands +---------------------------- + +A ‘MANIFEST.in’ file consists of commands, one per line, instructing +setuptools to add or remove some set of files from the sdist. The +commands are: + +Command Description + +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +‘include `pat1' `pat2' ...’ Add all files matching any of the listed patterns (Files must be given as paths relative to the root + of the project) + + +‘exclude `pat1' `pat2' ...’ Remove all files matching any of the listed patterns (Files must be given as paths relative to the + root of the project) + + +‘recursive-include `dir-pattern' `pat1' `pat2' ...’ Add all files under directories matching ‘dir-pattern’ that match any of the listed patterns + + +‘recursive-exclude `dir-pattern' `pat1' `pat2' ...’ Remove all files under directories matching ‘dir-pattern’ that match any of the listed patterns + + +‘global-include `pat1' `pat2' ...’ Add all files anywhere in the source tree matching any of the listed patterns + + +‘global-exclude `pat1' `pat2' ...’ Remove all files anywhere in the source tree matching any of the listed patterns + + +‘graft `dir-pattern'’ Add all files under directories matching ‘dir-pattern’ + + +‘prune `dir-pattern'’ Remove all files under directories matching ‘dir-pattern’ + + +The patterns here are glob-style patterns: ‘*’ matches zero or more +regular filename characters (on Unix, everything except forward slash; +on Windows, everything except backslash and colon); ‘?’ matches a single +regular filename character, and ‘[chars]’ matches any one of the +characters between the square brackets (which may contain character +ranges, e.g., ‘[a-z]’ or ‘[a-fA-F0-9]’). Setuptools also has +undocumented support for ‘**’ matching zero or more characters including +forward slash, backslash, and colon. + +Directory patterns are relative to the root of the project directory; +e.g., ‘graft example*’ will include a directory named ‘examples’ in the +project root but will not include ‘docs/examples/’. + +File & directory names in ‘MANIFEST.in’ should be ‘/’-separated; +setuptools will automatically convert the slashes to the local +platform’s appropriate directory separator. + +Commands are processed in the order they appear in the ‘MANIFEST.in’ +file. For example, given the commands: + + graft tests + global-exclude *.py[cod] + +the contents of the directory tree ‘tests’ will first be added to the +sdist, and then after that all files in the sdist with a ‘.pyc’, ‘.pyo’, +or ‘.pyd’ extension will be removed from the sdist. If the commands +were in the opposite order, then ‘*.pyc’ files etc. would be only be +removed from what was already in the sdist before adding ‘tests’, and if +‘tests’ happened to contain any ‘*.pyc’ files, they would end up +included in the sdist because the exclusion happened before they were +included. + + +File: pythonpackagingguide.info, Node: Single-sourcing the package version, Next: Supporting multiple Python versions, Prev: Including files in source distributions with MANIFEST in, Up: Guides + +3.10 Single-sourcing the package version +======================================== + +There are many techniques to maintain a single source of truth for the +version number of your project: + + 1. Read the file in ‘setup.py’ and get the version. Example (from pip + setup.py(1)): + + import codecs + import os.path + + def read(rel_path): + here = os.path.abspath(os.path.dirname(__file__)) + with codecs.open(os.path.join(here, rel_path), 'r') as fp: + return fp.read() + + def get_version(rel_path): + for line in read(rel_path).splitlines(): + if line.startswith('__version__'): + delim = '"' if '"' in line else "'" + return line.split(delim)[1] + else: + raise RuntimeError("Unable to find version string.") + + setup( + ... + version=get_version("package/__init__.py") + ... + ) + + Note: As of the release of setuptools 46.4.0, one can + accomplish the same thing by instead placing the following in + the project’s ‘setup.cfg’ file (replacing “package” with the + import name of the package): + + [metadata] + version = attr: package.__version__ + + Earlier versions of setuptools implemented the ‘attr:’ + directive by importing the module, but setuptools 46.4.0 added + rudimentary AST analysis so that ‘attr:’ can function without + having to import any of the package’s dependencies. + + Also, please be aware that declarative config indicators, + including the ‘attr:’ directive, are not supported in + parameters to ‘setup.py’. + + 2. Use an external build tool that either manages updating both + locations, or offers an API that both locations can use. + + Few tools you could use, in no particular order, and not + necessarily complete: bump2version(2), changes(3), commitizen(4), + zest.releaser(5). + + 3. Set the value to a ‘__version__’ global variable in a dedicated + module in your project (e.g. ‘version.py’), then have ‘setup.py’ + read and ‘exec’ the value into a variable. + + version = {} + with open("...sample/version.py") as fp: + exec(fp.read(), version) + # later on we use: version['__version__'] + + Example using this technique: warehouse(6). + + 4. Place the value in a simple ‘VERSION’ text file and have both + ‘setup.py’ and the project code read it. + + with open(os.path.join(mypackage_root_dir, 'VERSION')) as version_file: + version = version_file.read().strip() + + An advantage with this technique is that it’s not specific to + Python. Any tool can read the version. + + Warning: With this approach you must make sure that the + ‘VERSION’ file is included in all your source and binary + distributions (e.g. add ‘include VERSION’ to your + ‘MANIFEST.in’). + + 5. Set the value in ‘setup.py’, and have the project code use the + ‘importlib.metadata’ API to fetch the value at runtime. + (‘importlib.metadata’ was introduced in Python 3.8 and is available + to older versions as the ‘importlib-metadata’ project.) An + installed project’s version can be fetched with the API as follows: + + import sys + + if sys.version_info >= (3, 8): + from importlib import metadata + else: + import importlib_metadata as metadata + + assert metadata.version('pip') == '1.2.0' + + Be aware that the ‘importlib.metadata’ API only knows about what’s + in the installation metadata, which is not necessarily the code + that’s currently imported. + + If a project uses this method to fetch its version at runtime, then + its ‘install_requires’ value needs to be edited to install + ‘importlib-metadata’ on pre-3.8 versions of Python like so: + + setup( + ... + install_requires=[ + ... + 'importlib-metadata >= 1.0 ; python_version < "3.8"', + ... + ], + ... + ) + + An older (and less efficient) alternative to ‘importlib.metadata’ + is the ‘pkg_resources’ API provided by ‘setuptools’: + + import pkg_resources + assert pkg_resources.get_distribution('pip').version == '1.2.0' + + If a project uses ‘pkg_resources’ to fetch its own version at + runtime, then ‘setuptools’ must be added to the project’s + ‘install_requires’ list. + + Example using this technique: setuptools(7). + + 6. Set the value to ‘__version__’ in ‘sample/__init__.py’ and import + ‘sample’ in ‘setup.py’. + + import sample + setup( + ... + version=sample.__version__ + ... + ) + + Warning: Although this technique is common, beware that it + will fail if ‘sample/__init__.py’ imports packages from + ‘install_requires’ dependencies, which will very likely not be + installed yet when ‘setup.py’ is run. + + 7. Keep the version number in the tags of a version control system + (Git, Mercurial, etc) instead of in the code, and automatically + extract it from there using setuptools_scm(8). + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/pip/blob/main/setup.py#L11 + + (2) https://pypi.org/project/bump2version + + (3) https://pypi.org/project/changes + + (4) https://pypi.org/project/commitizen + + (5) https://pypi.org/project/zest.releaser + + (6) +https://github.com/pypa/warehouse/blob/64ca42e42d5613c8339b3ec5e1cb7765c6b23083/warehouse/__about__.py + + (7) +https://github.com/pypa/setuptools/blob/main/setuptools/version.py + + (8) https://pypi.org/project/setuptools-scm/ + + +File: pythonpackagingguide.info, Node: Supporting multiple Python versions, Next: Dropping support for older Python versions, Prev: Single-sourcing the package version, Up: Guides + +3.11 Supporting multiple Python versions +======================================== + + +Page Status: Incomplete + + +Last Reviewed: 2014-12-24 + + FIXME + + Useful projects/resources to reference: + + - DONE six + - DONE python-future (http://python-future.org) + - tox + - DONE Travis and Shining Panda CI (Shining Panda no longer available) + - DONE Appveyor + - DONE Ned Batchelder's "What's in Which Python" + - http://nedbatchelder.com/blog/201310/whats_in_which_python_3.html + - http://nedbatchelder.com/blog/201109/whats_in_which_python.html + - Lennart Regebro's "Porting to Python 3" + - Greg Hewgill's script to identify the minimum version of Python + required to run a particular script: + https://github.com/ghewgill/pyqver + - the Python 3 porting how to in the main docs + - cross reference to the stable ABI discussion + in the binary extensions topic (once that exists) + - mention version classifiers for distribution metadata + +In addition to the work required to create a Python package, it is often +necessary that the package must be made available on different versions +of Python. Different Python versions may contain different (or renamed) +standard library packages, and the changes between Python versions 2.x +and 3.x include changes in the language syntax. + +Performed manually, all the testing required to ensure that the package +works correctly on all the target Python versions (and OSs!) could be +very time-consuming. Fortunately, several tools are available for +dealing with this, and these will briefly be discussed here. + +* Menu: + +* Automated testing and continuous integration:: +* Tools for single-source Python packages:: +* What’s in which Python?:: + + +File: pythonpackagingguide.info, Node: Automated testing and continuous integration, Next: Tools for single-source Python packages, Up: Supporting multiple Python versions + +3.11.1 Automated testing and continuous integration +--------------------------------------------------- + +Several hosted services for automated testing are available. These +services will typically monitor your source code repository (e.g. at +Github(1) or Bitbucket(2)) and run your project’s test suite every time +a new commit is made. + +These services also offer facilities to run your project’s test suite on +`multiple versions of Python', giving rapid feedback about whether the +code will work, without the developer having to perform such tests +themselves. + +Wikipedia has an extensive comparison(3) of many continuous-integration +systems. There are two hosted services which when used in conjunction +provide automated testing across Linux, Mac and Windows: + + - Travis CI(4) provides both a Linux and a macOS environment. + The Linux environment is Ubuntu 12.04 LTS Server Edition 64 + bit while the macOS is 10.9.2 at the time of writing. + + - Appveyor(5) provides a Windows environment (Windows Server + 2012). + + TODO Either link to or provide example .yml files for these two + services. + + TODO How do we keep the Travis Linux and macOS versions up-to-date in this + document? + +Both Travis CI(6) and Appveyor(7) require a YAML(8)-formatted file as +specification for the instructions for testing. If any tests fail, the +output log for that specific configuration can be inspected. + +For Python projects that are intended to be deployed on both Python 2 +and 3 with a single-source strategy, there are a number of options. + + ---------- Footnotes ---------- + + (1) https://github.com + + (2) https://bitbucket.org + + (3) +https://en.wikipedia.org/wiki/Comparison_of_continuous_integration_software + + (4) https://travis-ci.org + + (5) https://www.appveyor.com/ + + (6) https://travis-ci.org + + (7) https://www.appveyor.com/ + + (8) https://yaml.org + + +File: pythonpackagingguide.info, Node: Tools for single-source Python packages, Next: What’s in which Python?, Prev: Automated testing and continuous integration, Up: Supporting multiple Python versions + +3.11.2 Tools for single-source Python packages +---------------------------------------------- + +six(1) is a tool developed by Benjamin Peterson for wrapping over the +differences between Python 2 and Python 3. The six(2) package has +enjoyed widespread use and may be regarded as a reliable way to write a +single-source Python module that can be use in both Python 2 and 3. The +six(3) module can be used from as early as Python 2.5. A tool called +modernize(4), developed by Armin Ronacher, can be used to automatically +apply the code modifications provided by six(5). + +Similar to six(6), python-future(7) is a package that provides a +compatibility layer between Python 2 and Python 3 source code; however, +unlike six(8), this package aims to provide interoperability between +Python 2 and Python 3 with a language syntax that matches one of the two +Python versions: one may use + + - a Python 2 (by syntax) module in a Python 3 project. + + - a Python 3 (by syntax) module in a `Python 2' project. + +Because of the bi-directionality, python-future(9) offers a pathway to +converting a Python 2 package to Python 3 syntax module-by-module. +However, in contrast to six(10), python-future(11) is supported only +from Python 2.6. Similar to modernize(12) for six(13), +python-future(14) comes with two scripts called ‘futurize’ and +‘pasteurize’ that can be applied to either a Python 2 module or a Python +3 module respectively. + +Use of six(15) or python-future(16) adds an additional runtime +dependency to your package: with python-future(17), the ‘futurize’ +script can be called with the ‘--stage1’ option to apply only the +changes that Python 2.6+ already provides for forward-compatibility to +Python 3. Any remaining compatibility problems would require manual +changes. + + ---------- Footnotes ---------- + + (1) https://pypi.org/project/six/ + + (2) https://pypi.org/project/six/ + + (3) https://pypi.org/project/six/ + + (4) https://pypi.org/project/modernize + + (5) https://pypi.org/project/six/ + + (6) https://pypi.org/project/six/ + + (7) http://python-future.org/overview.html + + (8) https://pypi.org/project/six/ + + (9) http://python-future.org/overview.html + + (10) https://pypi.org/project/six/ + + (11) http://python-future.org/overview.html + + (12) https://pypi.org/project/modernize + + (13) https://pypi.org/project/six/ + + (14) http://python-future.org/overview.html + + (15) https://pypi.org/project/six/ + + (16) http://python-future.org/overview.html + + (17) http://python-future.org/overview.html + + +File: pythonpackagingguide.info, Node: What’s in which Python?, Prev: Tools for single-source Python packages, Up: Supporting multiple Python versions + +3.11.3 What’s in which Python? +------------------------------ + +Ned Batchelder provides a list of changes in each Python release for +Python 2(1), Python 3.0-3.3(2) and Python 3.4-3.6(3). These lists may +be used to check whether any changes between Python versions may affect +your package. + + TODO These lists should be reproduced here (with permission). + + TODO The py3 list should be updated to include 3.4 + + ---------- Footnotes ---------- + + (1) https://nedbatchelder.com/blog/201109/whats_in_which_python.html + + (2) +https://nedbatchelder.com/blog/201310/whats_in_which_python_3.html + + (3) +https://nedbatchelder.com/blog/201803/whats_in_which_python_3436.html + + +File: pythonpackagingguide.info, Node: Dropping support for older Python versions, Next: Packaging binary extensions, Prev: Supporting multiple Python versions, Up: Guides + +3.12 Dropping support for older Python versions +=============================================== + +Dropping support for older Python versions is supported by the standard +*note Core metadata specifications: 106. 1.2 specification via a +“Requires-Python” attribute. + +Metadata 1.2+ clients, such as Pip 9.0+, will adhere to this +specification by matching the current Python runtime and comparing it +with the required version in the package metadata. If they do not +match, it will attempt to install the last package distribution that +supported that Python runtime. + +This mechanism can be used to drop support for older Python versions, by +amending the “Requires-Python” attribute in the package metadata. + +This guide is specifically for users of *note setuptools: 2d, other +packaging tools such as ‘flit’ may offer similar functionality but users +will need to consult relevant documentation. + +* Menu: + +* Requirements:: +* Dealing with the universal wheels:: +* Defining the Python version required:: +* Dropping a Python release:: + + +File: pythonpackagingguide.info, Node: Requirements, Next: Dealing with the universal wheels, Up: Dropping support for older Python versions + +3.12.1 Requirements +------------------- + +This workflow requires that: + + 1. The publisher is using the latest version of *note setuptools: 2d, + + 2. The latest version of *note twine: 6d. is used to upload the + package, + + 3. The user installing the package has at least Pip 9.0, or a client + that supports the Metadata 1.2 specification. + + +File: pythonpackagingguide.info, Node: Dealing with the universal wheels, Next: Defining the Python version required, Prev: Requirements, Up: Dropping support for older Python versions + +3.12.2 Dealing with the universal wheels +---------------------------------------- + +Traditionally, projects providing Python code that is semantically +compatible with both Python 2 and Python 3, produce *note wheels: d. +that have a ‘py2.py3’ tag in their names. When dropping support for +Python 2, it is important not to forget to change this tag to just +‘py3’. It is often configured within ‘setup.cfg’ under the +‘[bdist_wheel]’ section by setting ‘universal = 1’ if they use +setuptools. + +If you use this method, either remove this option or section, or +explicitly set ‘universal’ to ‘0’: + + # setup.cfg + + [bdist_wheel] + universal = 0 # Make the generated wheels have `py3` tag + + Tip: Since it is possible to override the ‘setup.cfg’ settings via + CLI flags, make sure that your scripts don’t have ‘--universal’ in + your package creation scripts. + + +File: pythonpackagingguide.info, Node: Defining the Python version required, Next: Dropping a Python release, Prev: Dealing with the universal wheels, Up: Dropping support for older Python versions + +3.12.3 Defining the Python version required +------------------------------------------- + +* Menu: + +* 1. Download the newest version of Setuptools: 1 Download the newest version of Setuptools. +* 2. Specify the version ranges for supported Python distributions: 2 Specify the version ranges for supported Python distributions. +* 3. Validating the Metadata before publishing: 3 Validating the Metadata before publishing. +* 4. Using Twine to publish: 4 Using Twine to publish. + + +File: pythonpackagingguide.info, Node: 1 Download the newest version of Setuptools, Next: 2 Specify the version ranges for supported Python distributions, Up: Defining the Python version required + +3.12.3.1 1. Download the newest version of Setuptools +..................................................... + +Ensure that before you generate source distributions or binary +distributions, you update Setuptools and install twine. + +Steps: (Unix/macOS) + python3 -m pip install  --upgrade setuptools twine +(Windows) + py -m pip install  --upgrade setuptools twine + +*note setuptools: 2d. version should be above 24.0.0. + + +File: pythonpackagingguide.info, Node: 2 Specify the version ranges for supported Python distributions, Next: 3 Validating the Metadata before publishing, Prev: 1 Download the newest version of Setuptools, Up: Defining the Python version required + +3.12.3.2 2. Specify the version ranges for supported Python distributions +......................................................................... + +You can specify version ranges and exclusion rules, such as at least +Python 3. Or, Python 2.7, 3.4 and beyond. + +Examples: + + Requires-Python: ">=3" + Requires-Python: ">2.7,!=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +The way to set those values is within the call to ‘setup’ within your +‘setup.py’ script. This will insert the ‘Requires-Python’ metadata +values based on the argument you provide in ‘python_requires’. + + from setuptools import setup + + + setup( + # Your setup arguments + python_requires='>=2.7', # Your supported Python ranges + ) + + +File: pythonpackagingguide.info, Node: 3 Validating the Metadata before publishing, Next: 4 Using Twine to publish, Prev: 2 Specify the version ranges for supported Python distributions, Up: Defining the Python version required + +3.12.3.3 3. Validating the Metadata before publishing +..................................................... + +Within a Python source package (the zip or the tar-gz file you download) +is a text file called PKG-INFO. + +This file is generated by Distutils or *note setuptools: 2d. when it +generates the source package. The file contains a set of keys and +values, the list of keys is part of the PyPa standard metadata format. + +You can see the contents of the generated file like this: + + tar xfO dist/my-package-1.0.0.tar.gz my-package-1.0.0/PKG-INFO + +Validate that the following is in place, before publishing the package: + + - If you have upgraded correctly, the Metadata-Version value should + be 1.2 or higher. + + - The Requires-Python field is set and matches your specification in + setup.py. + + +File: pythonpackagingguide.info, Node: 4 Using Twine to publish, Prev: 3 Validating the Metadata before publishing, Up: Defining the Python version required + +3.12.3.4 4. Using Twine to publish +.................................. + +Twine has a number of advantages, apart from being faster it is now the +supported method for publishing packages. + +Make sure you are using the newest version of Twine, at least 1.9. + + +File: pythonpackagingguide.info, Node: Dropping a Python release, Prev: Defining the Python version required, Up: Dropping support for older Python versions + +3.12.4 Dropping a Python release +-------------------------------- + +Once you have published a package with the Requires-Python metadata, you +can then make a further update removing that Python runtime from +support. + +It must be done in this order for the automated fallback to work. + +For example, you published the Requires-Python: “>=2.7” as version 1.0.0 +of your package. + +If you were then to update the version string to “>=3.5”, and publish a +new version 2.0.0 of your package, any users running Pip 9.0+ from +version 2.7 will have version 1.0.0 of the package installed, and any +>=3.5 users will receive version 2.0.0. + + +File: pythonpackagingguide.info, Node: Packaging binary extensions, Next: Supporting Windows using Appveyor, Prev: Dropping support for older Python versions, Up: Guides + +3.13 Packaging binary extensions +================================ + + +Page Status: Incomplete + + +Last Reviewed: 2013-12-08 + +One of the features of the CPython reference interpreter is that, in +addition to allowing the execution of Python code, it also exposes a +rich C API for use by other software. One of the most common uses of +this C API is to create importable C extensions that allow things which +aren’t always easy to achieve in pure Python code. + +* Menu: + +* An overview of binary extensions:: +* Implementing binary extensions:: +* Building binary extensions:: +* Publishing binary extensions:: +* Additional resources:: + + +File: pythonpackagingguide.info, Node: An overview of binary extensions, Next: Implementing binary extensions, Up: Packaging binary extensions + +3.13.1 An overview of binary extensions +--------------------------------------- + +* Menu: + +* Use cases:: +* Disadvantages:: +* Alternatives to handcoded accelerator modules:: +* Alternatives to handcoded wrapper modules:: +* Alternatives for low level system access:: + + +File: pythonpackagingguide.info, Node: Use cases, Next: Disadvantages, Up: An overview of binary extensions + +3.13.1.1 Use cases +.................. + +The typical use cases for binary extensions break down into just three +conventional categories: + + * `accelerator modules': these modules are completely self-contained, + and are created solely to run faster than the equivalent pure + Python code runs in CPython. Ideally, accelerator modules will + always have a pure Python equivalent to use as a fallback if the + accelerated version isn’t available on a given system. The CPython + standard library makes extensive use of accelerator modules. + `Example': When importing ‘datetime’, Python falls back to the + datetime.py(1) module if the C implementation ( + _datetimemodule.c(2)) is not available. + + * `wrapper modules': these modules are created to expose existing C + interfaces to Python code. They may either expose the underlying C + interface directly, or else expose a more “Pythonic” API that makes + use of Python language features to make the API easier to use. The + CPython standard library makes extensive use of wrapper modules. + `Example': functools.py(3) is a Python module wrapper for + _functoolsmodule.c(4). + + * `low-level system access': these modules are created to access + lower level features of the CPython runtime, the operating system, + or the underlying hardware. Through platform specific code, + extension modules may achieve things that aren’t possible in pure + Python code. A number of CPython standard library modules are + written in C in order to access interpreter internals that aren’t + exposed at the language level. `Example': ‘sys’, which comes from + sysmodule.c(5). + + One particularly notable feature of C extensions is that, when they + don’t need to call back into the interpreter runtime, they can + release CPython’s global interpreter lock around long-running + operations (regardless of whether those operations are CPU or IO + bound). + +Not all extension modules will fit neatly into the above categories. +The extension modules included with NumPy, for example, span all three +use cases - they move inner loops to C for speed reasons, wrap external +libraries written in C, FORTRAN and other languages, and use low level +system interfaces for both CPython and the underlying operation system +to support concurrent execution of vectorised operations and to tightly +control the exact memory layout of created objects. + + ---------- Footnotes ---------- + + (1) https://github.com/python/cpython/blob/main/Lib/datetime.py + + (2) +https://github.com/python/cpython/blob/main/Modules/_datetimemodule.c + + (3) https://github.com/python/cpython/blob/main/Lib/functools.py + + (4) +https://github.com/python/cpython/blob/main/Modules/_functoolsmodule.c + + (5) https://github.com/python/cpython/blob/main/Python/sysmodule.c + + +File: pythonpackagingguide.info, Node: Disadvantages, Next: Alternatives to handcoded accelerator modules, Prev: Use cases, Up: An overview of binary extensions + +3.13.1.2 Disadvantages +...................... + +The main disadvantage of using binary extensions is the fact that it +makes subsequent distribution of the software more difficult. One of +the advantages of using Python is that it is largely cross platform, and +the languages used to write extension modules (typically C or C++, but +really any language that can bind to the CPython C API) typically +require that custom binaries be created for different platforms. + +This means that binary extensions: + + * require that end users be able to either build them from source, or + else that someone publish pre-built binaries for common platforms + + * may not be compatible with different builds of the CPython + reference interpreter + + * often will not work correctly with alternative interpreters such as + PyPy, IronPython or Jython + + * if handcoded, make maintenance more difficult by requiring that + maintainers be familiar not only with Python, but also with the + language used to create the binary extension, as well as with the + details of the CPython C API. + + * if a pure Python fallback implementation is provided, make + maintenance more difficult by requiring that changes be implemented + in two places, and introducing additional complexity in the test + suite to ensure both versions are always executed. + +Another disadvantage of relying on binary extensions is that alternative +import mechanisms (such as the ability to import modules directly from +zipfiles) often won’t work for extension modules (as the dynamic loading +mechanisms on most platforms can only load libraries from disk). + + +File: pythonpackagingguide.info, Node: Alternatives to handcoded accelerator modules, Next: Alternatives to handcoded wrapper modules, Prev: Disadvantages, Up: An overview of binary extensions + +3.13.1.3 Alternatives to handcoded accelerator modules +...................................................... + +When extension modules are just being used to make code run faster +(after profiling has identified the code where the speed increase is +worth additional maintenance effort), a number of other alternatives +should also be considered: + + * look for existing optimised alternatives. The CPython standard + library includes a number of optimised data structures and + algorithms (especially in the builtins and the ‘collections’ and + ‘itertools’ modules). The Python Package Index also offers + additional alternatives. Sometimes, the appropriate choice of + standard library or third party module can avoid the need to create + your own accelerator module. + + * for long running applications, the JIT compiled PyPy interpreter(1) + may offer a suitable alternative to the standard CPython runtime. + The main barrier to adopting PyPy is typically reliance on other + binary extension modules - while PyPy does emulate the CPython C + API, modules that rely on that cause problems for the PyPy JIT, and + the emulation layer can often expose latent defects in extension + modules that CPython currently tolerates (frequently around + reference counting errors - an object having one live reference + instead of two often won’t break anything, but no references + instead of one is a major problem). + + * Cython(2) is a mature static compiler that can compile most Python + code to C extension modules. The initial compilation provides some + speed increases (by bypassing the CPython interpreter layer), and + Cython’s optional static typing features can offer additional + opportunities for speed increases. Using Cython still carries the + *note disadvantages: 113. associated with using binary extensions, + but has the benefit of having a reduced barrier to entry for Python + programmers (relative to other languages like C or C++). + + * Numba(3) is a newer tool, created by members of the scientific + Python community, that aims to leverage LLVM to allow selective + compilation of pieces of a Python application to native machine + code at runtime. It requires that LLVM be available on the system + where the code is running, but can provide significant speed + increases, especially for operations that are amenable to + vectorisation. + + ---------- Footnotes ---------- + + (1) https://www.pypy.org/ + + (2) https://cython.org/ + + (3) http://numba.pydata.org/ + + +File: pythonpackagingguide.info, Node: Alternatives to handcoded wrapper modules, Next: Alternatives for low level system access, Prev: Alternatives to handcoded accelerator modules, Up: An overview of binary extensions + +3.13.1.4 Alternatives to handcoded wrapper modules +.................................................. + +The C ABI (Application Binary Interface) is a common standard for +sharing functionality between multiple applications. One of the +strengths of the CPython C API (Application Programming Interface) is +allowing Python users to tap into that functionality. However, wrapping +modules by hand is quite tedious, so a number of other alternative +approaches should be considered. + +The approaches described below don’t simplify the distribution case at +all, but they `can' significantly reduce the maintenance burden of +keeping wrapper modules up to date. + + * In addition to being useful for the creation of accelerator + modules, Cython(1) is also widely used for creating wrapper modules + for C or C++ APIs. It involves wrapping the interfaces by hand, + which gives a wide range of freedom in designing and optimising the + wrapper code, but may not be a good choice for wrapping very large + APIs quickly. See the list of third-party tools(2) for automatic + wrapping with Cython. It also supports performance-oriented Python + implementations that provide a CPython-like C-API, such as PyPy and + Pyston. + + * pybind11(3) is a pure C++11 library that provides a clean C++ + interface to the CPython (and PyPy) C API. It does not require a + pre-processing step; it is written entirely in templated C++. + Helpers are included for Setuptools or CMake builds. It was based + on Boost.Python(4), but doesn’t require the Boost libraries or + BJam. + + * cffi(5) is a project created by some of the PyPy developers to make + it straightforward for developers that already know both Python and + C to expose their C modules to Python applications. It also makes + it relatively straightforward to wrap a C module based on its + header files, even if you don’t know C yourself. + + One of the key advantages of ‘cffi’ is that it is compatible with + the PyPy JIT, allowing CFFI wrapper modules to participate fully in + PyPy’s tracing JIT optimisations. + + * SWIG(6) is a wrapper interface generator that allows a variety of + programming languages, including Python, to interface with C and + C++ code. + + * The standard library’s ‘ctypes’ module, while useful for getting + access to C level interfaces when header information isn’t + available, suffers from the fact that it operates solely at the C + ABI level, and thus has no automatic consistency checking between + the interface actually being exported by the library and the one + declared in the Python code. By contrast, the above alternatives + are all able to operate at the C `API' level, using C header files + to ensure consistency between the interface exported by the library + being wrapped and the one expected by the Python wrapper module. + While ‘cffi’ `can' operate directly at the C ABI level, it suffers + from the same interface inconsistency problems as ‘ctypes’ when it + is used that way. + + ---------- Footnotes ---------- + + (1) https://cython.org/ + + (2) https://github.com/cython/cython/wiki/AutoPxd + + (3) https://pybind11.readthedocs.io/en/stable/index.html + + (4) +https://www.boost.org/doc/libs/1_76_0/libs/python/doc/html/index.html + + (5) https://cffi.readthedocs.io/en/latest/index.html + + (6) http://www.swig.org/ + + +File: pythonpackagingguide.info, Node: Alternatives for low level system access, Prev: Alternatives to handcoded wrapper modules, Up: An overview of binary extensions + +3.13.1.5 Alternatives for low level system access +................................................. + +For applications that need low level system access (regardless of the +reason), a binary extension module often `is' the best way to go about +it. This is particularly true for low level access to the CPython +runtime itself, since some operations (like releasing the Global +Interpreter Lock) are simply invalid when the interpreter is running +code, even if a module like ‘ctypes’ or ‘cffi’ is used to obtain access +to the relevant C API interfaces. + +For cases where the extension module is manipulating the underlying +operating system or hardware (rather than the CPython runtime), it may +sometimes be better to just write an ordinary C library (or a library in +another systems programming language like C++ or Rust that can export a +C compatible ABI), and then use one of the wrapping techniques described +above to make the interface available as an importable Python module. + + +File: pythonpackagingguide.info, Node: Implementing binary extensions, Next: Building binary extensions, Prev: An overview of binary extensions, Up: Packaging binary extensions + +3.13.2 Implementing binary extensions +------------------------------------- + +The CPython Extending and Embedding(1) guide includes an introduction to +writing a custom extension module in C(2). + + mention the stable ABI (3.2+, link to the CPython C API docs) + mention the module lifecycle + mention the challenges of shared static state and subinterpreters + mention the implications of the GIL for extension modules + mention the memory allocation APIs in 3.4+ + + mention again that all this is one of the reasons why you probably + *don't* want to handcode your extension modules :) + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/extending/index.html + + (2) https://docs.python.org/3/extending/extending.html + + +File: pythonpackagingguide.info, Node: Building binary extensions, Next: Publishing binary extensions, Prev: Implementing binary extensions, Up: Packaging binary extensions + +3.13.3 Building binary extensions +--------------------------------- + +* Menu: + +* Building extensions for multiple platforms:: +* Binary extensions for Windows:: +* Binary extensions for Linux:: +* Binary extensions for macOS:: + + +File: pythonpackagingguide.info, Node: Building extensions for multiple platforms, Next: Binary extensions for Windows, Up: Building binary extensions + +3.13.3.1 Building extensions for multiple platforms +................................................... + +If you plan to distribute your extension, you should provide *note +wheels: d. for all the platforms you intend to support. For most +extensions, this is at least one package per Python version times the +number of OS and architectures you support. These are usually built on +continuous integration (CI) systems. There are tools to help you build +highly redistributable binaries from CI; these include *note +cibuildwheel: 11a. and *note multibuild: 11b. + + +File: pythonpackagingguide.info, Node: Binary extensions for Windows, Next: Binary extensions for Linux, Prev: Building extensions for multiple platforms, Up: Building binary extensions + +3.13.3.2 Binary extensions for Windows +...................................... + +Before it is possible to build a binary extension, it is necessary to +ensure that you have a suitable compiler available. On Windows, Visual +C is used to build the official CPython interpreter, and should be used +to build compatible binary extensions. To set up a build environment +for binary extensions, install Visual Studio Community Edition(1) - any +recent version is fine. + +One caveat: if you use Visual Studio 2019 or later, your extension will +depend on an “extra” file, ‘VCRUNTIME140_1.dll’, in addition to the +‘VCRUNTIME140.dll’ that all previous versions back to 2015 depend on. +This will add an extra requirement to using your extension on versions +of CPython that do not include this extra file. To avoid this, you can +add the compile-time argument ‘/d2FH4-’. Recent versions of Python may +include this file. + +Building for Python prior to 3.5 is discouraged, because older versions +of Visual Studio are no longer available from Microsoft. If you do need +to build for older versions, you can set ‘DISTUTILS_USE_SDK=1’ and +‘MSSdk=1’ to force a the currently activated version of MSVC to be +found, and you should exercise care when designing your extension not to +malloc/free memory across different libraries, avoid relying on changed +data structures, and so on. Tools for generating extension modules +usually avoid these things for you. + + ---------- Footnotes ---------- + + (1) https://visualstudio.microsoft.com/downloads/ + + +File: pythonpackagingguide.info, Node: Binary extensions for Linux, Next: Binary extensions for macOS, Prev: Binary extensions for Windows, Up: Building binary extensions + +3.13.3.3 Binary extensions for Linux +.................................... + +Linux binaries must use a sufficiently old glibc to be compatible with +older distributions. The manylinux(1) Docker images provide a build +environment with a glibc old enough to support most current Linux +distributions on common architectures. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/manylinux + + +File: pythonpackagingguide.info, Node: Binary extensions for macOS, Prev: Binary extensions for Linux, Up: Building binary extensions + +3.13.3.4 Binary extensions for macOS +.................................... + +Binary compatibility on macOS is determined by the target minimum +deployment system, e.g. `10.9', which is often specified with the +‘MACOSX_DEPLOYMENT_TARGET’ environmental variable when building binaries +on macOS. When building with setuptools / distutils, the deployment +target is specified with the flag ‘--plat-name’, e.g. +‘macosx-10.9-x86_64’. For common deployment targets for macOS Python +distributions, see the MacPython Spinning Wheels wiki(1). + + ---------- Footnotes ---------- + + (1) https://github.com/MacPython/wiki/wiki/Spinning-wheels + + +File: pythonpackagingguide.info, Node: Publishing binary extensions, Next: Additional resources, Prev: Building binary extensions, Up: Packaging binary extensions + +3.13.4 Publishing binary extensions +----------------------------------- + +For interim guidance on this topic, see the discussion in this issue(1). + + FIXME + + cover publishing as wheel files on PyPI or a custom index server + cover creation of Windows and macOS installers + cover weak linking + mention the fact that Linux distros have a requirement to build from + source in their own build systems, so binary-only releases are strongly + discouraged + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/issues/284 + + +File: pythonpackagingguide.info, Node: Additional resources, Prev: Publishing binary extensions, Up: Packaging binary extensions + +3.13.5 Additional resources +--------------------------- + +Cross-platform development and distribution of extension modules is a +complex topic, so this guide focuses primarily on providing pointers to +various tools that automate dealing with the underlying technical +challenges. The additional resources in this section are instead +intended for developers looking to understand more about the underlying +binary interfaces that those systems rely on at runtime. + +* Menu: + +* Cross-platform wheel generation with scikit-build:: +* Introduction to C/C++ extension modules:: + + +File: pythonpackagingguide.info, Node: Cross-platform wheel generation with scikit-build, Next: Introduction to C/C++ extension modules, Up: Additional resources + +3.13.5.1 Cross-platform wheel generation with scikit-build +.......................................................... + +The scikit-build(1) package helps abstract cross-platform build +operations and provides additional capabilities when creating binary +extension packages. Additional documentation is also available on the C +runtime, compiler, and build system generator(2) for Python binary +extension modules. + + ---------- Footnotes ---------- + + (1) https://scikit-build.readthedocs.io/en/latest/ + + (2) https://scikit-build.readthedocs.io/en/latest/generators.html + + +File: pythonpackagingguide.info, Node: Introduction to C/C++ extension modules, Prev: Cross-platform wheel generation with scikit-build, Up: Additional resources + +3.13.5.2 Introduction to C/C++ extension modules +................................................ + +For a more in depth explanation of how extension modules are used by +CPython on a Debian system, see the following articles: + + * What are (c)python extension modules?(1) + + * Releasing the gil(2) + + * Writing cpython extension modules using C++(3) + + ---------- Footnotes ---------- + + (1) https://thomasnyberg.com/what_are_extension_modules.html + + (2) https://thomasnyberg.com/releasing_the_gil.html + + (3) https://thomasnyberg.com/cpp_extension_modules.html + + +File: pythonpackagingguide.info, Node: Supporting Windows using Appveyor, Next: Packaging namespace packages, Prev: Packaging binary extensions, Up: Guides + +3.14 Supporting Windows using Appveyor +====================================== + + +Page Status: Incomplete + + +Last Reviewed: 2015-12-03 + +This section covers how to use the free Appveyor(1) continuous +integration service to provide Windows support for your project. This +includes testing the code on Windows, and building Windows-targeted +binaries for projects that use C extensions. + +* Menu: + +* Background:: +* Setting up:: +* Adding Appveyor support to your project:: +* Additional notes:: + + ---------- Footnotes ---------- + + (1) https://www.appveyor.com/ + + +File: pythonpackagingguide.info, Node: Background, Next: Setting up, Up: Supporting Windows using Appveyor + +3.14.1 Background +----------------- + +Many projects are developed on Unix by default, and providing Windows +support can be a challenge, because setting up a suitable Windows test +environment is non-trivial, and may require buying software licenses. + +The Appveyor service is a continuous integration service, much like the +better-known Travis(1) service that is commonly used for testing by +projects hosted on Github(2). However, unlike Travis, the build workers +on Appveyor are Windows hosts and have the necessary compilers installed +to build Python extensions. + +Windows users typically do not have access to a C compiler, and +therefore are reliant on projects that use C extensions distributing +binary wheels on PyPI in order for the distribution to be installable +via ‘python -m pip install ’. By using Appveyor as a build +service (even if not using it for testing) it is possible for projects +without a dedicated Windows environment to provide Windows-targeted +binaries. + + ---------- Footnotes ---------- + + (1) https://travis-ci.org/ + + (2) https://github.com + + +File: pythonpackagingguide.info, Node: Setting up, Next: Adding Appveyor support to your project, Prev: Background, Up: Supporting Windows using Appveyor + +3.14.2 Setting up +----------------- + +In order to use Appveyor to build Windows wheels for your project, you +must have an account on the service. Instructions on setting up an +account are given in the Appveyor documentation(1). The free tier of +account is perfectly adequate for open source projects. + +Appveyor provides integration with Github(2) and Bitbucket(3), so as +long as your project is hosted on one of those two services, setting up +Appveyor integration is straightforward. + +Once you have set up your Appveyor account and added your project, +Appveyor will automatically build your project each time a commit +occurs. This behaviour will be familiar to users of Travis. + + ---------- Footnotes ---------- + + (1) https://www.appveyor.com/docs/ + + (2) https://github.com + + (3) https://bitbucket.org/ + + +File: pythonpackagingguide.info, Node: Adding Appveyor support to your project, Next: Additional notes, Prev: Setting up, Up: Supporting Windows using Appveyor + +3.14.3 Adding Appveyor support to your project +---------------------------------------------- + +In order to define how Appveyor should build your project, you need to +add an ‘appveyor.yml’ file to your project. The full details of what +can be included in the file are covered in the Appveyor documentation. +This guide will provide the details necessary to set up wheel builds. + +Appveyor includes by default all of the compiler toolchains needed to +build extensions for Python. For Python 2.7, 3.5+ and 32-bit versions +of 3.3 and 3.4, the tools work out of the box. But for 64-bit versions +of Python 3.3 and 3.4, there is a small amount of additional +configuration needed to let distutils know where to find the 64-bit +compilers. (From 3.5 onwards, the version of Visual Studio used +includes 64-bit compilers with no additional setup). + +* Menu: + +* appveyor.yml: appveyor yml. +* Support script:: +* Access to the built wheels:: + + +File: pythonpackagingguide.info, Node: appveyor yml, Next: Support script, Up: Adding Appveyor support to your project + +3.14.3.1 appveyor.yml +..................... + + environment: + + matrix: + + # For Python versions available on Appveyor, see + # https://www.appveyor.com/docs/windows-images-software/#python + # The list here is complete (excluding Python 2.6, which + # isn't covered by this document) at the time of writing. + + - PYTHON: "C:\\Python27" + - PYTHON: "C:\\Python33" + - PYTHON: "C:\\Python34" + - PYTHON: "C:\\Python35" + - PYTHON: "C:\\Python27-x64" + - PYTHON: "C:\\Python33-x64" + DISTUTILS_USE_SDK: "1" + - PYTHON: "C:\\Python34-x64" + DISTUTILS_USE_SDK: "1" + - PYTHON: "C:\\Python35-x64" + - PYTHON: "C:\\Python36-x64" + + install: + # We need wheel installed to build wheels + - "%PYTHON%\\python.exe -m pip install wheel" + + build: off + + test_script: + # Put your test command here. + # If you don't need to build C extensions on 64-bit Python 3.3 or 3.4, + # you can remove "build.cmd" from the front of the command, as it's + # only needed to support those cases. + # Note that you must use the environment variable %PYTHON% to refer to + # the interpreter you're using - Appveyor does not do anything special + # to put the Python version you want to use on PATH. + - "build.cmd %PYTHON%\\python.exe setup.py test" + + after_test: + # This step builds your wheels. + # Again, you only need build.cmd if you're building C extensions for + # 64-bit Python 3.3/3.4. And you need to use %PYTHON% to get the correct + # interpreter + - "build.cmd %PYTHON%\\python.exe setup.py bdist_wheel" + + artifacts: + # bdist_wheel puts your built wheel in the dist directory + - path: dist\* + + #on_success: + # You can use this step to upload your artifacts to a public website. + # See Appveyor's documentation for more details. Or you can simply + # access your wheels from the Appveyor "artifacts" tab for your build. + +This file can be downloaded from here(1). + +The ‘appveyor.yml’ file must be located in the root directory of your +project. It is in ‘YAML’ format, and consists of a number of sections. + +The ‘environment’ section is the key to defining the Python versions for +which your wheels will be created. Appveyor comes with Python 2.6, 2.7, +3.3, 3.4 and 3.5 installed, in both 32-bit and 64-bit builds. The +example file builds for all of these environments except Python 2.6. +Installing for Python 2.6 is more complex, as it does not come with pip +included. We don’t support 2.6 in this document (as Windows users still +using Python 2 are generally able to move to Python 2.7 without too much +difficulty). + +The ‘install’ section uses pip to install any additional software that +the project may require. The only requirement for building wheels is +the ‘wheel’ project, but projects may wish to customise this code in +certain circumstances (for example, to install additional build packages +such as ‘Cython’, or test tools such as ‘tox’). + +The ‘build’ section simply switches off builds - there is no build step +needed for Python, unlike languages like ‘C#’. + +The main sections that will need to be tailored to your project are +‘test_script’ and ‘after_test’. + +The ‘test_script’ section is where you will run your project’s tests. +The supplied file runs your test suite using ‘setup.py test’. If you +are only interested in building wheels, and not in running your tests on +Windows, you can replace this section with a dummy command such as ‘echo +Skipped Tests’. You may wish to use another test tool, such as ‘nose’ +or ‘py.test’. Or you may wish to use a test driver like ‘tox’ - however +if you are using ‘tox’ there are some additional configuration changes +you will need to consider, which are described below. + +The ‘after_test’ runs once your tests have completed, and so is where +the wheels should be built. Assuming your project uses the recommended +tools (specifically, ‘setuptools’) then the ‘setup.py bdist_wheel’ +command will build your wheels. + +Note that wheels will only be built if your tests succeed. If you +expect your tests to fail on Windows, you can skip them as described +above. + + ---------- Footnotes ---------- + + (1) +https://raw.githubusercontent.com/pypa/python-packaging-user-guide/master/source/guides/appveyor-sample/appveyor.yml + + +File: pythonpackagingguide.info, Node: Support script, Next: Access to the built wheels, Prev: appveyor yml, Up: Adding Appveyor support to your project + +3.14.3.2 Support script +....................... + +The ‘appveyor.yml’ file relies on a single support script, which sets up +the environment to use the SDK compiler for 64-bit builds on Python 3.3 +and 3.4. For projects which do not need a compiler, or which don’t +support 3.3 or 3.4 on 64-bit Windows, only the ‘appveyor.yml’ file is +needed. + +build.cmd(1) is a Windows batch script that runs a single command in an +environment with the appropriate compiler for the selected Python +version. All you need to do is to set the single environment variable +‘DISTUTILS_USE_SDK’ to a value of ‘1’ and the script does the rest. It +sets up the SDK needed for 64-bit builds of Python 3.3 or 3.4, so don’t +set the environment variable for any other builds. + +You can simply download the batch file and include it in your project +unchanged. + + ---------- Footnotes ---------- + + (1) +https://raw.githubusercontent.com/pypa/python-packaging-user-guide/master/source/guides/appveyor-sample/build.cmd + + +File: pythonpackagingguide.info, Node: Access to the built wheels, Prev: Support script, Up: Adding Appveyor support to your project + +3.14.3.3 Access to the built wheels +................................... + +When your build completes, the built wheels will be available from the +Appveyor control panel for your project. They can be found by going to +the build status page for each build in turn. At the top of the build +output there is a series of links, one of which is “Artifacts”. That +page will include a list of links to the wheels for that Python version +/ architecture. You can download those wheels and upload them to PyPI +as part of your release process. + + +File: pythonpackagingguide.info, Node: Additional notes, Prev: Adding Appveyor support to your project, Up: Supporting Windows using Appveyor + +3.14.4 Additional notes +----------------------- + +* Menu: + +* Testing with tox:: +* Automatically uploading wheels:: +* External dependencies:: +* Support scripts:: + + +File: pythonpackagingguide.info, Node: Testing with tox, Next: Automatically uploading wheels, Up: Additional notes + +3.14.4.1 Testing with tox +......................... + +Many projects use the Tox(1) tool to run their tests. It ensures that +tests are run in an isolated environment using the exact files that will +be distributed by the project. + +In order to use ‘tox’ on Appveyor there are a couple of additional +considerations (in actual fact, these issues are not specific to +Appveyor, and may well affect other CI systems). + + 1. By default, ‘tox’ only passes a chosen subset of environment + variables to the test processes. Because ‘distutils’ uses + environment variables to control the compiler, this “test + isolation” feature will cause the tests to use the wrong compiler + by default. + + To force ‘tox’ to pass the necessary environment variables to the + subprocess, you need to set the ‘tox’ configuration option + ‘passenv’ to list the additional environment variables to be passed + to the subprocess. For the SDK compilers, you need + + - ‘DISTUTILS_USE_SDK’ + + - ‘MSSdk’ + + - ‘INCLUDE’ + + - ‘LIB’ + + The ‘passenv’ option can be set in your ‘tox.ini’, or if you + prefer to avoid adding Windows-specific settings to your + general project files, it can be set by setting the + ‘TOX_TESTENV_PASSENV’ environment variable. The supplied + ‘build.cmd’ script does this by default whenever + ‘DISTUTILS_USE_SDK’ is set. + + 2. When used interactively, ‘tox’ allows you to run your tests against + multiple environments (often, this means multiple Python versions). + This feature is not as useful in a CI environment like Travis or + Appveyor, where all tests are run in isolated environments for each + configuration. As a result, projects often supply an argument ‘-e + ENVNAME’ to ‘tox’ to specify which environment to use (there are + default environments for most versions of Python). + + However, this does `not' work well with a Windows CI system + like Appveyor, where there are (for example) two installations + of Python 3.4 (32-bit and 64-bit) available, but only one + ‘py34’ environment in ‘tox’. + + In order to run tests using ‘tox’, therefore, projects should + probably use the default ‘py’ environment in ‘tox’, which uses + the Python interpreter that was used to run ‘tox’. This will + ensure that when Appveyor runs the tests, they will be run + with the configured interpreter. + + In order to support running under the ‘py’ environment, it is + possible that projects with complex ‘tox’ configurations might + need to modify their ‘tox.ini’ file. Doing so is, however, + outside the scope of this document. + + ---------- Footnotes ---------- + + (1) https://tox.wiki/en/latest/index.html + + +File: pythonpackagingguide.info, Node: Automatically uploading wheels, Next: External dependencies, Prev: Testing with tox, Up: Additional notes + +3.14.4.2 Automatically uploading wheels +....................................... + +It is possible to request Appveyor to automatically upload wheels. +There is a ‘deployment’ step available in ‘appveyor.yml’ that can be +used to (for example) copy the built artifacts to a FTP site, or an +Amazon S3 instance. Documentation on how to do this is included in the +Appveyor guides. + +Alternatively, it would be possible to add a ‘twine upload’ step to the +build. The supplied ‘appveyor.yml’ does not do this, as it is not clear +that uploading new wheels after every commit is desirable (although some +projects may wish to do this). + + +File: pythonpackagingguide.info, Node: External dependencies, Next: Support scripts, Prev: Automatically uploading wheels, Up: Additional notes + +3.14.4.3 External dependencies +.............................. + +The supplied scripts will successfully build any distribution that does +not rely on 3rd party external libraries for the build. + +It is possible to add steps to the ‘appveyor.yml’ configuration +(typically in the “install” section) to download and/or build external +libraries needed by the distribution. And if needed, it is possible to +add extra configuration for the build to supply the location of these +libraries to the compiler. However, this level of configuration is +beyond the scope of this document. + + +File: pythonpackagingguide.info, Node: Support scripts, Prev: External dependencies, Up: Additional notes + +3.14.4.4 Support scripts +........................ + +For reference, the SDK setup support script is listed here: + +‘appveyor-sample/build.cmd’ + + @echo off + :: To build extensions for 64 bit Python 3, we need to configure environment + :: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of: + :: MS Windows SDK for Windows 7 and .NET Framework 4 + :: + :: More details at: + :: https://github.com/cython/cython/wiki/CythonExtensionsOnWindows + + IF "%DISTUTILS_USE_SDK%"=="1" ( + ECHO Configuring environment to build with MSVC on a 64bit architecture + ECHO Using Windows SDK 7.1 + "C:\Program Files\Microsoft SDKs\Windows\v7.1\Setup\WindowsSdkVer.exe" -q -version:v7.1 + CALL "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 /release + SET MSSdk=1 + REM Need the following to allow tox to see the SDK compiler + SET TOX_TESTENV_PASSENV=DISTUTILS_USE_SDK MSSdk INCLUDE LIB + ) ELSE ( + ECHO Using default MSVC build environment + ) + + CALL %* + + +File: pythonpackagingguide.info, Node: Packaging namespace packages, Next: Creating and discovering plugins, Prev: Supporting Windows using Appveyor, Up: Guides + +3.15 Packaging namespace packages +================================= + +Namespace packages allow you to split the sub-packages and modules +within a single *note package: a. across multiple, separate *note +distribution packages: b. (referred to as `distributions' in this +document to avoid ambiguity). For example, if you have the following +package structure: + + mynamespace/ + __init__.py + subpackage_a/ + __init__.py + ... + subpackage_b/ + __init__.py + ... + module_b.py + setup.py + +And you use this package in your code like so: + + from mynamespace import subpackage_a + from mynamespace import subpackage_b + +Then you can break these sub-packages into two separate distributions: + + mynamespace-subpackage-a/ + setup.py + mynamespace/ + subpackage_a/ + __init__.py + + mynamespace-subpackage-b/ + setup.py + mynamespace/ + subpackage_b/ + __init__.py + module_b.py + +Each sub-package can now be separately installed, used, and versioned. + +Namespace packages can be useful for a large collection of +loosely-related packages (such as a large corpus of client libraries for +multiple products from a single company). However, namespace packages +come with several caveats and are not appropriate in all cases. A +simple alternative is to use a prefix on all of your distributions such +as ‘import mynamespace_subpackage_a’ (you could even use ‘import +mynamespace_subpackage_a as subpackage_a’ to keep the import object +short). + +* Menu: + +* Creating a namespace package:: + + +File: pythonpackagingguide.info, Node: Creating a namespace package, Up: Packaging namespace packages + +3.15.1 Creating a namespace package +----------------------------------- + +There are currently three different approaches to creating namespace +packages: + + 1. Use *note native namespace packages: 134. This type of namespace + package is defined in PEP 420(1) and is available in Python 3.3 and + later. This is recommended if packages in your namespace only ever + need to support Python 3 and installation via ‘pip’. + + 2. Use *note pkgutil-style namespace packages: 135. This is + recommended for new packages that need to support Python 2 and 3 + and installation via both ‘pip’ and ‘python setup.py install’. + + 3. Use *note pkg_resources-style namespace packages: 136. This method + is recommended if you need compatibility with packages already + using this method or if your package needs to be zip-safe. + + Warning: While native namespace packages and pkgutil-style + namespace packages are largely compatible, pkg_resources-style + namespace packages are not compatible with the other methods. It’s + inadvisable to use different methods in different distributions + that provide packages to the same namespace. + +* Menu: + +* Native namespace packages:: +* pkgutil-style namespace packages:: +* pkg_resources-style namespace packages:: + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0420 + + +File: pythonpackagingguide.info, Node: Native namespace packages, Next: pkgutil-style namespace packages, Up: Creating a namespace package + +3.15.1.1 Native namespace packages +.................................. + +Python 3.3 added `implicit' namespace packages from PEP 420(1). All +that is required to create a native namespace package is that you just +omit ‘__init__.py’ from the namespace package directory. An example +file structure: + + setup.py + mynamespace/ + # No __init__.py here. + subpackage_a/ + # Sub-packages have __init__.py. + __init__.py + module.py + +It is extremely important that every distribution that uses the +namespace package omits the ‘__init__.py’ or uses a pkgutil-style +‘__init__.py’. If any distribution does not, it will cause the +namespace logic to fail and the other sub-packages will not be +importable. + +Because ‘mynamespace’ doesn’t contain an ‘__init__.py’, +‘setuptools.find_packages()’ won’t find the sub-package. You must use +‘setuptools.find_namespace_packages()’ instead or explicitly list all +packages in your ‘setup.py’. For example: + + from setuptools import setup, find_namespace_packages + + setup( + name='mynamespace-subpackage-a', + ... + packages=find_namespace_packages(include=['mynamespace.*']) + ) + +A complete working example of two native namespace packages can be found +in the native namespace package example project(2). + + Note: Because native and pkgutil-style namespace packages are + largely compatible, you can use native namespace packages in the + distributions that only support Python 3 and pkgutil-style + namespace packages in the distributions that need to support Python + 2 and 3. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0420 + + (2) +https://github.com/pypa/sample-namespace-packages/tree/master/native + + +File: pythonpackagingguide.info, Node: pkgutil-style namespace packages, Next: pkg_resources-style namespace packages, Prev: Native namespace packages, Up: Creating a namespace package + +3.15.1.2 pkgutil-style namespace packages +......................................... + +Python 2.3 introduced the pkgutil(1) module and the +pkgutil.extend_path()(2) function. This can be used to declare +namespace packages that need to be compatible with both Python 2.3+ and +Python 3. This is the recommended approach for the highest level of +compatibility. + +To create a pkgutil-style namespace package, you need to provide an +‘__init__.py’ file for the namespace package: + + setup.py + mynamespace/ + __init__.py # Namespace package __init__.py + subpackage_a/ + __init__.py # Sub-package __init__.py + module.py + +The ‘__init__.py’ file for the namespace package needs to contain `only' +the following: + + __path__ = __import__('pkgutil').extend_path(__path__, __name__) + +`Every' distribution that uses the namespace package must include an +identical ‘__init__.py’. If any distribution does not, it will cause +the namespace logic to fail and the other sub-packages will not be +importable. Any additional code in ‘__init__.py’ will be inaccessible. + +A complete working example of two pkgutil-style namespace packages can +be found in the pkgutil namespace example project(3). + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/library/pkgutil.html + + (2) +https://docs.python.org/3/library/pkgutil.html#pkgutil.extend_path + + (3) +https://github.com/pypa/sample-namespace-packages/tree/master/pkgutil + + +File: pythonpackagingguide.info, Node: pkg_resources-style namespace packages, Prev: pkgutil-style namespace packages, Up: Creating a namespace package + +3.15.1.3 pkg_resources-style namespace packages +............................................... + +Setuptools(1) provides the pkg_resources.declare_namespace(2) function +and the ‘namespace_packages’ argument to ‘setup()’. Together these can +be used to declare namespace packages. While this approach is no longer +recommended, it is widely present in most existing namespace packages. +If you are creating a new distribution within an existing namespace +package that uses this method then it’s recommended to continue using +this as the different methods are not cross-compatible and it’s not +advisable to try to migrate an existing package. + +To create a pkg_resources-style namespace package, you need to provide +an ‘__init__.py’ file for the namespace package: + + setup.py + mynamespace/ + __init__.py # Namespace package __init__.py + subpackage_a/ + __init__.py # Sub-package __init__.py + module.py + +The ‘__init__.py’ file for the namespace package needs to contain `only' +the following: + + __import__('pkg_resources').declare_namespace(__name__) + +`Every' distribution that uses the namespace package must include an +identical ‘__init__.py’. If any distribution does not, it will cause +the namespace logic to fail and the other sub-packages will not be +importable. Any additional code in ‘__init__.py’ will be inaccessible. + + Note: Some older recommendations advise the following in the + namespace package ‘__init__.py’: + + try: + __import__('pkg_resources').declare_namespace(__name__) + except ImportError: + __path__ = __import__('pkgutil').extend_path(__path__, __name__) + + The idea behind this was that in the rare case that setuptools + isn’t available packages would fall-back to the pkgutil-style + packages. This isn’t advisable because pkgutil and + pkg_resources-style namespace packages are not cross-compatible. + If the presence of setuptools is a concern then the package should + just explicitly depend on setuptools via ‘install_requires’. + +Finally, every distribution must provide the ‘namespace_packages’ +argument to ‘setup()’ in ‘setup.py’. For example: + + from setuptools import find_packages, setup + + setup( + name='mynamespace-subpackage-a', + ... + packages=find_packages() + namespace_packages=['mynamespace'] + ) + +A complete working example of two pkg_resources-style namespace packages +can be found in the pkg_resources namespace example project(3). + + ---------- Footnotes ---------- + + (1) https://setuptools.pypa.io/en/latest/index.html + + (2) +https://setuptools.readthedocs.io/en/latest/pkg_resources.html#namespace-package-support + + (3) +https://github.com/pypa/sample-namespace-packages/tree/master/pkg_resources + + +File: pythonpackagingguide.info, Node: Creating and discovering plugins, Next: Migrating to PyPI org, Prev: Packaging namespace packages, Up: Guides + +3.16 Creating and discovering plugins +===================================== + +Often when creating a Python application or library you’ll want the +ability to provide customizations or extra features via `plugins'. +Because Python packages can be separately distributed, your application +or library may want to automatically `discover' all of the plugins +available. + +There are three major approaches to doing automatic plugin discovery: + + 1. *note Using naming convention: 13b. + + 2. *note Using namespace packages: 13c. + + 3. *note Using package metadata: 13d. + +* Menu: + +* Using naming convention:: +* Using namespace packages:: +* Using package metadata:: + + +File: pythonpackagingguide.info, Node: Using naming convention, Next: Using namespace packages, Up: Creating and discovering plugins + +3.16.1 Using naming convention +------------------------------ + +If all of the plugins for your application follow the same naming +convention, you can use pkgutil.iter_modules()(1) to discover all of the +top-level modules that match the naming convention. For example, +Flask(2) uses the naming convention ‘flask_{plugin_name}’. If you +wanted to automatically discover all of the Flask plugins installed: + + import importlib + import pkgutil + + discovered_plugins = { + name: importlib.import_module(name) + for finder, name, ispkg + in pkgutil.iter_modules() + if name.startswith('flask_') + } + +If you had both the Flask-SQLAlchemy(3) and Flask-Talisman(4) plugins +installed then ‘discovered_plugins’ would be: + + { + 'flask_sqlachemy': , + 'flask_talisman': , + } + +Using naming convention for plugins also allows you to query the Python +Package Index’s simple API(5) for all packages that conform to your +naming convention. + + ---------- Footnotes ---------- + + (1) +https://docs.python.org/2/library/pkgutil.html#pkgutil.iter_modules + + (2) https://pypi.org/project/Flask/ + + (3) https://pypi.org/project/Flask-SQLAlchemy/ + + (4) https://pypi.org/project/flask-talisman + + (5) https://www.python.org/dev/peps/pep-0503/#specification + + +File: pythonpackagingguide.info, Node: Using namespace packages, Next: Using package metadata, Prev: Using naming convention, Up: Creating and discovering plugins + +3.16.2 Using namespace packages +------------------------------- + +*note Namespace packages: 130. can be used to provide a convention for +where to place plugins and also provides a way to perform discovery. +For example, if you make the sub-package ‘myapp.plugins’ a namespace +package then other *note distributions: b. can provide modules and +packages to that namespace. Once installed, you can use +pkgutil.iter_modules()(1) to discover all modules and packages installed +under that namespace: + + import importlib + import pkgutil + + import myapp.plugins + + def iter_namespace(ns_pkg): + # Specifying the second argument (prefix) to iter_modules makes the + # returned name an absolute name instead of a relative one. This allows + # import_module to work without having to do additional modification to + # the name. + return pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + ".") + + discovered_plugins = { + name: importlib.import_module(name) + for finder, name, ispkg + in iter_namespace(myapp.plugins) + } + +Specifying ‘myapp.plugins.__path__’ to iter_modules()(2) causes it to +only look for the modules directly under that namespace. For example, +if you have installed distributions that provide the modules +‘myapp.plugins.a’ and ‘myapp.plugins.b’ then ‘discovered_plugins’ in +this case would be: + + { + 'a': , + 'b': , + } + +This sample uses a sub-package as the namespace package +(‘myapp.plugins’), but it’s also possible to use a top-level package for +this purpose (such as ‘myapp_plugins’). How to pick the namespace to +use is a matter of preference, but it’s not recommended to make your +project’s main top-level package (‘myapp’ in this case) a namespace +package for the purpose of plugins, as one bad plugin could cause the +entire namespace to break which would in turn make your project +unimportable. For the “namespace sub-package” approach to work, the +plugin packages must omit the ‘__init__.py’ for your top-level package +directory (‘myapp’ in this case) and include the namespace-package style +‘__init__.py’ in the namespace sub-package directory (‘myapp/plugins’). +This also means that plugins will need to explicitly pass a list of +packages to ‘setup()’’s ‘packages’ argument instead of using +‘setuptools.find_packages()’. + + Warning: Namespace packages are a complex feature and there are + several different ways to create them. It’s highly recommended to + read the *note Packaging namespace packages: 130. documentation and + clearly document which approach is preferred for plugins to your + project. + + ---------- Footnotes ---------- + + (1) +https://docs.python.org/2/library/pkgutil.html#pkgutil.iter_modules + + (2) +https://docs.python.org/2/library/pkgutil.html#pkgutil.iter_modules + + +File: pythonpackagingguide.info, Node: Using package metadata, Prev: Using namespace packages, Up: Creating and discovering plugins + +3.16.3 Using package metadata +----------------------------- + +Setuptools(1) provides special support(2) for plugins. By providing the +‘entry_points’ argument to ‘setup()’ in ‘setup.py’ plugins can register +themselves for discovery. + +For example if you have a package named ‘myapp-plugin-a’ and it includes +in its ‘setup.py’: + + setup( + ... + entry_points={'myapp.plugins': 'a = myapp_plugin_a'}, + ... + ) + +Then you can discover and load all of the registered entry points by +using ‘importlib.metadata.entry_points()’ (or the backport(3) +‘importlib_metadata >= 3.6’ for Python 3.6-3.9): + + import sys + if sys.version_info < (3, 10): + from importlib_metadata import entry_points + else: + from importlib.metadata import entry_points + + discovered_plugins = entry_points(group='myapp.plugins') + +In this example, ‘discovered_plugins’ would be a collection of type +‘importlib.metadata.EntryPoint’: + + ( + EntryPoint(name='a', value='myapp_plugin_a', group='myapp.plugins'), + ... + ) + +Now the module of your choice can be imported by executing +‘discovered_plugins['a'].load()’. + + Note: The ‘entry_point’ specification in ‘setup.py’ is fairly + flexible and has a lot of options. It’s recommended to read over + the entire section on entry points(4) . + + Note: Since this specification is part of the standard library(5), + most packaging tools other than setuptools provide support for + defining entry points. + + ---------- Footnotes ---------- + + (1) https://setuptools.pypa.io/en/latest/index.html + + (2) https://setuptools.pypa.io/en/latest/userguide/entry_point.html + + (3) https://importlib-metadata.readthedocs.io/en/latest/ + + (4) https://setuptools.pypa.io/en/latest/userguide/entry_point.html + + (5) https://docs.python.org/3/library/importlib.metadata.html + + +File: pythonpackagingguide.info, Node: Migrating to PyPI org, Next: Using TestPyPI<2>, Prev: Creating and discovering plugins, Up: Guides + +3.17 Migrating to PyPI.org +========================== + +*note pypi.org: 143. is the new, rewritten version of PyPI that has +replaced the legacy PyPI code base. It is the default version of PyPI +that people are expected to use. These are the tools and processes that +people will need to interact with ‘PyPI.org’. + +* Menu: + +* Publishing releases:: +* Registering package names & metadata:: +* Using TestPyPI:: +* Registering new user accounts:: +* Browsing packages:: +* Downloading packages:: +* Managing published packages and releases:: + + +File: pythonpackagingguide.info, Node: Publishing releases, Next: Registering package names & metadata, Up: Migrating to PyPI org + +3.17.1 Publishing releases +-------------------------- + +‘pypi.org’ is the default upload platform as of September 2016. + +Uploads through ‘pypi.python.org’ were `switched off' on `July 3, 2017'. +As of April 13th, 2018, ‘pypi.org’ is the URL for PyPI. + +The recommended way to migrate to PyPI.org for uploading is to ensure +that you are using a new enough version of your upload tool. + +The default upload settings switched to ‘pypi.org’ in the following +versions: + + * ‘twine’ 1.8.0 + + * ‘setuptools’ 27.0.0 + + * Python 2.7.13 (‘distutils’ update) + + * Python 3.4.6 (‘distutils’ update) + + * Python 3.5.3 (‘distutils’ update) + + * Python 3.6.0 (‘distutils’ update) + +In addition to ensuring you’re on a new enough version of the tool for +the tool’s default to have switched, you must also make sure that you +have not configured the tool to override its default upload URL. +Typically this is configured in a file located at ‘$HOME/.pypirc’. If +you see a file like: + + [distutils] + index-servers = + pypi + + [pypi] + repository = https://pypi.python.org/pypi + username = + password = + +Then simply delete the line starting with ‘repository’ and you will use +your upload tool’s default URL. + +If for some reason you’re unable to upgrade the version of your tool to +a version that defaults to using PyPI.org, then you may edit +‘$HOME/.pypirc’ and include the ‘repository:’ line, but use the value +‘https://upload.pypi.org/legacy/’ instead: + + [distutils] + index-servers = + pypi + + [pypi] + repository = https://upload.pypi.org/legacy/ + username = + password = + +(‘legacy’ in this URL refers to the fact that this is the new server +implementation’s emulation of the legacy server implementation’s upload +API.) + +For more details, see the *note specification: f3. for ‘.pypirc’. + + +File: pythonpackagingguide.info, Node: Registering package names & metadata, Next: Using TestPyPI, Prev: Publishing releases, Up: Migrating to PyPI org + +3.17.2 Registering package names & metadata +------------------------------------------- + +Explicit pre-registration of package names with the ‘setup.py register’ +command prior to the first upload is no longer required, and is not +currently supported by the legacy upload API emulation on PyPI.org. + +As a result, attempting explicit registration after switching to using +PyPI.org for uploads will give the following error message: + + Server response (410): This API is no longer supported, instead simply upload the file. + +The solution is to skip the registration step, and proceed directly to +uploading artifacts. + + +File: pythonpackagingguide.info, Node: Using TestPyPI, Next: Registering new user accounts, Prev: Registering package names & metadata, Up: Migrating to PyPI org + +3.17.3 Using TestPyPI +--------------------- + +Legacy TestPyPI (testpypi.python.org) is no longer available; use +test.pypi.org(1) instead. If you use TestPyPI, you must update your +‘$HOME/.pypirc’ to handle TestPyPI’s new location, by replacing +‘https://testpypi.python.org/pypi’ with ‘https://test.pypi.org/legacy/’, +for example: + + [distutils] + index-servers= + pypi + testpypi + + [testpypi] + repository = https://test.pypi.org/legacy/ + username = + password = + +For more details, see the *note specification: f3. for ‘.pypirc’. + + ---------- Footnotes ---------- + + (1) https://test.pypi.org + + +File: pythonpackagingguide.info, Node: Registering new user accounts, Next: Browsing packages, Prev: Using TestPyPI, Up: Migrating to PyPI org + +3.17.4 Registering new user accounts +------------------------------------ + +In order to help mitigate spam attacks against PyPI, new user +registration through ‘pypi.python.org’ was `switched off' on `February +20, 2018'. New user registrations at ‘pypi.org’ are open. + + +File: pythonpackagingguide.info, Node: Browsing packages, Next: Downloading packages, Prev: Registering new user accounts, Up: Migrating to PyPI org + +3.17.5 Browsing packages +------------------------ + +While ‘pypi.python.org’ is may still be used in links from other PyPA +documentation, etc, the default interface for browsing packages is +‘pypi.org’. The domain pypi.python.org now redirects to pypi.org, and +may be disabled sometime in the future. + + +File: pythonpackagingguide.info, Node: Downloading packages, Next: Managing published packages and releases, Prev: Browsing packages, Up: Migrating to PyPI org + +3.17.6 Downloading packages +--------------------------- + +‘pypi.org’ is the default host for downloading packages. + + +File: pythonpackagingguide.info, Node: Managing published packages and releases, Prev: Downloading packages, Up: Migrating to PyPI org + +3.17.7 Managing published packages and releases +----------------------------------------------- + +‘pypi.org’ provides a fully functional interface for logged in users to +manage their published packages and releases. + + +File: pythonpackagingguide.info, Node: Using TestPyPI<2>, Next: Making a PyPI-friendly README, Prev: Migrating to PyPI org, Up: Guides + +3.18 Using TestPyPI +=================== + +‘TestPyPI’ is a separate instance of the *note Python Package Index +(PyPI): 39. that allows you to try out the distribution tools and +process without worrying about affecting the real index. TestPyPI is +hosted at test.pypi.org(1) + +* Menu: + +* Registering your account:: +* Using TestPyPI with Twine:: +* Using TestPyPI with pip:: +* Setting up TestPyPI in .pypirc: Setting up TestPyPI in pypirc. + + ---------- Footnotes ---------- + + (1) https://test.pypi.org + + +File: pythonpackagingguide.info, Node: Registering your account, Next: Using TestPyPI with Twine, Up: Using TestPyPI<2> + +3.18.1 Registering your account +------------------------------- + +Because TestPyPI has a separate database from the live PyPI, you’ll need +a separate user account specifically for TestPyPI. Go to +‘https://test.pypi.org/account/register/’ to register your account. + + Note: The database for TestPyPI may be periodically pruned, so it + is not unusual for user accounts to be deleted. + + +File: pythonpackagingguide.info, Node: Using TestPyPI with Twine, Next: Using TestPyPI with pip, Prev: Registering your account, Up: Using TestPyPI<2> + +3.18.2 Using TestPyPI with Twine +-------------------------------- + +You can upload your distributions to TestPyPI using *note twine: 6d. by +specifying the ‘--repository’ flag: + + twine upload --repository testpypi dist/* + +You can see if your package has successfully uploaded by navigating to +the URL ‘https://test.pypi.org/project/’ where +‘sampleproject’ is the name of your project that you uploaded. It may +take a minute or two for your project to appear on the site. + + +File: pythonpackagingguide.info, Node: Using TestPyPI with pip, Next: Setting up TestPyPI in pypirc, Prev: Using TestPyPI with Twine, Up: Using TestPyPI<2> + +3.18.3 Using TestPyPI with pip +------------------------------ + +You can tell *note pip: 2b. to download packages from TestPyPI instead +of PyPI by specifying the ‘--index-url’ flag: (Unix/macOS) + python3 -m pip install --index-url https://test.pypi.org/simple/ your-package +(Windows) + py -m pip install --index-url https://test.pypi.org/simple/ your-package + +If you want to allow pip to also download packages from PyPI, you can +specify ‘--extra-index-url’ to point to PyPI. This is useful when the +package you’re testing has dependencies: (Unix/macOS) + python3 -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ your-package +(Windows) + py -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ your-package + + +File: pythonpackagingguide.info, Node: Setting up TestPyPI in pypirc, Prev: Using TestPyPI with pip, Up: Using TestPyPI<2> + +3.18.4 Setting up TestPyPI in ‘.pypirc’ +--------------------------------------- + +If you want to avoid entering your username, you can configure TestPyPI +in your ‘$HOME/.pypirc’: + + [testpypi] + username = + +For more details, see the *note specification: f3. for ‘.pypirc’. + + +File: pythonpackagingguide.info, Node: Making a PyPI-friendly README, Next: Publishing package distribution releases using GitHub Actions CI/CD workflows, Prev: Using TestPyPI<2>, Up: Guides + +3.19 Making a PyPI-friendly README +================================== + +README files can help your users understand your project and can be used +to set your project’s description on PyPI. This guide helps you create a +README in a PyPI-friendly format and include your README in your package +so it appears on PyPI. + +* Menu: + +* Creating a README file:: +* Including your README in your package’s metadata:: +* Validating reStructuredText markup:: + + +File: pythonpackagingguide.info, Node: Creating a README file, Next: Including your README in your package’s metadata, Up: Making a PyPI-friendly README + +3.19.1 Creating a README file +----------------------------- + +README files for Python projects are often named ‘README’, ‘README.txt’, +‘README.rst’, or ‘README.md’. + +For your README to display properly on PyPI, choose a markup language +supported by PyPI. Formats supported by PyPI’s README renderer(1) are: + + * plain text + + * reStructuredText(2) (without Sphinx extensions) + + * Markdown (GitHub Flavored Markdown(3) by default, or CommonMark(4)) + +It’s customary to save your README file in the root of your project, in +the same directory as your ‘setup.py’ file. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/readme_renderer + + (2) https://docutils.sourceforge.io/rst.html + + (3) https://github.github.com/gfm/ + + (4) https://commonmark.org/ + + +File: pythonpackagingguide.info, Node: Including your README in your package’s metadata, Next: Validating reStructuredText markup, Prev: Creating a README file, Up: Making a PyPI-friendly README + +3.19.2 Including your README in your package’s metadata +------------------------------------------------------- + +To include your README’s contents as your package description, set your +project’s ‘Description’ and ‘Description-Content-Type’ metadata, +typically in your project’s ‘setup.py’ file. + +See also +........ + + * *note Description: 154. + + * *note Description-Content-Type: 155. + +For example, to set these values in a package’s ‘setup.py’ file, use +‘setup()’’s ‘long_description’ and ‘long_description_content_type’. + +Set the value of ‘long_description’ to the contents (not the path) of +the README file itself. Set the ‘long_description_content_type’ to an +accepted ‘Content-Type’-style value for your README file’s markup, such +as ‘text/plain’, ‘text/x-rst’ (for reStructuredText), or +‘text/markdown’. + + Note: If you’re using GitHub-flavored Markdown to write a project’s + description, ensure you upgrade the following tools: (Unix/macOS) + python3 -m pip install --user --upgrade setuptools wheel twine + (Windows) + py -m pip install --user --upgrade setuptools wheel twine + + The minimum required versions of the respective tools are: + + - ‘setuptools >= 38.6.0’ + + - ‘wheel >= 0.31.0’ + + - ‘twine >= 1.11.0’ + + It’s recommended that you use ‘twine’ to upload the project’s + distribution packages: + + twine upload dist/* + +For example, see this ‘setup.py’ file, which reads the contents of +‘README.md’ as ‘long_description’ and identifies the markup as +GitHub-flavored Markdown: + + from setuptools import setup + + # read the contents of your README file + from pathlib import Path + this_directory = Path(__file__).parent + long_description = (this_directory / "README.md").read_text() + + setup( + name='an_example_package', + # other arguments omitted + long_description=long_description, + long_description_content_type='text/markdown' + ) + + +File: pythonpackagingguide.info, Node: Validating reStructuredText markup, Prev: Including your README in your package’s metadata, Up: Making a PyPI-friendly README + +3.19.3 Validating reStructuredText markup +----------------------------------------- + +If your README is written in reStructuredText, any invalid markup will +prevent it from rendering, causing PyPI to instead just show the +README’s raw source. + +Note that Sphinx extensions used in docstrings, such as directives and +roles(1) (e.g., “‘:py:func:`getattr`’” or +“‘:ref:`my-reference-label`’”), are not allowed here and will result in +error messages like “‘Error: Unknown interpreted text role "py:func".’”. + +You can check your README for markup errors before uploading as follows: + + 1. Install the latest version of twine(2); version 1.12.0 or higher is + required: (Unix/macOS) + python3 -m pip install --upgrade twine + (Windows) + py -m pip install --upgrade twine + + 2. Build the sdist and wheel for your project as described under *note + Packaging your project: d5. + + 3. Run ‘twine check’ on the sdist and wheel: + + twine check dist/* + + This command will report any problems rendering your README. If + your markup renders fine, the command will output ‘Checking + distribution FILENAME: Passed’. + + ---------- Footnotes ---------- + + (1) +https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html + + (2) https://github.com/pypa/twine + + +File: pythonpackagingguide.info, Node: Publishing package distribution releases using GitHub Actions CI/CD workflows, Next: Tool recommendations, Prev: Making a PyPI-friendly README, Up: Guides + +3.20 Publishing package distribution releases using GitHub Actions CI/CD workflows +================================================================================== + +GitHub Actions CI/CD(1) allows you to run a series of commands whenever +an event occurs on the GitHub platform. One popular choice is having a +workflow that’s triggered by a ‘push’ event. This guide shows you how +to publish a Python distribution whenever a tagged commit is pushed. It +will use the pypa/gh-action-pypi-publish GitHub Action(2). + + Attention: This guide `assumes' that you already have a project + that you know how to build distributions for and `it lives on + GitHub'. + +* Menu: + +* Saving credentials on GitHub:: +* Creating a workflow definition:: +* Defining a workflow job environment:: +* Checking out the project and building distributions:: +* Publishing the distribution to PyPI and TestPyPI:: +* That’s all, folks!: That’s all folks!. + + ---------- Footnotes ---------- + + (1) https://github.com/features/actions + + (2) https://github.com/marketplace/actions/pypi-publish + + +File: pythonpackagingguide.info, Node: Saving credentials on GitHub, Next: Creating a workflow definition, Up: Publishing package distribution releases using GitHub Actions CI/CD workflows + +3.20.1 Saving credentials on GitHub +----------------------------------- + +In this guide, we’ll demonstrate uploading to both PyPI and TestPyPI, +meaning that we’ll have two separate sets of credentials. And we’ll +need to save them in the GitHub repository settings. + +Let’s begin! 🚀 + + 1. Go to ‘https://pypi.org/manage/account/#api-tokens’ and create a + new API token(1). If you have the project on PyPI already, limit + the token scope to just that project. You can call it something + like ‘GitHub Actions CI/CD — project-org/project-repo’ in order for + it to be easily distinguishable in the token list. `Don’t close + the page just yet — you won’t see that token again.' + + 2. In a separate browser tab or window, go to the ‘Settings’ tab of + your target repository and then click on Secrets(2) in the left + sidebar. + + 3. Create a new secret called ‘PYPI_API_TOKEN’ and copy-paste the + token from the first step. + + 4. Now, go to ‘https://test.pypi.org/manage/account/#api-tokens’ and + repeat the steps. Save that TestPyPI token on GitHub as + ‘TEST_PYPI_API_TOKEN’. + + Attention: If you don’t have a TestPyPI account, you’ll need + to create it. It’s not the same as a regular PyPI account. + + ---------- Footnotes ---------- + + (1) https://pypi.org/help/#apitoken + + (2) https://docs.github.com/en/actions/reference/encrypted-secrets + + +File: pythonpackagingguide.info, Node: Creating a workflow definition, Next: Defining a workflow job environment, Prev: Saving credentials on GitHub, Up: Publishing package distribution releases using GitHub Actions CI/CD workflows + +3.20.2 Creating a workflow definition +------------------------------------- + +GitHub CI/CD workflows are declared in YAML files stored in the +‘.github/workflows/’ directory of your repository. + +Let’s create a ‘.github/workflows/publish-to-test-pypi.yml’ file. + +Start it with a meaningful name and define the event that should make +GitHub run this workflow: + + name: Publish Python 🐍 distributions 📦 to PyPI and TestPyPI + + on: push + + + +File: pythonpackagingguide.info, Node: Defining a workflow job environment, Next: Checking out the project and building distributions, Prev: Creating a workflow definition, Up: Publishing package distribution releases using GitHub Actions CI/CD workflows + +3.20.3 Defining a workflow job environment +------------------------------------------ + +Now, let’s add initial setup for our job. It’s a process that will +execute commands that we’ll define later. In this guide, we’ll use +Ubuntu 18.04: + + + jobs: + build-n-publish: + name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI + runs-on: ubuntu-18.04 + + + +File: pythonpackagingguide.info, Node: Checking out the project and building distributions, Next: Publishing the distribution to PyPI and TestPyPI, Prev: Defining a workflow job environment, Up: Publishing package distribution releases using GitHub Actions CI/CD workflows + +3.20.4 Checking out the project and building distributions +---------------------------------------------------------- + +Then, add the following under the ‘build-n-publish’ section: + + + steps: + - uses: actions/checkout@master + - name: Set up Python 3.9 + uses: actions/setup-python@v1 + with: + python-version: 3.9 + +This will download your repository into the CI runner and then install +and activate Python 3.9. + +And now we can build dists from source. In this example, we’ll use +‘build’ package, assuming that your project has a ‘pyproject.toml’ +properly set up (see PEP 517(1)/ PEP 518(2)). + + Tip: You can use any other method for building distributions as + long as it produces ready-to-upload artifacts saved into the + ‘dist/’ folder. + +So add this to the steps list: + + - name: Install pypa/build + run: >- + python -m + pip install + build + --user + - name: Build a binary wheel and a source tarball + run: >- + python -m + build + --sdist + --wheel + --outdir dist/ + . + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0517 + + (2) https://www.python.org/dev/peps/pep-0518 + + +File: pythonpackagingguide.info, Node: Publishing the distribution to PyPI and TestPyPI, Next: That’s all folks!, Prev: Checking out the project and building distributions, Up: Publishing package distribution releases using GitHub Actions CI/CD workflows + +3.20.5 Publishing the distribution to PyPI and TestPyPI +------------------------------------------------------- + +Finally, add the following steps at the end: + + - name: Publish distribution 📦 to Test PyPI + uses: pypa/gh-action-pypi-publish@master + with: + password: ${{ secrets.TEST_PYPI_API_TOKEN }} + repository_url: https://test.pypi.org/legacy/ + - name: Publish distribution 📦 to PyPI + if: startsWith(github.ref, 'refs/tags') + uses: pypa/gh-action-pypi-publish@master + with: + password: ${{ secrets.PYPI_API_TOKEN }} + +These two steps use the pypa/gh-action-pypi-publish(1) GitHub Action: +the first one uploads contents of the ‘dist/’ folder into TestPyPI +unconditionally and the second does that to PyPI, but only if the +current commit is tagged. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/gh-action-pypi-publish + + +File: pythonpackagingguide.info, Node: That’s all folks!, Prev: Publishing the distribution to PyPI and TestPyPI, Up: Publishing package distribution releases using GitHub Actions CI/CD workflows + +3.20.6 That’s all, folks! +------------------------- + +Now, whenever you push a tagged commit to your Git repository remote on +GitHub, this workflow will publish it to PyPI. And it’ll publish any +push to TestPyPI which is useful for providing test builds to your alpha +users as well as making sure that your release pipeline remains healthy! + + +File: pythonpackagingguide.info, Node: Tool recommendations, Next: Analyzing PyPI package downloads, Prev: Publishing package distribution releases using GitHub Actions CI/CD workflows, Up: Guides + +3.21 Tool recommendations +========================= + +If you’re familiar with Python packaging and installation, and just want +to know what tools are currently recommended, then here it is. + +* Menu: + +* Application dependency management:: +* Installation tool recommendations:: +* Packaging tool recommendations:: +* Publishing platform migration:: + + +File: pythonpackagingguide.info, Node: Application dependency management, Next: Installation tool recommendations, Up: Tool recommendations + +3.21.1 Application dependency management +---------------------------------------- + + * Use *note pip: 2b. in a secure manner(1) to install a Python + application and its dependencies during deployment. + + * Use *note virtualenv: 32. or venv(2) to isolate + application-specific dependencies from a shared Python + installation. (3) + + * Use pip-tools(4), *note Pipenv: 36, or poetry(5) to generate the + fully-specified application-specific dependencies, when developing + Python applications. + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/topics/secure-installs/ + + (2) https://docs.python.org/3/library/venv.html + + (3) (4) Beginning with Python 3.4, ‘venv’ will create virtualenv +environments with ‘pip’ installed, thereby making it an equal +alternative to *note virtualenv: 32. However, using *note virtualenv: +32. will still be recommended for users that need cross-version +consistency. + + (4) https://github.com/jazzband/pip-tools + + (5) https://python-poetry.org/ + + +File: pythonpackagingguide.info, Node: Installation tool recommendations, Next: Packaging tool recommendations, Prev: Application dependency management, Up: Tool recommendations + +3.21.2 Installation tool recommendations +---------------------------------------- + + * Use *note pip: 2b. to install Python *note packages: b. from *note + PyPI: 39. (1) (2) Depending on how *note pip: 2b. is installed, + you may need to also install *note wheel: 2e. to get the benefit of + wheel caching. (3) + + * Use *note virtualenv: 32. or venv(4) to isolate project-specific + dependencies from a shared Python installation. (5) + + * If you’re looking for management of fully integrated cross-platform + software stacks, consider: + + * *note buildout: 169.: primarily focused on the web development + community + + * *note Spack: 16a, *note Hashdist: 16b, or *note conda: 16c.: + primarily focused on the scientific community. + + ---------- Footnotes ---------- + + (1) (1) There are some cases where you might choose to use +‘easy_install’ (from *note setuptools: 2d.), e.g. if you need to +install from *note Eggs: 166. (which pip doesn’t support). For a +detailed breakdown, see *note pip vs easy_install: 167. + + (2) (2) The acceptance of PEP 453 +(https://www.python.org/dev/peps/pep-0453) means that *note pip: 2b. +will be available by default in most installations of Python 3.4 or +later. See the rationale section +(https://www.python.org/dev/peps/pep-0453#rationale) from PEP 453 +(https://www.python.org/dev/peps/pep-0453) as for why pip was chosen. + + (3) (3) get-pip.py (https://github.com/pypa/get-pip/#readme) and +*note virtualenv: 32. install *note wheel: 2e, whereas *note ensurepip: +168. and *note venv: 7e. do not currently. Also, the common +“python-pip” package that’s found in various linux distros, does not +depend on “python-wheel” currently. + + (4) https://docs.python.org/3/library/venv.html + + (5) (4) Beginning with Python 3.4, ‘venv’ will create virtualenv +environments with ‘pip’ installed, thereby making it an equal +alternative to *note virtualenv: 32. However, using *note virtualenv: +32. will still be recommended for users that need cross-version +consistency. + + +File: pythonpackagingguide.info, Node: Packaging tool recommendations, Next: Publishing platform migration, Prev: Installation tool recommendations, Up: Tool recommendations + +3.21.3 Packaging tool recommendations +------------------------------------- + + * Use *note setuptools: 2d. to define projects. (1) (2) + + * Use *note build: 5f. to create *note Source Distributions: 3d. and + *note wheels: d. + +If you have binary extensions and want to distribute wheels for multiple +platforms, use *note cibuildwheel: 11a. as part of your CI setup to +build distributable wheels. + + * Use twine(3) for uploading distributions to *note PyPI: 39. + + ---------- Footnotes ---------- + + (1) (5) Although you can use pure ‘distutils’ for many projects, it +does not support defining dependencies on other projects and is missing +several convenience utilities for automatically populating distribution +metadata correctly that are provided by ‘setuptools’. Being outside the +standard library, ‘setuptools’ also offers a more consistent feature set +across different versions of Python, and (unlike ‘distutils’), recent +versions of ‘setuptools’ support all of the modern metadata fields +described in *note Core metadata specifications: 106. + +Even for projects that do choose to use ‘distutils’, when *note pip: 2b. +installs such projects directly from source (rather than installing from +a prebuilt *note wheel: d. file), it will actually build your project +using *note setuptools: 2d. instead. + + (2) (6) distribute (https://pypi.org/project/distribute) (a fork of +setuptools) was merged back into *note setuptools: 2d. in June 2013, +thereby making setuptools the default choice for packaging. + + (3) https://pypi.org/project/twine + + +File: pythonpackagingguide.info, Node: Publishing platform migration, Prev: Packaging tool recommendations, Up: Tool recommendations + +3.21.4 Publishing platform migration +------------------------------------ + +The original Python Package Index implementation (previously hosted at +pypi.python.org(1)) has been phased out in favour of an updated +implementation hosted at pypi.org(2). + +See *note Migrating to PyPI.org: 142. for more information on the status +of the migration, and what settings to change in your clients. + +__________________________________________________________________ + + ---------- Footnotes ---------- + + (1) https://pypi.python.org + + (2) https://pypi.org + + +File: pythonpackagingguide.info, Node: Analyzing PyPI package downloads, Prev: Tool recommendations, Up: Guides + +3.22 Analyzing PyPI package downloads +===================================== + +This section covers how to use the public PyPI download statistics +dataset to learn more about downloads of a package (or packages) hosted +on PyPI. For example, you can use it to discover the distribution of +Python versions used to download a package. + +* Menu: + +* Background: Background<2>. +* Public dataset:: +* Caveats:: +* Additional tools:: +* References:: + + +File: pythonpackagingguide.info, Node: Background<2>, Next: Public dataset, Up: Analyzing PyPI package downloads + +3.22.1 Background +----------------- + +PyPI does not display download statistics for a number of reasons: (1) + + - `Inefficient to make work with a Content Distribution Network + (CDN):' Download statistics change constantly. Including them in + project pages, which are heavily cached, would require invalidating + the cache more often, and reduce the overall effectiveness of the + cache. + + - `Highly inaccurate:' A number of things prevent the download counts + from being accurate, some of which include: + + - ‘pip’’s download cache (lowers download counts) + + - Internal or unofficial mirrors (can both raise or lower + download counts) + + - Packages not hosted on PyPI (for comparisons sake) + + - Unofficial scripts or attempts at download count inflation + (raises download counts) + + - Known historical data quality issues (lowers download counts) + + - `Not particularly useful:' Just because a project has been + downloaded a lot doesn’t mean it’s good; Similarly just because a + project hasn’t been downloaded a lot doesn’t mean it’s bad! + +In short, because it’s value is low for various reasons, and the +tradeoffs required to make it work are high, it has been not an +effective use of limited resources. + + ---------- Footnotes ---------- + + (1) (1) PyPI Download Counts deprecation email +(https://mail.python.org/pipermail/distutils-sig/2013-May/020855.html) + + +File: pythonpackagingguide.info, Node: Public dataset, Next: Caveats, Prev: Background<2>, Up: Analyzing PyPI package downloads + +3.22.2 Public dataset +--------------------- + +As an alternative, the Linehaul project(1) streams download logs from +PyPI to Google BigQuery(2) (3), where they are stored as a public +dataset. + +* Menu: + +* Getting set up:: +* Data schema:: +* Useful queries:: + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/linehaul + + (2) https://cloud.google.com/bigquery + + (3) (2) PyPI BigQuery dataset announcement email +(https://mail.python.org/pipermail/distutils-sig/2016-May/028986.html) + + +File: pythonpackagingguide.info, Node: Getting set up, Next: Data schema, Up: Public dataset + +3.22.2.1 Getting set up +....................... + +In order to use Google BigQuery(1) to query the public PyPI download +statistics dataset(2), you’ll need a Google account and to enable the +BigQuery API on a Google Cloud Platform project. You can run the up to +1TB of queries per month using the BigQuery free tier without a credit +card(3) + + - Navigate to the BigQuery web UI(4). + + - Create a new project. + + - Enable the BigQuery API(5). + +For more detailed instructions on how to get started with BigQuery, +check out the BigQuery quickstart guide(6). + + ---------- Footnotes ---------- + + (1) https://cloud.google.com/bigquery + + (2) +https://console.cloud.google.com/bigquery?p=bigquery-public-data&d=pypi&page=dataset + + (3) +https://cloud.google.com/blog/products/data-analytics/query-without-a-credit-card-introducing-bigquery-sandbox + + (4) https://console.cloud.google.com/bigquery + + (5) +https://console.developers.google.com/apis/library/bigquery-json.googleapis.com + + (6) +https://cloud.google.com/bigquery/docs/quickstarts/quickstart-web-ui + + +File: pythonpackagingguide.info, Node: Data schema, Next: Useful queries, Prev: Getting set up, Up: Public dataset + +3.22.2.2 Data schema +.................... + +Linehaul writes an entry in a ‘bigquery-public-data.pypi.file_downloads’ +table for each download. The table contains information about what file +was downloaded and how it was downloaded. Some useful columns from the +table schema(1) include: + +Column Description Examples + +------------------------------------------------------------------------------------- + +timestamp Date and time ‘2020-03-09 00:33:03 UTC’ + + +file.project Project name ‘pipenv’, ‘nose’ + + +file.version Package version ‘0.1.6’, ‘1.4.2’ + + +details.installer.name Installer pip, *note bandersnatch: 176. + + +details.python Python version ‘2.7.12’, ‘3.6.4’ + + + ---------- Footnotes ---------- + + (1) +https://console.cloud.google.com/bigquery?pli=1&p=bigquery-public-data&d=pypi&t=file_downloads&page=table + + +File: pythonpackagingguide.info, Node: Useful queries, Prev: Data schema, Up: Public dataset + +3.22.2.3 Useful queries +....................... + +Run queries in the BigQuery web UI(1) by clicking the “Compose query” +button. + +Note that the rows are stored in a partitioned, which helps limit the +cost of queries. These example queries analyze downloads from recent +history by filtering on the ‘timestamp’ column. + +* Menu: + +* Counting package downloads:: +* Package downloads over time:: +* Python versions over time:: + + ---------- Footnotes ---------- + + (1) https://console.cloud.google.com/bigquery + + +File: pythonpackagingguide.info, Node: Counting package downloads, Next: Package downloads over time, Up: Useful queries + +3.22.2.4 Counting package downloads +................................... + +The following query counts the total number of downloads for the project +“pytest”. + + #standardSQL + SELECT COUNT(*) AS num_downloads + FROM `bigquery-public-data.pypi.file_downloads` + WHERE file.project = 'pytest' + -- Only query the last 30 days of history + AND DATE(timestamp) + BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) + AND CURRENT_DATE() + +num_downloads + +-------------------- + +26190085 + +To only count downloads from pip, filter on the ‘details.installer.name’ +column. + + #standardSQL + SELECT COUNT(*) AS num_downloads + FROM `bigquery-public-data.pypi.file_downloads` + WHERE file.project = 'pytest' + AND details.installer.name = 'pip' + -- Only query the last 30 days of history + AND DATE(timestamp) + BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) + AND CURRENT_DATE() + +num_downloads + +-------------------- + +24334215 + + +File: pythonpackagingguide.info, Node: Package downloads over time, Next: Python versions over time, Prev: Counting package downloads, Up: Useful queries + +3.22.2.5 Package downloads over time +.................................... + +To group by monthly downloads, use the ‘TIMESTAMP_TRUNC’ function. Also +filtering by this column reduces corresponding costs. + + #standardSQL + SELECT + COUNT(*) AS num_downloads, + DATE_TRUNC(DATE(timestamp), MONTH) AS `month` + FROM `bigquery-public-data.pypi.file_downloads` + WHERE + file.project = 'pytest' + -- Only query the last 6 months of history + AND DATE(timestamp) + BETWEEN DATE_TRUNC(DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH), MONTH) + AND CURRENT_DATE() + GROUP BY `month` + ORDER BY `month` DESC + +num_downloads month + +------------------------------------- + +1956741 2018-01-01 + + +2344692 2017-12-01 + + +1730398 2017-11-01 + + +2047310 2017-10-01 + + +1744443 2017-09-01 + + +1916952 2017-08-01 + + + +File: pythonpackagingguide.info, Node: Python versions over time, Prev: Package downloads over time, Up: Useful queries + +3.22.2.6 Python versions over time +.................................. + +Extract the Python version from the ‘details.python’ column. Warning: +This query processes over 500 GB of data. + + #standardSQL + SELECT + REGEXP_EXTRACT(details.python, r"[0-9]+\.[0-9]+") AS python_version, + COUNT(*) AS num_downloads, + FROM `bigquery-public-data.pypi.file_downloads` + WHERE + -- Only query the last 6 months of history + DATE(timestamp) + BETWEEN DATE_TRUNC(DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH), MONTH) + AND CURRENT_DATE() + GROUP BY `python_version` + ORDER BY `num_downloads` DESC + +python num_downloads + +--------------------------------- + +3.7 18051328726 + + +3.6 9635067203 + + +3.8 7781904681 + + +2.7 6381252241 + + +null 2026630299 + + +3.5 1894153540 + + + +File: pythonpackagingguide.info, Node: Caveats, Next: Additional tools, Prev: Public dataset, Up: Analyzing PyPI package downloads + +3.22.3 Caveats +-------------- + +In addition to the caveats listed in the background above, Linehaul +suffered from a bug which caused it to significantly under-report +download statistics prior to July 26, 2018. Downloads before this date +are proportionally accurate (e.g. the percentage of Python 2 vs. +Python 3 downloads) but total numbers are lower than actual by an order +of magnitude. + + +File: pythonpackagingguide.info, Node: Additional tools, Next: References, Prev: Caveats, Up: Analyzing PyPI package downloads + +3.22.4 Additional tools +----------------------- + +Besides using the BigQuery console, there are some additional tools +which may be useful when analyzing download statistics. + +* Menu: + +* google-cloud-bigquery:: +* pypinfo:: +* pandas-gbq:: + + +File: pythonpackagingguide.info, Node: google-cloud-bigquery, Next: pypinfo, Up: Additional tools + +3.22.4.1 ‘google-cloud-bigquery’ +................................ + +You can also access the public PyPI download statistics dataset +programmatically via the BigQuery API and the google-cloud-bigquery(1) +project, the official Python client library for BigQuery. + + from google.cloud import bigquery + + # Note: depending on where this code is being run, you may require + # additional authentication. See: + # https://cloud.google.com/bigquery/docs/authentication/ + client = bigquery.Client() + + query_job = client.query(""" + SELECT COUNT(*) AS num_downloads + FROM `bigquery-public-data.pypi.file_downloads` + WHERE file.project = 'pytest' + -- Only query the last 30 days of history + AND DATE(timestamp) + BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) + AND CURRENT_DATE()""") + + results = query_job.result() # Waits for job to complete. + for row in results: + print("{} downloads".format(row.num_downloads)) + + ---------- Footnotes ---------- + + (1) https://cloud.google.com/bigquery/docs/reference/libraries + + +File: pythonpackagingguide.info, Node: pypinfo, Next: pandas-gbq, Prev: google-cloud-bigquery, Up: Additional tools + +3.22.4.2 ‘pypinfo’ +.................. + +pypinfo(1) is a command-line tool which provides access to the dataset +and can generate several useful queries. For example, you can query the +total number of download for a package with the command ‘pypinfo +package_name’. + +Install pypinfo(2) using pip. + + python -m pip install pypinfo + +Usage: + + $ pypinfo requests + Served from cache: False + Data processed: 6.87 GiB + Data billed: 6.87 GiB + Estimated cost: $0.04 + + | download_count | + | -------------- | + | 9,316,415 | + + ---------- Footnotes ---------- + + (1) https://github.com/ofek/pypinfo/blob/master/README.rst + + (2) https://github.com/ofek/pypinfo/blob/master/README.rst + + +File: pythonpackagingguide.info, Node: pandas-gbq, Prev: pypinfo, Up: Additional tools + +3.22.4.3 ‘pandas-gbq’ +..................... + +The pandas-gbq(1) project allows for accessing query results via +Pandas(2). + + ---------- Footnotes ---------- + + (1) https://pandas-gbq.readthedocs.io/en/latest/ + + (2) https://pandas.pydata.org/ + + +File: pythonpackagingguide.info, Node: References, Prev: Additional tools, Up: Analyzing PyPI package downloads + +3.22.5 References +----------------- + + +File: pythonpackagingguide.info, Node: Discussions, Next: PyPA specifications, Prev: Guides, Up: Top + +4 Discussions +************* + +`Discussions' are focused on providing comprehensive information about a +specific topic. If you’re just trying to get stuff done, see *note +Guides: 22. + +* Menu: + +* Deploying Python applications:: +* pip vs easy_install:: +* install_requires vs requirements files:: +* Wheel vs Egg:: + + +File: pythonpackagingguide.info, Node: Deploying Python applications, Next: pip vs easy_install, Up: Discussions + +4.1 Deploying Python applications +================================= + + +Page Status: Incomplete + + +Last Reviewed: 2021-8-24 + +* Menu: + +* Overview:: +* OS packaging & installers:: +* Application bundles:: +* Configuration management:: + + +File: pythonpackagingguide.info, Node: Overview, Next: OS packaging & installers, Up: Deploying Python applications + +4.1.1 Overview +-------------- + +* Menu: + +* Supporting multiple hardware platforms:: + + +File: pythonpackagingguide.info, Node: Supporting multiple hardware platforms, Up: Overview + +4.1.1.1 Supporting multiple hardware platforms +.............................................. + + FIXME + + Meaning: x86, x64, ARM, others? + + For Python-only distributions, it *should* be straightforward to deploy on all + platforms where Python can run. + + For distributions with binary extensions, deployment is major headache. Not only + must the extensions be built on all the combinations of operating system and + hardware platform, but they must also be tested, preferably on continuous + integration platforms. The issues are similar to the "multiple Python + versions" section above, not sure whether this should be a separate section. + Even on Windows x64, both the 32 bit and 64 bit versions of Python enjoy + significant usage. + + +File: pythonpackagingguide.info, Node: OS packaging & installers, Next: Application bundles, Prev: Overview, Up: Deploying Python applications + +4.1.2 OS packaging & installers +------------------------------- + + FIXME + + - Building rpm/debs for projects + - Building rpms/debs for whole virtualenvs + - Building macOS installers for Python projects + - Building Android APKs with Kivy+P4A or P4A & Buildozer + +* Menu: + +* Windows:: + + +File: pythonpackagingguide.info, Node: Windows, Up: OS packaging & installers + +4.1.2.1 Windows +............... + + FIXME + + - Building Windows installers for Python projects + +* Menu: + +* Pynsist:: + + +File: pythonpackagingguide.info, Node: Pynsist, Up: Windows + +4.1.2.2 Pynsist +............... + +Pynsist(1) is a tool that bundles Python programs together with the +Python-interpreter into a single installer based on NSIS. In most cases, +packaging only requires the user to choose a version of the +Python-interpreter and declare the dependencies of the program. The +tool downloads the specified Python-interpreter for Windows and packages +it with all the dependencies in a single Windows-executable installer. + +The installed program can be started from a shortcut that the installer +adds to the start-menu. It uses a Python interpreter installed within +its application directory, independent of any other Python installation +on the computer. + +A big advantage of Pynsist is that the Windows packages can be built on +Linux. There are several examples for different kinds of programs +(console, GUI) in the documentation(2). The tool is released under the +MIT-licence. + + ---------- Footnotes ---------- + + (1) https://pypi.org/project/pynsist + + (2) https://pynsist.readthedocs.io/en/latest/index.html + + +File: pythonpackagingguide.info, Node: Application bundles, Next: Configuration management, Prev: OS packaging & installers, Up: Deploying Python applications + +4.1.3 Application bundles +------------------------- + + FIXME + + - wheels kinda/sorta + +* Menu: + +* Windows: Windows<2>. +* macOS:: +* Unix (including Linux and macOS): Unix including Linux and macOS. + + +File: pythonpackagingguide.info, Node: Windows<2>, Next: macOS, Up: Application bundles + +4.1.3.1 Windows +............... + +* Menu: + +* py2exe:: + + +File: pythonpackagingguide.info, Node: py2exe, Up: Windows<2> + +4.1.3.2 py2exe +.............. + +py2exe(1) is a distutils extension which allows to build standalone +Windows executable programs (32-bit and 64-bit) from Python scripts. +Python versions included in the official development cycle are supported +(refers to Status of Python branches(2)). py2exe can build console +executables and windows (GUI) executables. Building windows services, +and DLL/EXE COM servers might work but it is not actively supported. +The distutils extension is released under the MIT-licence and Mozilla +Public License 2.0. + + ---------- Footnotes ---------- + + (1) https://pypi.org/project/py2exe/ + + (2) https://devguide.python.org/#status-of-python-branches + + +File: pythonpackagingguide.info, Node: macOS, Next: Unix including Linux and macOS, Prev: Windows<2>, Up: Application bundles + +4.1.3.3 macOS +............. + +* Menu: + +* py2app:: + + +File: pythonpackagingguide.info, Node: py2app, Up: macOS + +4.1.3.4 py2app +.............. + +py2app(1) is a Python setuptools command which will allow you to make +standalone macOS application bundles and plugins from Python scripts. +Note that py2app MUST be used on macOS to build applications, it cannot +create Mac applications on other platforms. py2app is released under +the MIT-license. + + ---------- Footnotes ---------- + + (1) https://pypi.org/project/py2app/ + + +File: pythonpackagingguide.info, Node: Unix including Linux and macOS, Prev: macOS, Up: Application bundles + +4.1.3.5 Unix (including Linux and macOS) +........................................ + +* Menu: + +* pex:: + + +File: pythonpackagingguide.info, Node: pex, Up: Unix including Linux and macOS + +4.1.3.6 pex +........... + +pex(1) is a library for generating .pex (Python EXecutable) files which +are executable Python environments in the spirit of virtualenvs. pex is +an expansion upon the ideas outlined in PEP 441(2) and makes the +deployment of Python applications as simple as cp. pex files may even +include multiple platform-specific Python distributions, meaning that a +single pex file can be portable across Linux and macOS. pex is released +under the Apache License 2.0. + + ---------- Footnotes ---------- + + (1) https://pypi.org/project/pex/ + + (2) https://www.python.org/dev/peps/pep-0441 + + +File: pythonpackagingguide.info, Node: Configuration management, Prev: Application bundles, Up: Deploying Python applications + +4.1.4 Configuration management +------------------------------ + + FIXME + + puppet + salt + chef + ansible + fabric + + +File: pythonpackagingguide.info, Node: pip vs easy_install, Next: install_requires vs requirements files, Prev: Deploying Python applications, Up: Discussions + +4.2 pip vs easy_install +======================= + +*note easy_install: 196, now deprecated(1), was released in 2004 as part +of *note setuptools: 2d. It was notable at the time for installing +*note packages: b. from *note PyPI: 39. using requirement specifiers, +and automatically installing dependencies. + +*note pip: 2b. came later in 2008, as alternative to *note easy_install: +196, although still largely built on top of *note setuptools: 2d. +components. It was notable at the time for `not' installing packages as +*note Eggs: 166. or from *note Eggs: 166. (but rather simply as ‘flat’ +packages from *note sdists: 3d.), and introducing the idea of +Requirements Files(2), which gave users the power to easily replicate +environments. + +Here’s a breakdown of the important differences between pip and the +deprecated easy_install: + + `pip' `easy_install' + + +Installs from *note Wheels: d. Yes No + + +Uninstall Packages Yes (‘python -m pip uninstall’) No + + +Dependency Overrides Yes (Requirements Files(3)) No + + +List Installed Packages Yes (‘python -m pip list’ and ‘python -m No + pip freeze’) + + +PEP 438(4) Support Yes No + + +Installation format ‘Flat’ packages with ‘egg-info’ Encapsulated Egg format + metadata. + + +sys.path modification No Yes + + +Installs from *note Eggs: 166. No Yes + + +pylauncher support(5) No Yes (6) + + +*note Multi-version installs: a7. No Yes + + +Exclude scripts during install No Yes + + +per project index Only in virtualenv Yes, via setup.cfg + + +__________________________________________________________________ + + ---------- Footnotes ---------- + + (1) https://setuptools.readthedocs.io/en/latest/history.html#v42-0-0 + + (2) https://pip.pypa.io/en/latest/user_guide/#requirements-files + + (3) https://pip.pypa.io/en/latest/user_guide/#requirements-files + + (4) https://www.python.org/dev/peps/pep-0438 + + (5) https://bitbucket.org/vinay.sajip/pylauncher + + (6) (1) +‘https://setuptools.readthedocs.io/en/latest/deprecated/easy_install.html#natural-script-launcher’ + + +File: pythonpackagingguide.info, Node: install_requires vs requirements files, Next: Wheel vs Egg, Prev: pip vs easy_install, Up: Discussions + +4.3 install_requires vs requirements files +========================================== + +* Menu: + +* install_requires: install_requires<2>. +* Requirements files: Requirements files<2>. + + +File: pythonpackagingguide.info, Node: install_requires<2>, Next: Requirements files<2>, Up: install_requires vs requirements files + +4.3.1 install_requires +---------------------- + +‘install_requires’ is a *note setuptools: 2d. ‘setup.py’ keyword that +should be used to specify what a project `minimally' needs to run +correctly. When the project is installed by *note pip: 2b, this is the +specification that is used to install its dependencies. + +For example, if the project requires A and B, your ‘install_requires’ +would be like so: + + install_requires=[ + 'A', + 'B' + ] + +Additionally, it’s best practice to indicate any known lower or upper +bounds. + +For example, it may be known, that your project requires at least v1 of +‘A’, and v2 of ‘B’, so it would be like so: + + install_requires=[ + 'A>=1', + 'B>=2' + ] + +It may also be known that project A follows semantic versioning, and +that v2 of ‘A’ will indicate a break in compatibility, so it makes sense +to not allow v2: + + install_requires=[ + 'A>=1,<2', + 'B>=2' + ] + +It is not considered best practice to use ‘install_requires’ to pin +dependencies to specific versions, or to specify sub-dependencies (i.e. +dependencies of your dependencies). This is overly-restrictive, and +prevents the user from gaining the benefit of dependency upgrades. + +Lastly, it’s important to understand that ‘install_requires’ is a +listing of “Abstract” requirements, i.e just names and version +restrictions that don’t determine where the dependencies will be +fulfilled from (i.e. from what index or source). The where (i.e. how +they are to be made “Concrete”) is to be determined at install time +using *note pip: 2b. options. (1) + + ---------- Footnotes ---------- + + (1) (1) For more on “Abstract” vs “Concrete” requirements, see +‘https://caremad.io/posts/2013/07/setup-vs-requirement/’. + + +File: pythonpackagingguide.info, Node: Requirements files<2>, Prev: install_requires<2>, Up: install_requires vs requirements files + +4.3.2 Requirements files +------------------------ + +Requirements Files(1) described most simply, are just a list of pip +install(2) arguments placed into a file. + +Whereas ‘install_requires’ defines the dependencies for a single +project, Requirements Files(3) are often used to define the requirements +for a complete Python environment. + +Whereas ‘install_requires’ requirements are minimal, requirements files +often contain an exhaustive listing of pinned versions for the purpose +of achieving repeatable installations(4) of a complete environment. + +Whereas ‘install_requires’ requirements are “Abstract”, i.e. not +associated with any particular index, requirements files often contain +pip options like ‘--index-url’ or ‘--find-links’ to make requirements +“Concrete”, i.e. associated with a particular index or directory of +packages. (5) + +Whereas ‘install_requires’ metadata is automatically analyzed by pip +during an install, requirements files are not, and only are used when a +user specifically installs them using ‘python -m pip install -r’. + +__________________________________________________________________ + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/en/latest/user_guide/#requirements-files + + (2) https://pip.pypa.io/en/latest/cli/pip_install/#pip-install + + (3) https://pip.pypa.io/en/latest/user_guide/#requirements-files + + (4) https://pip.pypa.io/en/latest/user_guide/#repeatability + + (5) (1) For more on “Abstract” vs “Concrete” requirements, see +‘https://caremad.io/posts/2013/07/setup-vs-requirement/’. + + +File: pythonpackagingguide.info, Node: Wheel vs Egg, Prev: install_requires vs requirements files, Up: Discussions + +4.4 Wheel vs Egg +================ + +*note Wheel: d. and *note Egg: 166. are both packaging formats that aim +to support the use case of needing an install artifact that doesn’t +require building or compilation, which can be costly in testing and +production workflows. + +The *note Egg: 166. format was introduced by *note setuptools: 2d. in +2004, whereas the *note Wheel: d. format was introduced by PEP 427(1) in +2012. + +*note Wheel: d. is currently considered the standard for *note built: +68. and *note binary: 19f. packaging for Python. + +Here’s a breakdown of the important differences between *note Wheel: d. +and *note Egg: 166. + + * *note Wheel: d. has an official PEP(2). *note Egg: 166. did not. + + * *note Wheel: d. is a *note distribution: b. format, i.e a packaging + format. (3) *note Egg: 166. was both a distribution format and a + runtime installation format (if left zipped), and was designed to + be importable. + + * *note Wheel: d. archives do not include .pyc files. Therefore, + when the distribution only contains Python files (i.e. no compiled + extensions), and is compatible with Python 2 and 3, it’s possible + for a wheel to be “universal”, similar to an *note sdist: 3d. + + * *note Wheel: d. uses PEP376-compliant(4) ‘.dist-info’ directories. + Egg used ‘.egg-info’. + + * *note Wheel: d. has a richer file naming convention(5). A single + wheel archive can indicate its compatibility with a number of + Python language versions and implementations, ABIs, and system + architectures. + + * *note Wheel: d. is versioned. Every wheel file contains the + version of the wheel specification and the implementation that + packaged it. + + * *note Wheel: d. is internally organized by sysconfig path type(6), + therefore making it easier to convert to other formats. + +__________________________________________________________________ + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0427 + + (2) https://www.python.org/dev/peps/pep-0427 + + (3) (1) Circumstantially, in some cases, wheels can be used as an +importable runtime format, although this is not officially supported at +this time +(https://www.python.org/dev/peps/pep-0427#is-it-possible-to-import-python-code-directly-from-a-wheel-file). + + (4) https://www.python.org/dev/peps/pep-0376 + + (5) https://www.python.org/dev/peps/pep-0425 + + (6) +https://docs.python.org/2/library/sysconfig.html#installation-paths + + +File: pythonpackagingguide.info, Node: PyPA specifications, Next: Project Summaries, Prev: Discussions, Up: Top + +5 PyPA specifications +********************* + +This is a list of currently active interoperability specifications +maintained by the Python Packaging Authority. The process for updating +these standards, and for proposing new ones, is documented on +pypa.io(1). + +* Menu: + +* Package Distribution Metadata:: +* Package Distribution File Formats:: +* Package Index Interfaces:: + + ---------- Footnotes ---------- + + (1) https://www.pypa.io/en/latest/specifications/ + + +File: pythonpackagingguide.info, Node: Package Distribution Metadata, Next: Package Distribution File Formats, Up: PyPA specifications + +5.1 Package Distribution Metadata +================================= + +* Menu: + +* Core metadata specifications:: +* Version specifiers:: +* Dependency specifiers:: +* Declaring build system dependencies:: +* Declaring project metadata:: +* Platform compatibility tags:: +* Recording installed projects:: +* Entry points specification:: +* Recording the Direct URL Origin of installed distributions:: + + +File: pythonpackagingguide.info, Node: Core metadata specifications, Next: Version specifiers, Up: Package Distribution Metadata + +5.1.1 Core metadata specifications +---------------------------------- + +Fields defined in the following specification should be considered +valid, complete and not subject to change. The required fields are: + + - ‘Metadata-Version’ + + - ‘Name’ + + - ‘Version’ + +All the other fields are optional. + +The standard file format for metadata (including in *note wheels: 1a6. +and *note installed projects: 1a7.) is based on the format of email +headers. However, email formats have been revised several times, and +exactly which email RFC applies to packaging metadata is not specified. +In the absence of a precise definition, the practical standard is set by +what the standard library email.parser(1) module can parse using the +compat32(2) policy. + +Whenever metadata is serialised to a byte stream (for example, to save +to a file), strings must be serialised using the UTF-8 encoding. + +Although PEP 566(3) defined a way to transform metadata into a +JSON-compatible dictionary, this is not yet used as a standard +interchange format. The need for tools to work with years worth of +existing packages makes it difficult to shift to a new format. + + Note: `Interpreting old metadata:' In PEP 566(4), the version + specifier field format specification was relaxed to accept the + syntax used by popular publishing tools (namely to remove the + requirement that version specifiers must be surrounded by + parentheses). Metadata consumers may want to use the more relaxed + formatting rules even for metadata files that are nominally less + than version 2.1. + +* Menu: + +* Metadata-Version:: +* Name:: +* Version:: +* Dynamic (multiple use): Dynamic multiple use. +* Platform (multiple use): Platform multiple use. +* Supported-Platform (multiple use): Supported-Platform multiple use. +* Summary:: +* Description:: +* Description-Content-Type:: +* Keywords:: +* Home-page:: +* Download-URL:: +* Author:: +* Author-email:: +* Maintainer:: +* Maintainer-email:: +* License:: +* Classifier (multiple use): Classifier multiple use. +* Requires-Dist (multiple use): Requires-Dist multiple use. +* Requires-Python:: +* Requires-External (multiple use): Requires-External multiple use. +* Project-URL (multiple-use): Project-URL multiple-use. +* Provides-Extra (multiple use): Provides-Extra multiple use. +* Rarely Used Fields:: + + ---------- Footnotes ---------- + + (1) +https://docs.python.org/3/library/email.parser.html#module-email.parser + + (2) +https://docs.python.org/3/library/email.policy.html#email.policy.compat32 + + (3) https://www.python.org/dev/peps/pep-0566 + + (4) https://www.python.org/dev/peps/pep-0566 + + +File: pythonpackagingguide.info, Node: Metadata-Version, Next: Name, Up: Core metadata specifications + +5.1.1.1 Metadata-Version +........................ + +New in version 1.0. + +Version of the file format; legal values are “1.0”, “1.1”, “1.2”, “2.1”, +“2.2”, and “2.3”. + +Automated tools consuming metadata SHOULD warn if ‘metadata_version’ is +greater than the highest version they support, and MUST fail if +‘metadata_version’ has a greater major version than the highest version +they support (as described in PEP 440(1), the major version is the value +before the first dot). + +For broader compatibility, build tools MAY choose to produce +distribution metadata using the lowest metadata version that includes +all of the needed fields. + +Example: + + Metadata-Version: 2.3 + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0440 + + +File: pythonpackagingguide.info, Node: Name, Next: Version, Prev: Metadata-Version, Up: Core metadata specifications + +5.1.1.2 Name +............ + +New in version 1.0. + +Changed in version 2.1: Added additional restrictions on format from PEP +508(1) + +The name of the distribution. The name field is the primary identifier +for a distribution. A valid name consists only of ASCII letters and +numbers, period, underscore and hyphen. It must start and end with a +letter or number. Distribution names are limited to those which match +the following regex (run with ‘re.IGNORECASE’): + + ^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$ + +Example: + + Name: BeagleVote + +To normalize a distribution name for comparison purposes, it should be +lowercased with all runs of the characters ‘.’, ‘-’, or ‘_’ replaced +with a single ‘-’ character. This can be done using the following +snippet of code (as specified in PEP 503(2)): + + re.sub(r"[-_.]+", "-", name).lower() + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0508 + + (2) https://www.python.org/dev/peps/pep-0503 + + +File: pythonpackagingguide.info, Node: Version, Next: Dynamic multiple use, Prev: Name, Up: Core metadata specifications + +5.1.1.3 Version +............... + +New in version 1.0. + +A string containing the distribution’s version number. This field must +be in the format specified in PEP 440(1). + +Example: + + Version: 1.0a2 + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0440 + + +File: pythonpackagingguide.info, Node: Dynamic multiple use, Next: Platform multiple use, Prev: Version, Up: Core metadata specifications + +5.1.1.4 Dynamic (multiple use) +.............................. + +New in version 2.2. + +A string containing the name of another core metadata field. The field +names ‘Name’, ‘Version’, and ‘Metadata-Version’ may not be specified in +this field. + +When found in the metadata of a source distribution, the following rules +apply: + + 1. If a field is `not' marked as ‘Dynamic’, then the value of the + field in any wheel built from the sdist MUST match the value in the + sdist. If the field is not in the sdist, and not marked as + ‘Dynamic’, then it MUST NOT be present in the wheel. + + 2. If a field is marked as ‘Dynamic’, it may contain any valid value + in a wheel built from the sdist (including not being present at + all). + +If the sdist metadata version is older than version 2.2, then all fields +should be treated as if they were specified with ‘Dynamic’ (i.e. there +are no special restrictions on the metadata of wheels built from the +sdist). + +In any context other than a source distribution, ‘Dynamic’ is for +information only, and indicates that the field value was calculated at +wheel build time, and may not be the same as the value in the sdist or +in other wheels for the project. + +Full details of the semantics of ‘Dynamic’ are described in PEP 643(1). + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0643 + + +File: pythonpackagingguide.info, Node: Platform multiple use, Next: Supported-Platform multiple use, Prev: Dynamic multiple use, Up: Core metadata specifications + +5.1.1.5 Platform (multiple use) +............................... + +New in version 1.0. + +A Platform specification describing an operating system supported by the +distribution which is not listed in the “Operating System” Trove +classifiers. See “Classifier” below. + +Examples: + + Platform: ObscureUnix + Platform: RareDOS + + +File: pythonpackagingguide.info, Node: Supported-Platform multiple use, Next: Summary, Prev: Platform multiple use, Up: Core metadata specifications + +5.1.1.6 Supported-Platform (multiple use) +......................................... + +New in version 1.1. + +Binary distributions containing a PKG-INFO file will use the +Supported-Platform field in their metadata to specify the OS and CPU for +which the binary distribution was compiled. The semantics of the +Supported-Platform field are not specified in this PEP. + +Example: + + Supported-Platform: RedHat 7.2 + Supported-Platform: i386-win32-2791 + + +File: pythonpackagingguide.info, Node: Summary, Next: Description, Prev: Supported-Platform multiple use, Up: Core metadata specifications + +5.1.1.7 Summary +............... + +New in version 1.0. + +A one-line summary of what the distribution does. + +Example: + + Summary: A module for collecting votes from beagles. + + +File: pythonpackagingguide.info, Node: Description, Next: Description-Content-Type, Prev: Summary, Up: Core metadata specifications + +5.1.1.8 Description +................... + +New in version 1.0. + +Changed in version 2.1: This field may be specified in the message body +instead. + +A longer description of the distribution that can run to several +paragraphs. Software that deals with metadata should not assume any +maximum size for this field, though people shouldn’t include their +instruction manual as the description. + +The contents of this field can be written using reStructuredText markup +(1). For programs that work with the metadata, supporting markup is +optional; programs can also display the contents of the field as-is. +This means that authors should be conservative in the markup they use. + +To support empty lines and lines with indentation with respect to the +RFC 822 format, any CRLF character has to be suffixed by 7 spaces +followed by a pipe (“|”) char. As a result, the Description field is +encoded into a folded field that can be interpreted by RFC822 parser +(2). + +Example: + + Description: This project provides powerful math functions + |For example, you can use `sum()` to sum numbers: + | + |Example:: + | + | >>> sum(1, 2) + | 3 + | + +This encoding implies that any occurrences of a CRLF followed by 7 +spaces and a pipe char have to be replaced by a single CRLF when the +field is unfolded using a RFC822 reader. + +Alternatively, the distribution’s description may instead be provided in +the message body (i.e., after a completely blank line following the +headers, with no indentation or other special formatting necessary). + + ---------- Footnotes ---------- + + (1) (1) reStructuredText markup: ‘https://docutils.sourceforge.io/’ + + (2) (2) RFC 822 Long Header Fields: RFC 822#section-3.1.1 +(https://tools.ietf.org/html/rfc822.html#section-3.1.1) + + +File: pythonpackagingguide.info, Node: Description-Content-Type, Next: Keywords, Prev: Description, Up: Core metadata specifications + +5.1.1.9 Description-Content-Type +................................ + +New in version 2.1. + +A string stating the markup syntax (if any) used in the distribution’s +description, so that tools can intelligently render the description. + +Historically, PyPI supported descriptions in plain text and +reStructuredText (reST)(1), and could render reST into HTML. However, it +is common for distribution authors to write the description in +Markdown(2) ( RFC 7763(3)) as many code hosting sites render Markdown +READMEs, and authors would reuse the file for the description. PyPI +didn’t recognize the format and so could not render the description +correctly. This resulted in many packages on PyPI with poorly-rendered +descriptions when Markdown is left as plain text, or worse, was +attempted to be rendered as reST. This field allows the distribution +author to specify the format of their description, opening up the +possibility for PyPI and other tools to be able to render Markdown and +other formats. + +The format of this field is the same as the ‘Content-Type’ header in +HTTP (i.e.: RFC 1341(4)). Briefly, this means that it has a +‘type/subtype’ part and then it can optionally have a number of +parameters: + +Format: + + Description-Content-Type: /; charset=[; = ...] + +The ‘type/subtype’ part has only a few legal values: + + - ‘text/plain’ + + - ‘text/x-rst’ + + - ‘text/markdown’ + +The ‘charset’ parameter can be used to specify the character encoding of +the description. The only legal value is ‘UTF-8’. If omitted, it is +assumed to be ‘UTF-8’. + +Other parameters might be specific to the chosen subtype. For example, +for the ‘markdown’ subtype, there is an optional ‘variant’ parameter +that allows specifying the variant of Markdown in use (defaults to ‘GFM’ +if not specified). Currently, two variants are recognized: + + - ‘GFM’ for Github-flavored Markdown(5) + + - ‘CommonMark’ for CommonMark(6) + +Example: + + Description-Content-Type: text/plain; charset=UTF-8 + +Example: + + Description-Content-Type: text/x-rst; charset=UTF-8 + +Example: + + Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM + +Example: + + Description-Content-Type: text/markdown + +If a ‘Description-Content-Type’ is not specified, then applications +should attempt to render it as ‘text/x-rst; charset=UTF-8’ and fall back +to ‘text/plain’ if it is not valid rst. + +If a ‘Description-Content-Type’ is an unrecognized value, then the +assumed content type is ‘text/plain’ (Although PyPI will probably reject +anything with an unrecognized value). + +If the ‘Description-Content-Type’ is ‘text/markdown’ and ‘variant’ is +not specified or is set to an unrecognized value, then the assumed +‘variant’ is ‘GFM’. + +So for the last example above, the ‘charset’ defaults to ‘UTF-8’ and the +‘variant’ defaults to ‘GFM’ and thus it is equivalent to the example +before it. + + ---------- Footnotes ---------- + + (1) +https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html + + (2) https://daringfireball.net/projects/markdown/ + + (3) https://tools.ietf.org/html/rfc7763.html + + (4) https://www.w3.org/Protocols/rfc1341/4_Content-Type.html + + (5) https://tools.ietf.org/html/rfc7764.html#section-3.2 + + (6) https://tools.ietf.org/html/rfc7764.html#section-3.5 + + +File: pythonpackagingguide.info, Node: Keywords, Next: Home-page, Prev: Description-Content-Type, Up: Core metadata specifications + +5.1.1.10 Keywords +................. + +New in version 1.0. + +A list of additional keywords, separated by commas, to be used to assist +searching for the distribution in a larger catalog. + +Example: + + Keywords: dog,puppy,voting,election + + Note: The specification previously showed keywords separated by + spaces, but distutils and setuptools implemented it with commas. + These tools have been very widely used for many years, so it was + easier to update the specification to match the de facto standard. + + +File: pythonpackagingguide.info, Node: Home-page, Next: Download-URL, Prev: Keywords, Up: Core metadata specifications + +5.1.1.11 Home-page +.................. + +New in version 1.0. + +A string containing the URL for the distribution’s home page. + +Example: + + Home-page: http://www.example.com/~cschultz/bvote/ + + +File: pythonpackagingguide.info, Node: Download-URL, Next: Author, Prev: Home-page, Up: Core metadata specifications + +5.1.1.12 Download-URL +..................... + +New in version 1.1. + +A string containing the URL from which this version of the distribution +can be downloaded. (This means that the URL can’t be something like +“…/BeagleVote-latest.tgz”, but instead must be “…/BeagleVote-0.45.tgz”.) + + +File: pythonpackagingguide.info, Node: Author, Next: Author-email, Prev: Download-URL, Up: Core metadata specifications + +5.1.1.13 Author +............... + +New in version 1.0. + +A string containing the author’s name at a minimum; additional contact +information may be provided. + +Example: + + Author: C. Schultz, Universal Features Syndicate, + Los Angeles, CA + + +File: pythonpackagingguide.info, Node: Author-email, Next: Maintainer, Prev: Author, Up: Core metadata specifications + +5.1.1.14 Author-email +..................... + +New in version 1.0. + +A string containing the author’s e-mail address. It can contain a name +and e-mail address in the legal forms for a RFC-822 ‘From:’ header. + +Example: + + Author-email: "C. Schultz" + +Per RFC-822, this field may contain multiple comma-separated e-mail +addresses: + + Author-email: cschultz@example.com, snoopy@peanuts.com + + +File: pythonpackagingguide.info, Node: Maintainer, Next: Maintainer-email, Prev: Author-email, Up: Core metadata specifications + +5.1.1.15 Maintainer +................... + +New in version 1.2. + +A string containing the maintainer’s name at a minimum; additional +contact information may be provided. + +Note that this field is intended for use when a project is being +maintained by someone other than the original author: it should be +omitted if it is identical to ‘Author’. + +Example: + + Maintainer: C. Schultz, Universal Features Syndicate, + Los Angeles, CA + + +File: pythonpackagingguide.info, Node: Maintainer-email, Next: License, Prev: Maintainer, Up: Core metadata specifications + +5.1.1.16 Maintainer-email +......................... + +New in version 1.2. + +A string containing the maintainer’s e-mail address. It can contain a +name and e-mail address in the legal forms for a RFC-822 ‘From:’ header. + +Note that this field is intended for use when a project is being +maintained by someone other than the original author: it should be +omitted if it is identical to ‘Author-email’. + +Example: + + Maintainer-email: "C. Schultz" + +Per RFC-822, this field may contain multiple comma-separated e-mail +addresses: + + Maintainer-email: cschultz@example.com, snoopy@peanuts.com + + +File: pythonpackagingguide.info, Node: License, Next: Classifier multiple use, Prev: Maintainer-email, Up: Core metadata specifications + +5.1.1.17 License +................ + +New in version 1.0. + +Text indicating the license covering the distribution where the license +is not a selection from the “License” Trove classifiers. See *note +“Classifier”: 1cb. below. This field may also be used to specify a +particular version of a license which is named via the ‘Classifier’ +field, or to indicate a variation or exception to such a license. + +Examples: + + License: This software may only be obtained by sending the + author a postcard, and then the user promises not + to redistribute it. + + License: GPL version 3, excluding DRM provisions + + +File: pythonpackagingguide.info, Node: Classifier multiple use, Next: Requires-Dist multiple use, Prev: License, Up: Core metadata specifications + +5.1.1.18 Classifier (multiple use) +.................................. + +New in version 1.1. + +Each entry is a string giving a single classification value for the +distribution. Classifiers are described in PEP 301(1), and the Python +Package Index publishes a dynamic list of currently defined +classifiers(2). + +This field may be followed by an environment marker after a semicolon. + +Examples: + + Classifier: Development Status :: 4 - Beta + Classifier: Environment :: Console (Text Based) + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0301 + + (2) https://pypi.org/classifiers/ + + +File: pythonpackagingguide.info, Node: Requires-Dist multiple use, Next: Requires-Python, Prev: Classifier multiple use, Up: Core metadata specifications + +5.1.1.19 Requires-Dist (multiple use) +..................................... + +New in version 1.2. + +Changed in version 2.1: The field format specification was relaxed to +accept the syntax used by popular publishing tools. + +Each entry contains a string naming some other distutils project +required by this distribution. + +The format of a requirement string contains from one to four parts: + + * A project name, in the same format as the ‘Name:’ field. The only + mandatory part. + + * A comma-separated list of ‘extra’ names. These are defined by the + required project, referring to specific features which may need + extra dependencies. The names MUST conform to the restrictions + specified by the ‘Provides-Extra:’ field. + + * A version specifier. Tools parsing the format should accept + optional parentheses around this, but tools generating it should + not use parentheses. + + * An environment marker after a semicolon. This means that the + requirement is only needed in the specified conditions. + +See PEP 508(1) for full details of the allowed format. + +The project names should correspond to names as found on the Python +Package Index(2). + +Version specifiers must follow the rules described in *note Version +specifiers: 1d0. + +Examples: + + Requires-Dist: pkginfo + Requires-Dist: PasteDeploy + Requires-Dist: zope.interface (>3.5.0) + Requires-Dist: pywin32 >1.0; sys_platform == 'win32' + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0508 + + (2) https://pypi.org/ + + +File: pythonpackagingguide.info, Node: Requires-Python, Next: Requires-External multiple use, Prev: Requires-Dist multiple use, Up: Core metadata specifications + +5.1.1.20 Requires-Python +........................ + +New in version 1.2. + +This field specifies the Python version(s) that the distribution is +guaranteed to be compatible with. Installation tools may look at this +when picking which version of a project to install. + +The value must be in the format specified in *note Version specifiers: +1d0. + +This field cannot be followed by an environment marker. + +Examples: + + Requires-Python: >=3 + Requires-Python: >2.6,!=3.0.*,!=3.1.* + Requires-Python: ~=2.6 + + +File: pythonpackagingguide.info, Node: Requires-External multiple use, Next: Project-URL multiple-use, Prev: Requires-Python, Up: Core metadata specifications + +5.1.1.21 Requires-External (multiple use) +......................................... + +New in version 1.2. + +Changed in version 2.1: The field format specification was relaxed to +accept the syntax used by popular publishing tools. + +Each entry contains a string describing some dependency in the system +that the distribution is to be used. This field is intended to serve as +a hint to downstream project maintainers, and has no semantics which are +meaningful to the ‘distutils’ distribution. + +The format of a requirement string is a name of an external dependency, +optionally followed by a version declaration within parentheses. + +This field may be followed by an environment marker after a semicolon. + +Because they refer to non-Python software releases, version numbers for +this field are `not' required to conform to the format specified in PEP +440(1): they should correspond to the version scheme used by the +external dependency. + +Notice that there is no particular rule on the strings to be used. + +Examples: + + Requires-External: C + Requires-External: libpng (>=1.5) + Requires-External: make; sys_platform != "win32" + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0440 + + +File: pythonpackagingguide.info, Node: Project-URL multiple-use, Next: Provides-Extra multiple use, Prev: Requires-External multiple use, Up: Core metadata specifications + +5.1.1.22 Project-URL (multiple-use) +................................... + +New in version 1.2. + +A string containing a browsable URL for the project and a label for it, +separated by a comma. + +Example: + + Project-URL: Bug Tracker, http://bitbucket.org/tarek/distribute/issues/ + +The label is free text limited to 32 characters. + + +File: pythonpackagingguide.info, Node: Provides-Extra multiple use, Next: Rarely Used Fields, Prev: Project-URL multiple-use, Up: Core metadata specifications + +5.1.1.23 Provides-Extra (multiple use) +...................................... + +New in version 2.1. + +Changed in version 2.3: PEP 685(1) restricted valid values to be +unambiguous (i.e. no normalization required). For older metadata +versions, value restrictions were brought into line with ‘Name:’ and +normalization rules were introduced. + +A string containing the name of an optional feature. A valid name +consists only of lowercase ASCII letters, ASCII numbers, and hyphen. It +must start and end with a letter or number. Hyphens cannot be followed +by another hyphen. Names are limited to those which match the following +regex (which guarantees unambiguity): + + ^([a-z0-9]|[a-z0-9]([a-z0-9-](?!--))*[a-z0-9])$ + +The specified name may be used to make a dependency conditional on +whether the optional feature has been requested. + +Example: + + Provides-Extra: pdf + Requires-Dist: reportlab; extra == 'pdf' + +A second distribution requires an optional dependency by placing it +inside square brackets, and can request multiple features by separating +them with a comma (,). The requirements are evaluated for each +requested feature and added to the set of requirements for the +distribution. + +Example: + + Requires-Dist: beaglevote[pdf] + Requires-Dist: libexample[test, doc] + +Two feature names ‘test’ and ‘doc’ are reserved to mark dependencies +that are needed for running automated tests and generating +documentation, respectively. + +It is legal to specify ‘Provides-Extra:’ without referencing it in any +‘Requires-Dist:’. + +When writing data for older metadata versions, names MUST be normalized +following the same rules used for the ‘Name:’ field when performing +comparisons. Tools writing metadata MUST raise an error if two +‘Provides-Extra:’ entries would clash after being normalized. + +When reading data for older metadata versions, tools SHOULD warn when +values for this field would be invalid under newer metadata versions. +If a value would be invalid following the rules for ‘Name:’ in any core +metadata version, the user SHOULD be warned and the value ignored to +avoid ambiguity. Tools MAY choose to raise an error when reading an +invalid name for older metadata versions. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0685 + + +File: pythonpackagingguide.info, Node: Rarely Used Fields, Prev: Provides-Extra multiple use, Up: Core metadata specifications + +5.1.1.24 Rarely Used Fields +........................... + +The fields in this section are currently rarely used, as their design +was inspired by comparable mechanisms in Linux package management +systems, and it isn’t at all clear how tools should interpret them in +the context of an open index server such as PyPI(1). + +As a result, popular installation tools ignore them completely, which in +turn means there is little incentive for package publishers to set them +appropriately. However, they’re retained in the metadata specification, +as they’re still potentially useful for informational purposes, and can +also be used for their originally intended purpose in combination with a +curated package repository. + +* Menu: + +* Provides-Dist (multiple use): Provides-Dist multiple use. +* Obsoletes-Dist (multiple use): Obsoletes-Dist multiple use. + + ---------- Footnotes ---------- + + (1) https://pypi.org + + +File: pythonpackagingguide.info, Node: Provides-Dist multiple use, Next: Obsoletes-Dist multiple use, Up: Rarely Used Fields + +5.1.1.25 Provides-Dist (multiple use) +..................................... + +New in version 1.2. + +Changed in version 2.1: The field format specification was relaxed to +accept the syntax used by popular publishing tools. + +Each entry contains a string naming a Distutils project which is +contained within this distribution. This field `must' include the +project identified in the ‘Name’ field, followed by the version : Name +(Version). + +A distribution may provide additional names, e.g. to indicate that +multiple projects have been bundled together. For instance, source +distributions of the ‘ZODB’ project have historically included the +‘transaction’ project, which is now available as a separate +distribution. Installing such a source distribution satisfies +requirements for both ‘ZODB’ and ‘transaction’. + +A distribution may also provide a “virtual” project name, which does not +correspond to any separately-distributed project: such a name might be +used to indicate an abstract capability which could be supplied by one +of multiple projects. E.g., multiple projects might supply RDBMS +bindings for use by a given ORM: each project might declare that it +provides ‘ORM-bindings’, allowing other projects to depend only on +having at most one of them installed. + +A version declaration may be supplied and must follow the rules +described in *note Version specifiers: 1d0. The distribution’s version +number will be implied if none is specified. + +This field may be followed by an environment marker after a semicolon. + +Examples: + + Provides-Dist: OtherProject + Provides-Dist: AnotherProject (3.4) + Provides-Dist: virtual_package; python_version >= "3.4" + + +File: pythonpackagingguide.info, Node: Obsoletes-Dist multiple use, Prev: Provides-Dist multiple use, Up: Rarely Used Fields + +5.1.1.26 Obsoletes-Dist (multiple use) +...................................... + +New in version 1.2. + +Changed in version 2.1: The field format specification was relaxed to +accept the syntax used by popular publishing tools. + +Each entry contains a string describing a distutils project’s +distribution which this distribution renders obsolete, meaning that the +two projects should not be installed at the same time. + +Version declarations can be supplied. Version numbers must be in the +format specified in *note Version specifiers: 1d0. + +This field may be followed by an environment marker after a semicolon. + +The most common use of this field will be in case a project name +changes, e.g. Gorgon 2.3 gets subsumed into Torqued Python 1.0. When +you install Torqued Python, the Gorgon distribution should be removed. + +Examples: + + Obsoletes-Dist: Gorgon + Obsoletes-Dist: OtherProject (<3.0) + Obsoletes-Dist: Foo; os_name == "posix" + +__________________________________________________________________ + + +File: pythonpackagingguide.info, Node: Version specifiers, Next: Dependency specifiers, Prev: Core metadata specifications, Up: Package Distribution Metadata + +5.1.2 Version specifiers +------------------------ + +Version numbering requirements and the semantics for specifying +comparisons between versions are defined in PEP 440(1). + +The version specifiers section in this PEP supersedes the version +specifiers section in PEP 345(2). + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0440 + + (2) https://www.python.org/dev/peps/pep-0345 + + +File: pythonpackagingguide.info, Node: Dependency specifiers, Next: Declaring build system dependencies, Prev: Version specifiers, Up: Package Distribution Metadata + +5.1.3 Dependency specifiers +--------------------------- + +The dependency specifier format used to declare a dependency on another +component is defined in PEP 508(1). + +The environment markers section in this PEP supersedes the environment +markers section in PEP 345(2). + +Restrictions on names for extras is defined in PEP 685(3). + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0508 + + (2) https://www.python.org/dev/peps/pep-0345 + + (3) https://www.python.org/dev/peps/pep-0685 + + +File: pythonpackagingguide.info, Node: Declaring build system dependencies, Next: Declaring project metadata, Prev: Dependency specifiers, Up: Package Distribution Metadata + +5.1.4 Declaring build system dependencies +----------------------------------------- + +*note pyproject.toml: 1e5. is a build system independent file format +defined in PEP 518(1) that projects may provide in order to declare any +Python level dependencies that must be installed in order to run the +project’s build system successfully. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0518 + + +File: pythonpackagingguide.info, Node: Declaring project metadata, Next: Platform compatibility tags, Prev: Declaring build system dependencies, Up: Package Distribution Metadata + +5.1.5 Declaring project metadata +-------------------------------- + +PEP 621(1) specifies how to write a project’s *note core metadata: 106. +in a ‘pyproject.toml’ file for packaging-related tools to consume. It +defines the following specification as the canonical source for the +format used. + +There are two kinds of metadata: `static' and `dynamic'. Static +metadata is specified in the ‘pyproject.toml’ file directly and cannot +be specified or changed by a tool. Dynamic metadata is listed via the +‘dynamic’ field (defined later in this specification) and represents +metadata that a tool will later provide. + +The fields defined in this specification MUST be in a table named +‘[project]’ in ‘pyproject.toml’. No tools may add fields to this table +which are not defined by this specification. For tools wishing to store +their own settings in ‘pyproject.toml’, they may use the ‘[tool]’ table +as defined in the *note build dependency declaration specification: 1e3. +The lack of a ‘[project]’ table implicitly means the build back-end will +dynamically provide all fields. + +The only fields required to be statically defined are: + + - ‘name’ + +The fields which are required but may be specified `either' statically +or listed as dynamic are: + + - ‘version’ + +All other fields are considered optional and my be specified statically, +listed as dynamic, or left unspecified. + +* Menu: + +* name: name<2>. +* version: version<2>. +* description: description<2>. +* readme:: +* requires-python:: +* license: license<2>. +* authors/maintainers:: +* keywords: keywords<2>. +* classifiers: classifiers<2>. +* urls:: +* Entry points:: +* dependencies/optional-dependencies:: +* dynamic:: + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0621 + + +File: pythonpackagingguide.info, Node: name<2>, Next: version<2>, Up: Declaring project metadata + +5.1.5.1 ‘name’ +.............. + + - TOML(1) type: string + + - Corresponding *note core metadata: 106. field: *note Name: 1a9. + +The name of the project. + +Tools SHOULD normalize this name, as specified by PEP 503(2), as soon as +it is read for internal consistency. + + ---------- Footnotes ---------- + + (1) https://toml.io + + (2) https://www.python.org/dev/peps/pep-0503 + + +File: pythonpackagingguide.info, Node: version<2>, Next: description<2>, Prev: name<2>, Up: Declaring project metadata + +5.1.5.2 ‘version’ +................. + + - TOML(1) type: string + + - Corresponding *note core metadata: 106. field: *note Version: 1ab. + +The version of the project as supported by PEP 440(2). + +Users SHOULD prefer to specify already-normalized versions. + + ---------- Footnotes ---------- + + (1) https://toml.io + + (2) https://www.python.org/dev/peps/pep-0440 + + +File: pythonpackagingguide.info, Node: description<2>, Next: readme, Prev: version<2>, Up: Declaring project metadata + +5.1.5.3 ‘description’ +..................... + + - TOML(1) type: string + + - Corresponding *note core metadata: 106. field: *note Summary: 1b0. + +The summary description of the project. + + ---------- Footnotes ---------- + + (1) https://toml.io + + +File: pythonpackagingguide.info, Node: readme, Next: requires-python, Prev: description<2>, Up: Declaring project metadata + +5.1.5.4 ‘readme’ +................ + + - TOML(1) type: string or table + + - Corresponding *note core metadata: 106. field: *note Description: + 1b2. and *note Description-Content-Type: 1b4. + +The full description of the project (i.e. the README). + +The field accepts either a string or a table. If it is a string then it +is a path relative to ‘pyproject.toml’ to a text file containing the +full description. Tools MUST assume the file’s encoding is UTF-8. If +the file path ends in a case-insensitive ‘.md’ suffix, then tools MUST +assume the content-type is ‘text/markdown’. If the file path ends in a +case-insensitive ‘.rst’, then tools MUST assume the content-type is +‘text/x-rst’. If a tool recognizes more extensions than this PEP, they +MAY infer the content-type for the user without specifying this field as +‘dynamic’. For all unrecognized suffixes when a content-type is not +provided, tools MUST raise an error. + +The ‘readme’ field may also take a table. The ‘file’ key has a string +value representing a path relative to ‘pyproject.toml’ to a file +containing the full description. The ‘text’ key has a string value +which is the full description. These keys are mutually-exclusive, thus +tools MUST raise an error if the metadata specifies both keys. + +A table specified in the ‘readme’ field also has a ‘content-type’ field +which takes a string specifying the content-type of the full +description. A tool MUST raise an error if the metadata does not +specify this field in the table. If the metadata does not specify the +‘charset’ parameter, then it is assumed to be UTF-8. Tools MAY support +other encodings if they choose to. Tools MAY support alternative +content-types which they can transform to a content-type as supported by +the *note core metadata: 106. Otherwise tools MUST raise an error for +unsupported content-types. + + ---------- Footnotes ---------- + + (1) https://toml.io + + +File: pythonpackagingguide.info, Node: requires-python, Next: license<2>, Prev: readme, Up: Declaring project metadata + +5.1.5.5 ‘requires-python’ +......................... + + - TOML(1) type: string + + - Corresponding *note core metadata: 106. field: *note + Requires-Python: 1d1. + +The Python version requirements of the project. + + ---------- Footnotes ---------- + + (1) https://toml.io + + +File: pythonpackagingguide.info, Node: license<2>, Next: authors/maintainers, Prev: requires-python, Up: Declaring project metadata + +5.1.5.6 ‘license’ +................. + + - TOML(1) type: table + + - Corresponding *note core metadata: 106. field: *note License: 1c9. + +The table may have one of two keys. The ‘file’ key has a string value +that is a file path relative to ‘pyproject.toml’ to the file which +contains the license for the project. Tools MUST assume the file’s +encoding is UTF-8. The ‘text’ key has a string value which is the +license of the project. These keys are mutually exclusive, so a tool +MUST raise an error if the metadata specifies both keys. + + ---------- Footnotes ---------- + + (1) https://toml.io + + +File: pythonpackagingguide.info, Node: authors/maintainers, Next: keywords<2>, Prev: license<2>, Up: Declaring project metadata + +5.1.5.7 ‘authors’/‘maintainers’ +............................... + + - TOML(1) type: Array of inline tables with string keys and values + + - Corresponding *note core metadata: 106. field: *note Author: 1be, + *note Author-email: 1c1, *note Maintainer: 1c3, and *note + Maintainer-email: 1c6. + +The people or organizations considered to be the “authors” of the +project. The exact meaning is open to interpretation — it may list the +original or primary authors, current maintainers, or owners of the +package. + +The “maintainers” field is similar to “authors” in that its exact +meaning is open to interpretation. + +These fields accept an array of tables with 2 keys: ‘name’ and ‘email’. +Both values must be strings. The ‘name’ value MUST be a valid email +name (i.e. whatever can be put as a name, before an email, in RFC +822(2)) and not contain commas. The ‘email’ value MUST be a valid email +address. Both keys are optional. + +Using the data to fill in *note core metadata: 106. is as follows: + + 1. If only ‘name’ is provided, the value goes in *note Author: 1be. or + *note Maintainer: 1c3. as appropriate. + + 2. If only ‘email’ is provided, the value goes in *note Author-email: + 1c1. or *note Maintainer-email: 1c6. as appropriate. + + 3. If both ‘email’ and ‘name’ are provided, the value goes in *note + Author-email: 1c1. or *note Maintainer-email: 1c6. as appropriate, + with the format ‘{name} <{email}>’. + + 4. Multiple values should be separated by commas. + + ---------- Footnotes ---------- + + (1) https://toml.io + + (2) https://tools.ietf.org/html/rfc822.html + + +File: pythonpackagingguide.info, Node: keywords<2>, Next: classifiers<2>, Prev: authors/maintainers, Up: Declaring project metadata + +5.1.5.8 ‘keywords’ +.................. + + - TOML(1) type: array of strings + + - Corresponding *note core metadata: 106. field: *note Keywords: 1b7. + +The keywords for the project. + + ---------- Footnotes ---------- + + (1) https://toml.io + + +File: pythonpackagingguide.info, Node: classifiers<2>, Next: urls, Prev: keywords<2>, Up: Declaring project metadata + +5.1.5.9 ‘classifiers’ +..................... + + - TOML(1) type: array of strings + + - Corresponding *note core metadata: 106. field: *note Classifier: + 1cd. + +Trove classifiers which apply to the project. + + ---------- Footnotes ---------- + + (1) https://toml.io + + +File: pythonpackagingguide.info, Node: urls, Next: Entry points, Prev: classifiers<2>, Up: Declaring project metadata + +5.1.5.10 ‘urls’ +............... + + - TOML(1) type: table with keys and values of strings + + - Corresponding *note core metadata: 106. field: *note Project-URL: + 1d4. + +A table of URLs where the key is the URL label and the value is the URL +itself. + + ---------- Footnotes ---------- + + (1) https://toml.io + + +File: pythonpackagingguide.info, Node: Entry points, Next: dependencies/optional-dependencies, Prev: urls, Up: Declaring project metadata + +5.1.5.11 Entry points +..................... + + - TOML(1) type: table (‘[project.scripts]’, ‘[project.gui-scripts]’, + and ‘[project.entry-points]’) + + - *note Entry points specification: 1f4. + +There are three tables related to entry points. The ‘[project.scripts]’ +table corresponds to the ‘console_scripts’ group in the *note entry +points specification: 1f4. The key of the table is the name of the +entry point and the value is the object reference. + +The ‘[project.gui-scripts]’ table corresponds to the ‘gui_scripts’ group +in the *note entry points specification: 1f4. Its format is the same as +‘[project.scripts]’. + +The ‘[project.entry-points]’ table is a collection of tables. Each +sub-table’s name is an entry point group. The key and value semantics +are the same as ‘[project.scripts]’. Users MUST NOT create nested +sub-tables but instead keep the entry point groups to only one level +deep. + +Build back-ends MUST raise an error if the metadata defines a +‘[project.entry-points.console_scripts]’ or +‘[project.entry-points.gui_scripts]’ table, as they would be ambiguous +in the face of ‘[project.scripts]’ and ‘[project.gui-scripts]’, +respectively. + + ---------- Footnotes ---------- + + (1) https://toml.io + + +File: pythonpackagingguide.info, Node: dependencies/optional-dependencies, Next: dynamic, Prev: Entry points, Up: Declaring project metadata + +5.1.5.12 ‘dependencies’/‘optional-dependencies’ +............................................... + + - TOML(1) type: Array of PEP 508(2) strings (‘dependencies’), and a + table with values of arrays of PEP 508(3) strings + (‘optional-dependencies’) + + - Corresponding *note core metadata: 106. field: *note Requires-Dist: + 1ce. and *note Provides-Extra: 1d7. + +The (optional) dependencies of the project. + +For ‘dependencies’, it is a key whose value is an array of strings. +Each string represents a dependency of the project and MUST be formatted +as a valid PEP 508(4) string. Each string maps directly to a *note +Requires-Dist: 1ce. entry. + +For ‘optional-dependencies’, it is a table where each key specifies an +extra and whose value is an array of strings. The strings of the arrays +must be valid PEP 508(5) strings. The keys MUST be valid values for +*note Provides-Extra: 1d7. Each value in the array thus becomes a +corresponding *note Requires-Dist: 1ce. entry for the matching *note +Provides-Extra: 1d7. metadata. + + ---------- Footnotes ---------- + + (1) https://toml.io + + (2) https://www.python.org/dev/peps/pep-0508 + + (3) https://www.python.org/dev/peps/pep-0508 + + (4) https://www.python.org/dev/peps/pep-0508 + + (5) https://www.python.org/dev/peps/pep-0508 + + +File: pythonpackagingguide.info, Node: dynamic, Prev: dependencies/optional-dependencies, Up: Declaring project metadata + +5.1.5.13 ‘dynamic’ +.................. + + - TOML(1) type: array of string + + - A corresponding *note core metadata: 106. field does not exist + +Specifies which fields listed by this PEP were intentionally unspecified +so another tool can/will provide such metadata dynamically. This +clearly delineates which metadata is purposefully unspecified and +expected to stay unspecified compared to being provided via tooling +later on. + + - A build back-end MUST honour statically-specified metadata (which + means the metadata did not list the field in ‘dynamic’). + + - A build back-end MUST raise an error if the metadata specifies + ‘name’ in ‘dynamic’. + + - If the *note core metadata: 106. specification lists a field as + “Required”, then the metadata MUST specify the field statically or + list it in ‘dynamic’ (build back-ends MUST raise an error + otherwise, i.e. it should not be possible for a required field to + not be listed somehow in the ‘[project]’ table). + + - If the *note core metadata: 106. specification lists a field as + “Optional”, the metadata MAY list it in ‘dynamic’ if the + expectation is a build back-end will provide the data for the field + later. + + - Build back-ends MUST raise an error if the metadata specifies a + field statically as well as being listed in ‘dynamic’. + + - If the metadata does not list a field in ‘dynamic’, then a build + back-end CANNOT fill in the requisite metadata on behalf of the + user (i.e. ‘dynamic’ is the only way to allow a tool to fill in + metadata and the user must opt into the filling in). + + - Build back-ends MUST raise an error if the metadata specifies a + field in ‘dynamic’ but the build back-end was unable to determine + the data for it (omitting the data, if determined to be the + accurate value, is acceptable). + + ---------- Footnotes ---------- + + (1) https://toml.io + + +File: pythonpackagingguide.info, Node: Platform compatibility tags, Next: Recording installed projects, Prev: Declaring project metadata, Up: Package Distribution Metadata + +5.1.6 Platform compatibility tags +--------------------------------- + +Platform compatibility tags allow build tools to mark distributions as +being compatible with specific platforms, and allows installers to +understand which distributions are compatible with the system they are +running on. + +The platform compatibility tagging model used for the ‘wheel’ +distribution format is defined in PEP 425(1). + +* Menu: + +* Platform tags for Windows:: +* Platform tags for macOS (Mac OS X): Platform tags for macOS Mac OS X. +* Platform tags for common Linux distributions:: +* Platform tags for other *nix platforms:: + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0425 + + +File: pythonpackagingguide.info, Node: Platform tags for Windows, Next: Platform tags for macOS Mac OS X, Up: Platform compatibility tags + +5.1.6.1 Platform tags for Windows +................................. + +The scheme defined in PEP 425(1) covers public distribution of wheel +files to systems running Windows. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0425 + + +File: pythonpackagingguide.info, Node: Platform tags for macOS Mac OS X, Next: Platform tags for common Linux distributions, Prev: Platform tags for Windows, Up: Platform compatibility tags + +5.1.6.2 Platform tags for macOS (Mac OS X) +.......................................... + +The scheme defined in PEP 425(1) covers public distribution of wheel +files to systems running macOS (previously known as Mac OS X). + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0425 + + +File: pythonpackagingguide.info, Node: Platform tags for common Linux distributions, Next: Platform tags for other *nix platforms, Prev: Platform tags for macOS Mac OS X, Up: Platform compatibility tags + +5.1.6.3 Platform tags for common Linux distributions +.................................................... + +The scheme defined in PEP 425(1) is insufficient for public distribution +of wheel files (and *nix wheel files in general) to Linux platforms, due +to the large ecosystem of Linux platforms and subtle differences between +them. + +Instead, PEP 600(2) defines the ‘manylinux’ standard, which represents a +common subset of Linux platforms, and allows building wheels tagged with +the ‘manylinux’ platform tag which can be used across most common Linux +distributions. + +There were multiple iterations of the ‘manylinux’ specification, each +representing the common subset of Linux platforms at a given point in +time: + + * ‘manylinux1’ ( PEP 513(3)) supports ‘x86_64’ and ‘i686’ + architectures, and is based on a compatible Linux platform from + 2007. + + * ‘manylinux2010’ ( PEP 571(4)) supports ‘x86_64’ and ‘i686’ + architectures. and updates the previous specification to be based + on a compatible Linux platform from 2010 instead. + + * ‘manylinux2014’ ( PEP 599(5)) adds support for a number of + additional architectures (‘aarch64’, ‘armv7l’, ‘ppc64’, ‘ppc64le’, + and ‘s390x’) and updates the base platform to a compatible Linux + platform from 2014. + +‘manylinux_x_y’ ( PEP 600(6)) supersedes all previous PEPs to define a +future-proof standard. It defines ‘x’ and ‘y’ as glibc major an minor +versions supported (e.g. ‘manylinux_2_24’ should work on any distro +using glibc 2.24+). Previous tags are still supported for backward +compatibility. + +In general, distributions built for older versions of the specification +are forwards-compatible (meaning that ‘manylinux1’ distributions should +continue to work on modern systems) but not backwards-compatible +(meaning that ‘manylinux2010’ distributions are not expected to work on +platforms that existed before 2010). + +Package maintainers should attempt to target the most compatible +specification possible, with the caveat that the provided build +environment for ‘manylinux1’ and ‘manylinux2010’ have reached +end-of-life meaning that these images will no longer receive security +updates. + +* Menu: + +* Manylinux compatibility support:: + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0425 + + (2) https://www.python.org/dev/peps/pep-0600 + + (3) https://www.python.org/dev/peps/pep-0513 + + (4) https://www.python.org/dev/peps/pep-0571 + + (5) https://www.python.org/dev/peps/pep-0599 + + (6) https://www.python.org/dev/peps/pep-0600 + + +File: pythonpackagingguide.info, Node: Manylinux compatibility support, Up: Platform tags for common Linux distributions + +5.1.6.4 Manylinux compatibility support +....................................... + + Note: + * The ‘manylinux2014’ specification is relatively new and is not + yet widely recognised by install tools. + + * The ‘manylinux_x_y’ specification is relatively new and is not + yet widely recognised by install tools. + +The following table shows the minimum versions of relevant projects to +support the various ‘manylinux’ standards: + +Tool ‘manylinux1’ ‘manylinux2010’ ‘manylinux2014’ ‘manylinux_x_y’ + +---------------------------------------------------------------------------------------------------- + +pip ‘>=8.1.0’ ‘>=19.0’ ‘>=19.3’ ‘>=20.3’ + + +auditwheel ‘>=1.0.0’ ‘>=2.0.0’ ‘>=3.0.0’ ‘>=3.3.0’ (1) + + + ---------- Footnotes ---------- + + (1) (1) Only support for ‘manylinux_2_24’ has been added in +auditwheel 3.3.0 + + +File: pythonpackagingguide.info, Node: Platform tags for other *nix platforms, Prev: Platform tags for common Linux distributions, Up: Platform compatibility tags + +5.1.6.5 Platform tags for other *nix platforms +.............................................. + +The scheme defined in PEP 425(1) is not generally sufficient for public +distribution of wheel files to other *nix platforms. Efforts are +currently (albeit intermittently) under way to define improved +compatibility tagging schemes for AIX and for Alpine Linux. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0425 + + +File: pythonpackagingguide.info, Node: Recording installed projects, Next: Entry points specification, Prev: Platform compatibility tags, Up: Package Distribution Metadata + +5.1.7 Recording installed projects +---------------------------------- + +This document specifies a common format of recording information about +Python *note projects: 203. installed in an environment. A common +metadata format allows tools to query, manage or uninstall projects, +regardless of how they were installed. + +Almost all information is optional. This allows tools outside the +Python ecosystem, such as Linux package managers, to integrate with +Python tooling as much as possible. For example, even if an installer +cannot easily provide a list of installed files in a format specific to +Python tooling, it should still record the name and version of the +installed project. + +* Menu: + +* History and change workflow:: +* The .dist-info directory: The dist-info directory. +* The METADATA file:: +* The RECORD file:: +* The INSTALLER file:: +* The direct_url.json file: The direct_url json file. + + +File: pythonpackagingguide.info, Node: History and change workflow, Next: The dist-info directory, Up: Recording installed projects + +5.1.7.1 History and change workflow +................................... + +The metadata described here was first specified in PEP 376(1), and later +amended in PEP 627(2). It was formerly known as `Database of Installed +Python Distributions'. Further amendments (except trivial language or +typography fixes) must be made through the PEP process (see PEP 1(3)). + +While this document is the normative specification, these PEPs that +introduce changes to it may include additional information such as +rationales and backwards compatibility considerations. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0376 + + (2) https://www.python.org/dev/peps/pep-0627 + + (3) https://www.python.org/dev/peps/pep-0001 + + +File: pythonpackagingguide.info, Node: The dist-info directory, Next: The METADATA file, Prev: History and change workflow, Up: Recording installed projects + +5.1.7.2 The .dist-info directory +................................ + +Each project installed from a distribution must, in addition to files, +install a “‘.dist-info’” directory located alongside importable modules +and packages (commonly, the ‘site-packages’ directory). + +This directory is named as ‘{name}-{version}.dist-info’, with ‘name’ and +‘version’ fields corresponding to *note Core metadata specifications: +106. Both fields must be normalized (see PEP 503(1) and PEP 440(2) for +the definition of normalization for each field respectively), and +replace dash (‘-’) characters with underscore (‘_’) characters, so the +‘.dist-info’ directory always has exactly one dash (‘-’) character in +its stem, separating the ‘name’ and ‘version’ fields. + +Historically, tools have failed to replace dot characters or normalize +case in the ‘name’ field, or not perform normalization in the ‘version’ +field. Tools consuming ‘.dist-info’ directories should expect those +fields to be unnormalized, and treat them as equivalent to their +normalized counterparts. New tools that write ‘.dist-info’ directories +MUST normalize both ‘name’ and ‘version’ fields using the rules +described above, and existing tools are encouraged to start normalizing +those fields. + + Note: The ‘.dist-info’ directory’s name is formatted to + unambigiously represent a distribution as a filesystem path. Tools + presenting a distribution name to a user should avoid using the + normalized name, and instead present the specified name (when + needed prior to resolution to an installed package), or read the + respective fields in Core Metadata, since values listed there are + unescaped and accurately reflect the distribution. Libraries + should provide API for such tools to consume, so tools can have + access to the unnormalized name when displaying distrubution + information. + +This ‘.dist-info’ directory can contain these files, described in detail +below: + + * ‘METADATA’: contains project metadata + + * ‘RECORD’: records the list of installed files. + + * ‘INSTALLER’: records the name of the tool used to install the + project. + +The ‘METADATA’ file is mandatory. All other files may be omitted at the +installing tool’s discretion. Additional installer-specific files may +be present. + + Note: The *note Binary distribution format: 206. specification + describes additional files that may appear in the ‘.dist-info’ + directory of a *note Wheel: d. Such files may be copied to the + ‘.dist-info’ directory of an installed project. + +The previous versions of this specification also specified a ‘REQUESTED’ +file. This file is now considered a tool-specific extension, but may be +standardized again in the future. See PEP 376(3) for its original +meaning. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0503#normalized-names + + (2) https://www.python.org/dev/peps/pep-0440#normalization + + (3) https://www.python.org/dev/peps/pep-0376/#requested + + +File: pythonpackagingguide.info, Node: The METADATA file, Next: The RECORD file, Prev: The dist-info directory, Up: Recording installed projects + +5.1.7.3 The METADATA file +......................... + +The ‘METADATA’ file contains metadata as described in the *note Core +metadata specifications: 106. specification, version 1.1 or greater. + +The ‘METADATA’ file is mandatory. If it cannot be created, or if +required core metadata is not available, installers must report an error +and fail to install the project. + + +File: pythonpackagingguide.info, Node: The RECORD file, Next: The INSTALLER file, Prev: The METADATA file, Up: Recording installed projects + +5.1.7.4 The RECORD file +....................... + +The ‘RECORD’ file holds the list of installed files. It is a CSV file +containing one record (line) per installed file. + +The CSV dialect must be readable with the default ‘reader’ of Python’s +‘csv’ module: + + * field delimiter: ‘,’ (comma), + + * quoting char: ‘"’ (straight double quote), + + * line terminator: either ‘\r\n’ or ‘\n’. + +Each record is composed of three elements: the file’s `path', the `hash' +of the contents, and its `size'. + +The `path' may be either absolute, or relative to the directory +containing the ‘.dist-info’ directory (commonly, the ‘site-packages’ +directory). On Windows, directories may be separated either by forward- +or backslashes (‘/’ or ‘\’). + +The `hash' is either an empty string or the name of a hash algorithm +from ‘hashlib.algorithms_guaranteed’, followed by the equals character +‘=’ and the digest of the file’s contents, encoded with the +urlsafe-base64-nopad encoding (‘base64.urlsafe_b64encode(digest)’ with +trailing ‘=’ removed). + +The `size' is either the empty string, or file’s size in bytes, as a +base 10 integer. + +For any file, either or both of the `hash' and `size' fields may be left +empty. Commonly, entries for ‘.pyc’ files and the ‘RECORD’ file itself +have empty `hash' and `size'. For other files, leaving the information +out is discouraged, as it prevents verifying the integrity of the +installed project. + +If the ‘RECORD’ file is present, it must list all installed files of the +project, except ‘.pyc’ files corresponding to ‘.py’ files listed in +‘RECORD’, which are optional. Notably, the contents of the ‘.dist-info’ +directory (including the ‘RECORD’ file itself) must be listed. +Directories should not be listed. + +To completely uninstall a package, a tool needs to remove all files +listed in ‘RECORD’, all ‘.pyc’ files (of all optimization levels) +corresponding to removed ‘.py’ files, and any directories emptied by the +uninstallation. + +Here is an example snippet of a possible ‘RECORD’ file: + + /usr/bin/black,sha256=iFlOnL32lIa-RKk-MDihcbJ37wxmRbE4xk6eVYVTTeU,220 + ../../../bin/blackd,sha256=lCadt4mcU-B67O1gkQVh7-vsKgLpx6ny1le34Jz6UVo,221 + __pycache__/black.cpython-38.pyc,, + __pycache__/blackd.cpython-38.pyc,, + black-19.10b0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 + black-19.10b0.dist-info/LICENSE,sha256=nAQo8MO0d5hQz1vZbhGqqK_HLUqG1KNiI9erouWNbgA,1080 + black-19.10b0.dist-info/METADATA,sha256=UN40nGoVVTSpvLrTBwNsXgZdZIwoKFSrrDDHP6B7-A0,58841 + black-19.10b0.dist-info/RECORD,, + black.py,sha256=45IF72OgNfF8WpeNHnxV2QGfbCLubV5Xjl55cI65kYs,140161 + blackd.py,sha256=JCxaK4hLkMRwVfZMj8FRpRRYC0172-juKqbN22bISLE,6672 + blib2to3/__init__.py,sha256=9_8wL9Scv8_Cs8HJyJHGvx1vwXErsuvlsAqNZLcJQR0,8 + blib2to3/__pycache__/__init__.cpython-38.pyc,, + blib2to3/__pycache__/pygram.cpython-38.pyc,sha256=zpXgX4FHDuoeIQKO_v0sRsB-RzQFsuoKoBYvraAdoJw,1512 + blib2to3/__pycache__/pytree.cpython-38.pyc,sha256=LYLplXtG578ZjaFeoVuoX8rmxHn-BMAamCOsJMU1b9I,24910 + blib2to3/pygram.py,sha256=mXpQPqHcamFwch0RkyJsb92Wd0kUP3TW7d-u9dWhCGY,2085 + blib2to3/pytree.py,sha256=RWj3IL4U-Ljhkn4laN0C3p7IRdfvT3aIRjTV-x9hK1c,28530 + +If the ‘RECORD’ file is missing, tools that rely on ‘.dist-info’ must +not atempt to uninstall or upgrade the package. (This does not apply to +tools that rely on other sources of information, such as system package +managers in Linux distros.) + + +File: pythonpackagingguide.info, Node: The INSTALLER file, Next: The direct_url json file, Prev: The RECORD file, Up: Recording installed projects + +5.1.7.5 The INSTALLER file +.......................... + +If present, ‘INSTALLER’ is a single-line text file naming the tool used +to install the project. If the installer is executable from the command +line, ‘INSTALLER’ should contain the command name. Otherwise, it should +contain a printable ASCII string. + +The file can be terminated by zero or more ASCII whitespace characters. + +Here are examples of two possible ‘INSTALLER’ files: + + pip + + MegaCorp Cloud Install-O-Matic + +This value should be used for informational purposes only. For example, +if a tool is asked to uninstall a project but finds no ‘RECORD’ file, it +may suggest that the tool named in ‘INSTALLER’ may be able to do the +uninstallation. + + +File: pythonpackagingguide.info, Node: The direct_url json file, Prev: The INSTALLER file, Up: Recording installed projects + +5.1.7.6 The direct_url.json file +................................ + +This file MUST be created by installers when installing a distribution +from a requirement specifying a direct URL reference (including a VCS +URL). + +This file MUST NOT be created when installing a distribution from an +other type of requirement (i.e. name plus version specifier). + +Its detailed specification is at *note Recording the Direct URL Origin +of installed distributions: 20b. + + +File: pythonpackagingguide.info, Node: Entry points specification, Next: Recording the Direct URL Origin of installed distributions, Prev: Recording installed projects, Up: Package Distribution Metadata + +5.1.8 Entry points specification +-------------------------------- + +`Entry points' are a mechanism for an installed distribution to +advertise components it provides to be discovered and used by other +code. For example: + + - Distributions can specify ‘console_scripts’ entry points, each + referring to a function. When `pip' (or another console_scripts + aware installer) installs the distribution, it will create a + command-line wrapper for each entry point. + + - Applications can use entry points to load plugins; e.g. Pygments + (a syntax highlighting tool) can use additional lexers and styles + from separately installed packages. For more about this, see *note + Creating and discovering plugins: 138. + +The entry point file format was originally developed to allow packages +built with setuptools to provide integration point metadata that would +be read at runtime with ‘importlib.metadata’. It is now defined as a +PyPA interoperability specification in order to allow build tools other +than setuptools to publish ‘importlib.metadata’ compatible entry point +metadata, and runtime libraries other than ‘importlib.metadata’ to +portably read published entry point metadata (potentially with different +caching and conflict resolution strategies). + +* Menu: + +* Data model:: +* File format:: +* Use for scripts:: + + +File: pythonpackagingguide.info, Node: Data model, Next: File format, Up: Entry points specification + +5.1.8.1 Data model +.................. + +Conceptually, an entry point is defined by three required properties: + + - The `group' that an entry point belongs to indicates what sort of + object it provides. For instance, the group ‘console_scripts’ is + for entry points referring to functions which can be used as a + command, while ‘pygments.styles’ is the group for classes defining + pygments styles. The consumer typically defines the expected + interface. To avoid clashes, consumers defining a new group should + use names starting with a PyPI name owned by the consumer project, + followed by ‘.’. Group names must be one or more groups of + letters, numbers and underscores, separated by dots (regex + ‘^\w+(\.\w+)*$’). + + - The `name' identifies this entry point within its group. The + precise meaning of this is up to the consumer. For console + scripts, the name of the entry point is the command that will be + used to launch it. Within a distribution, entry point names should + be unique. If different distributions provide the same name, the + consumer decides how to handle such conflicts. The name may + contain any characters except ‘=’, but it cannot start or end with + any whitespace character, or start with ‘[’. For new entry points, + it is recommended to use only letters, numbers, underscores, dots + and dashes (regex ‘[\w.-]+’). + + - The `object reference' points to a Python object. It is either in + the form ‘importable.module’, or ‘importable.module:object.attr’. + Each of the parts delimited by dots and the colon is a valid Python + identifier. It is intended to be looked up like this: + + import importlib + modname, qualname_separator, qualname = object_ref.partition(':') + obj = importlib.import_module(modname) + if qualname_separator: + for attr in qualname.split('.'): + obj = getattr(obj, attr) + + Note: Some tools call this kind of object reference by itself an + ‘entry point’, for want of a better term, especially where it + points to a function to launch a program. + +There is also an optional property: the `extras' are a set of strings +identifying optional features of the distribution providing the entry +point. If these are specified, the entry point requires the +dependencies of those ‘extras’. See the metadata field *note +Provides-Extra (multiple use): 1d6. + +Using extras for an entry point is no longer recommended. Consumers +should support parsing them from existing distributions, but may then +ignore them. New publishing tools need not support specifying extras. +The functionality of handling extras was tied to setuptools’ model of +managing ‘egg’ packages, but newer tools such as pip and virtualenv use +a different model. + + +File: pythonpackagingguide.info, Node: File format, Next: Use for scripts, Prev: Data model, Up: Entry points specification + +5.1.8.2 File format +................... + +Entry points are defined in a file called ‘entry_points.txt’ in the +‘*.dist-info’ directory of the distribution. This is the directory +described in PEP 376(1) for installed distributions, and in PEP 427(2) +for wheels. The file uses the UTF-8 character encoding. + +The file contents are in INI format, as read by Python’s configparser(3) +module. However, configparser treats names as case-insensitive by +default, whereas entry point names are case sensitive. A case-sensitive +config parser can be made like this: + + import configparser + + class CaseSensitiveConfigParser(configparser.ConfigParser): + optionxform = staticmethod(str) + +The entry points file must always use ‘=’ to delimit names from values +(whereas configparser also allows using ‘:’). + +The sections of the config file represent entry point groups, the names +are names, and the values encode both the object reference and the +optional extras. If extras are used, they are a comma-separated list +inside square brackets. + +Within a value, readers must accept and ignore spaces (including +multiple consecutive spaces) before or after the colon, between the +object reference and the left square bracket, between the extra names +and the square brackets and colons delimiting them, and after the right +square bracket. The syntax for extras is formally specified as part of +PEP 508(4) (as ‘extras’) and restrictions on values specified in PEP +685(5). For tools writing the file, it is recommended only to insert a +space between the object reference and the left square bracket. + +For example: + + [console_scripts] + foo = foomod:main + # One which depends on extras: + foobar = foomod:main_bar [bar,baz] + + # pytest plugins refer to a module, so there is no ':obj' + [pytest11] + nbval = nbval.plugin + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0376 + + (2) https://www.python.org/dev/peps/pep-0427 + + (3) +https://docs.python.org/3/library/configparser.html#module-configparser + + (4) https://www.python.org/dev/peps/pep-0508 + + (5) https://www.python.org/dev/peps/pep-0685 + + +File: pythonpackagingguide.info, Node: Use for scripts, Prev: File format, Up: Entry points specification + +5.1.8.3 Use for scripts +....................... + +Two groups of entry points have special significance in packaging: +‘console_scripts’ and ‘gui_scripts’. In both groups, the name of the +entry point should be usable as a command in a system shell after the +package is installed. The object reference points to a function which +will be called with no arguments when this command is run. The function +may return an integer to be used as a process exit code, and returning +‘None’ is equivalent to returning ‘0’. + +For instance, the entry point ‘mycmd = mymod:main’ would create a +command ‘mycmd’ launching a script like this: + + import sys + from mymod import main + sys.exit(main()) + +The difference between ‘console_scripts’ and ‘gui_scripts’ only affects +Windows systems. ‘console_scripts’ are wrapped in a console executable, +so they are attached to a console and can use ‘sys.stdin’, ‘sys.stdout’ +and ‘sys.stderr’ for input and output. ‘gui_scripts’ are wrapped in a +GUI executable, so they can be started without a console, but cannot use +standard streams unless application code redirects them. Other +platforms do not have the same distinction. + +Install tools are expected to set up wrappers for both ‘console_scripts’ +and ‘gui_scripts’ in the scripts directory of the install scheme. They +are not responsible for putting this directory in the ‘PATH’ environment +variable which defines where command-line tools are found. + +As files are created from the names, and some filesystems are +case-insensitive, packages should avoid using names in these groups +which differ only in case. The behaviour of install tools when names +differ only in case is undefined. + + +File: pythonpackagingguide.info, Node: Recording the Direct URL Origin of installed distributions, Prev: Entry points specification, Up: Package Distribution Metadata + +5.1.9 Recording the Direct URL Origin of installed distributions +---------------------------------------------------------------- + +This document specifies a ‘direct_url.json’ file in the ‘*.dist-info’ +directory of an installed distribution, to record the Direct URL Origin +of the distribution. The layout of this file was originally specified +in PEP 610(1) and is formally documented here. + +* Menu: + +* Specification:: +* Registered VCS:: +* Examples:: + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0610 + + +File: pythonpackagingguide.info, Node: Specification, Next: Registered VCS, Up: Recording the Direct URL Origin of installed distributions + +5.1.9.1 Specification +..................... + +The ‘direct_url.json’ file MUST be created in the ‘*.dist-info’ +directory by installers when installing a distribution from a +requirement specifying a direct URL reference (including a VCS URL). + +This file MUST NOT be created when installing a distribution from an +other type of requirement (i.e. name plus version specifier). + +This JSON file MUST be a dictionary, compliant with RFC 8259(1) and +UTF-8 encoded. + +If present, it MUST contain at least two fields. The first one is +‘url’, with type ‘string’. Depending on what ‘url’ refers to, the +second field MUST be one of ‘vcs_info’ (if ‘url’ is a VCS reference), +‘archive_info’ (if ‘url’ is a source archives or a wheel), or ‘dir_info’ +(if ‘url’ is a local directory). These info fields have a (possibly +empty) subdictionary as value, with the possible keys defined below. + +‘url’ MUST be stripped of any sensitive authentication information, for +security reasons. + +The user:password section of the URL MAY however be composed of +environment variables, matching the following regular expression: + + \$\{[A-Za-z0-9-_]+\}(:\$\{[A-Za-z0-9-_]+\})? + +Additionally, the user:password section of the URL MAY be a well-known, +non security sensitive string. A typical example is ‘git’ in the case +of an URL such as ‘ssh://git@gitlab.com/user/repo’. + +When ‘url’ refers to a VCS repository, the ‘vcs_info’ key MUST be +present as a dictionary with the following keys: + + - A ‘vcs’ key (type ‘string’) MUST be present, containing the name of + the VCS (i.e. one of ‘git’, ‘hg’, ‘bzr’, ‘svn’). Other VCS’s + SHOULD be registered by writing a PEP to amend this specification. + The ‘url’ value MUST be compatible with the corresponding VCS, so + an installer can hand it off without transformation to a + checkout/download command of the VCS. + + - A ‘requested_revision’ key (type ‘string’) MAY be present naming a + branch/tag/ref/commit/revision/etc (in a format compatible with the + VCS) to install. + + - A ‘commit_id’ key (type ‘string’) MUST be present, containing the + exact commit/revision number that was installed. If the VCS + supports commit-hash based revision identifiers, such commit-hash + MUST be used as ‘commit_id’ in order to reference the immutable + version of the source code that was installed. + +When ‘url’ refers to a source archive or a wheel, the ‘archive_info’ key +MUST be present as a dictionary with the following key: + + - A ‘hash’ key (type ‘string’) SHOULD be present, with value + ‘=’. It is RECOMMENDED that only + hashes which are unconditionally provided by the latest version of + the standard library’s ‘hashlib’ module be used for source archive + hashes. At time of writing, that list consists of ‘md5’, ‘sha1’, + ‘sha224’, ‘sha256’, ‘sha384’, and ‘sha512’. + +When ‘url’ refers to a local directory, the ‘dir_info’ key MUST be +present as a dictionary with the following key: + + - ‘editable’ (type: ‘boolean’): ‘true’ if the distribution was + installed in editable mode, ‘false’ otherwise. If absent, default + to ‘false’. + +When ‘url’ refers to a local directory, it MUST have the ‘file’ sheme +and be compliant with RFC 8089(2). In particular, the path component +must be absolute. Symbolic links SHOULD be preserved when making +relative paths absolute. + + Note: When the requested URL has the ‘file://’ scheme and points to + a local directory that happens to contain a VCS checkout, + installers MUST NOT attempt to infer any VCS information and + therefore MUST NOT output any VCS related information (such as + ‘vcs_info’) in ‘direct_url.json’. + +A top-level ‘subdirectory’ field MAY be present containing a directory +path, relative to the root of the VCS repository, source archive or +local directory, to specify where ‘pyproject.toml’ or ‘setup.py’ is +located. + + Note: As a general rule, installers should as much as possible + preserve the information that was provided in the requested URL + when generating ‘direct_url.json’. For example user:password + environment variables should be preserved and ‘requested_revision’ + should reflect the revision that was provided in the requested URL + as faithfully as possible. This information is however `enriched' + with more precise data, such as ‘commit_id’. + + ---------- Footnotes ---------- + + (1) https://tools.ietf.org/html/rfc8259.html + + (2) https://tools.ietf.org/html/rfc8089.html + + +File: pythonpackagingguide.info, Node: Registered VCS, Next: Examples, Prev: Specification, Up: Recording the Direct URL Origin of installed distributions + +5.1.9.2 Registered VCS +...................... + +This section lists the registered VCS’s; expanded, VCS-specific +information on how to use the ‘vcs’, ‘requested_revision’, and other +fields of ‘vcs_info’; and in some cases additional VCS-specific fields. +Tools MAY support other VCS’s although it is RECOMMENDED to register +them by writing a PEP to amend this specification. The ‘vcs’ field +SHOULD be the command name (lowercased). Additional fields that would +be necessary to support such VCS SHOULD be prefixed with the VCS command +name. + +* Menu: + +* Git:: +* Mercurial:: +* Bazaar:: +* Subversion:: + + +File: pythonpackagingguide.info, Node: Git, Next: Mercurial, Up: Registered VCS + +5.1.9.3 Git +........... + +Home page + + ‘https://git-scm.com/’ + +vcs command + + git + +‘vcs’ field + + git + +‘requested_revision’ field + + A tag name, branch name, Git ref, commit hash, shortened commit + hash, or other commit-ish. + +‘commit_id’ field + + A commit hash (40 hexadecimal characters sha1). + + Note: Installers can use the ‘git show-ref’ and ‘git symbolic-ref’ + commands to determine if the ‘requested_revision’ corresponds to a + Git ref. In turn, a ref beginning with ‘refs/tags/’ corresponds to + a tag, and a ref beginning with ‘refs/remotes/origin/’ after + cloning corresponds to a branch. + + +File: pythonpackagingguide.info, Node: Mercurial, Next: Bazaar, Prev: Git, Up: Registered VCS + +5.1.9.4 Mercurial +................. + +Home page + + ‘https://www.mercurial-scm.org/’ + +vcs command + + hg + +‘vcs’ field + + hg + +‘requested_revision’ field + + A tag name, branch name, changeset ID, shortened changeset ID. + +‘commit_id’ field + + A changeset ID (40 hexadecimal characters). + + +File: pythonpackagingguide.info, Node: Bazaar, Next: Subversion, Prev: Mercurial, Up: Registered VCS + +5.1.9.5 Bazaar +.............. + +Home page + + ‘https://bazaar.canonical.com’ + +vcs command + + bzr + +‘vcs’ field + + bzr + +‘requested_revision’ field + + A tag name, branch name, revision id. + +‘commit_id’ field + + A revision id. + + +File: pythonpackagingguide.info, Node: Subversion, Prev: Bazaar, Up: Registered VCS + +5.1.9.6 Subversion +.................. + +Home page + + ‘https://subversion.apache.org/’ + +vcs command + + svn + +‘vcs’ field + + svn + +‘requested_revision’ field + + ‘requested_revision’ must be compatible with ‘svn checkout’ + ‘--revision’ option. In Subversion, branch or tag is part of + ‘url’. + +‘commit_id’ field + + Since Subversion does not support globally unique identifiers, this + field is the Subversion revision number in the corresponding + repository. + + +File: pythonpackagingguide.info, Node: Examples, Prev: Registered VCS, Up: Recording the Direct URL Origin of installed distributions + +5.1.9.7 Examples +................ + +* Menu: + +* Example direct_url.json: Example direct_url json. +* Example pip commands and their effect on direct_url.json: Example pip commands and their effect on direct_url json. + + +File: pythonpackagingguide.info, Node: Example direct_url json, Next: Example pip commands and their effect on direct_url json, Up: Examples + +5.1.9.8 Example direct_url.json +............................... + +Source archive: + + { + "url": "https://github.com/pypa/pip/archive/1.3.1.zip", + "archive_info": { + "hash": "sha256=2dc6b5a470a1bde68946f263f1af1515a2574a150a30d6ce02c6ff742fcc0db8" + } + } + +Git URL with tag and commit-hash: + + { + "url": "https://github.com/pypa/pip.git", + "vcs_info": { + "vcs": "git", + "requested_revision": "1.3.1", + "commit_id": "7921be1537eac1e97bc40179a57f0349c2aee67d" + } + } + +Local directory: + + { + "url": "file:///home/user/project", + "dir_info": {} + } + +Local directory installed in editable mode: + + { + "url": "file:///home/user/project", + "dir_info": { + "editable": true + } + } + + +File: pythonpackagingguide.info, Node: Example pip commands and their effect on direct_url json, Prev: Example direct_url json, Up: Examples + +5.1.9.9 Example pip commands and their effect on direct_url.json +................................................................ + +Commands that generate a ‘direct_url.json’: + + * ‘pip install https://example.com/app-1.0.tgz’ + + * ‘pip install https://example.com/app-1.0.whl’ + + * ‘pip install + "git+https://example.com/repo/app.git#egg=app&subdirectory=setup"’ + + * ‘pip install ./app’ + + * ‘pip install file:///home/user/app’ + + * ‘pip install --editable + "git+https://example.com/repo/app.git#egg=app&subdirectory=setup"’ + (in which case, ‘url’ will be the local directory where the git + repository has been cloned to, and ‘dir_info’ will be present with + ‘"editable": true’ and no ‘vcs_info’ will be set) + + * ‘pip install -e ./app’ + +Commands that `do not' generate a ‘direct_url.json’ + + * ‘pip install app’ + + * ‘pip install app --no-index --find-links https://example.com/’ + + +File: pythonpackagingguide.info, Node: Package Distribution File Formats, Next: Package Index Interfaces, Prev: Package Distribution Metadata, Up: PyPA specifications + +5.2 Package Distribution File Formats +===================================== + +* Menu: + +* Source distribution format:: +* Binary distribution format:: + + +File: pythonpackagingguide.info, Node: Source distribution format, Next: Binary distribution format, Up: Package Distribution File Formats + +5.2.1 Source distribution format +-------------------------------- + +The current standard format of source distribution format is identified +by the presence of a ‘pyproject.toml’ file in the distribution archive. +The layout of such a distribution was originally specified in PEP 517(1) +and is formally documented here. + +There is also the legacy source distribution format, implicitly defined +by the behaviour of ‘distutils’ module in the standard library, when +executing ‘setup.py sdist’. This document does not attempt to +standardise this format, except to note that if a legacy source +distribution contains a ‘PKG-INFO’ file using metadata version 2.2 or +later, then it MUST follow the rules applicable to source distributions +defined in the metadata specification. + +Source distributions are also known as `sdists' for short. + +* Menu: + +* Source trees:: +* Source distribution file name:: +* Source distribution file format:: + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0517 + + +File: pythonpackagingguide.info, Node: Source trees, Next: Source distribution file name, Up: Source distribution format + +5.2.1.1 Source trees +.................... + +A `source tree' is a collection of files and directories – like a +version control system checkout – which contains a ‘pyproject.toml’ file +that can be use to build a source distribution from the contained files +and directories. PEP 517(1) and PEP 518(2) specify what is required to +meet the definition of what ‘pyproject.toml’ must contain for something +to be deemed a source tree. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0517 + + (2) https://www.python.org/dev/peps/pep-0518 + + +File: pythonpackagingguide.info, Node: Source distribution file name, Next: Source distribution file format, Prev: Source trees, Up: Source distribution format + +5.2.1.2 Source distribution file name +..................................... + +The file name of a sdist is not currently standardised, although the `de +facto' form is ‘{name}-{version}.tar.gz’, where ‘{name}’ is the +canonicalized form of the project name (see PEP 503(1) for the +canonicalization rules) with ‘-’ characters replaced with ‘_’, and +‘{version}’ is the canonicalized form of the project version (see *note +Version specifiers: 1de.). + +The name and version components of the filename MUST match the values +stored in the metadata contained in the file. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0503 + + +File: pythonpackagingguide.info, Node: Source distribution file format, Prev: Source distribution file name, Up: Source distribution format + +5.2.1.3 Source distribution file format +....................................... + +A ‘.tar.gz’ source distribution (sdist) contains a single top-level +directory called ‘{name}-{version}’ (e.g. ‘foo-1.0’), containing the +source files of the package. The name and version MUST match the +metadata stored in the file. This directory must also contain a +‘pyproject.toml’ in the format defined in *note Declaring build system +dependencies: 1e3, and a ‘PKG-INFO’ file containing metadata in the +format described in the *note Core metadata specifications: 106. +specification. The metadata MUST conform to at least version 2.2 of the +metadata specification. + +No other content of a sdist is required or defined. Build systems can +store whatever information they need in the sdist to build the project. + +The tarball should use the modern POSIX.1-2001 pax tar format, which +specifies UTF-8 based file names. + + +File: pythonpackagingguide.info, Node: Binary distribution format, Prev: Source distribution format, Up: Package Distribution File Formats + +5.2.2 Binary distribution format +-------------------------------- + +The binary distribution format (*note wheel: d.) was originally defined +in PEP 427(1). The current version of the specification is here. + +* Menu: + +* Abstract:: +* PEP Acceptance:: +* Rationale:: +* Details:: +* FAQ:: +* Changes:: +* References: References<2>. +* Appendix:: +* Copyright:: + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0427 + + +File: pythonpackagingguide.info, Node: Abstract, Next: PEP Acceptance, Up: Binary distribution format + +5.2.2.1 Abstract +................ + +This PEP describes a built-package format for Python called “wheel”. + +A wheel is a ZIP-format archive with a specially formatted file name and +the ‘.whl’ extension. It contains a single distribution nearly as it +would be installed according to PEP 376 with a particular installation +scheme. Although a specialized installer is recommended, a wheel file +may be installed by simply unpacking into site-packages with the +standard ‘unzip’ tool while preserving enough information to spread its +contents out onto their final paths at any later time. + + +File: pythonpackagingguide.info, Node: PEP Acceptance, Next: Rationale, Prev: Abstract, Up: Binary distribution format + +5.2.2.2 PEP Acceptance +...................... + +This PEP was accepted, and the defined wheel version updated to 1.0, by +Nick Coghlan on 16th February, 2013 (1) + + ---------- Footnotes ---------- + + (1) (1) PEP acceptance +(‘https://mail.python.org/pipermail/python-dev/2013-February/124103.html’) + + +File: pythonpackagingguide.info, Node: Rationale, Next: Details, Prev: PEP Acceptance, Up: Binary distribution format + +5.2.2.3 Rationale +................. + +Python needs a package format that is easier to install than sdist. +Python’s sdist packages are defined by and require the distutils and +setuptools build systems, running arbitrary code to build-and-install, +and re-compile, code just so it can be installed into a new virtualenv. +This system of conflating build-install is slow, hard to maintain, and +hinders innovation in both build systems and installers. + +Wheel attempts to remedy these problems by providing a simpler interface +between the build system and the installer. The wheel binary package +format frees installers from having to know about the build system, +saves time by amortizing compile time over many installations, and +removes the need to install a build system in the target environment. + + +File: pythonpackagingguide.info, Node: Details, Next: FAQ, Prev: Rationale, Up: Binary distribution format + +5.2.2.4 Details +............... + +* Menu: + +* Installing a wheel ‘distribution-1.0-py32-none-any.whl’: Installing a wheel ‘distribution-1 0-py32-none-any whl’. +* File Format:: +* Signed wheel files:: +* Comparison to .egg: Comparison to egg. + + +File: pythonpackagingguide.info, Node: Installing a wheel ‘distribution-1 0-py32-none-any whl’, Next: File Format, Up: Details + +5.2.2.5 Installing a wheel ‘distribution-1.0-py32-none-any.whl’ +............................................................... + +Wheel installation notionally consists of two phases: + + - Unpack. + + a. Parse ‘distribution-1.0.dist-info/WHEEL’. + + b. Check that installer is compatible with Wheel-Version. Warn + if minor version is greater, abort if major version is + greater. + + c. If Root-Is-Purelib == ‘true’, unpack archive into purelib + (site-packages). + + d. Else unpack archive into platlib (site-packages). + + - Spread. + + a. Unpacked archive includes ‘distribution-1.0.dist-info/’ and + (if there is data) ‘distribution-1.0.data/’. + + b. Move each subtree of ‘distribution-1.0.data/’ onto its + destination path. Each subdirectory of + ‘distribution-1.0.data/’ is a key into a dict of destination + directories, such as + ‘distribution-1.0.data/(purelib|platlib|headers|scripts|data)’. + The initially supported paths are taken from + ‘distutils.command.install’. + + c. If applicable, update scripts starting with ‘#!python’ to + point to the correct interpreter. + + d. Update ‘distribution-1.0.dist-info/RECORD’ with the installed + paths. + + e. Remove empty ‘distribution-1.0.data’ directory. + + f. Compile any installed .py to .pyc. (Uninstallers should be + smart enough to remove .pyc even if it is not mentioned in + RECORD.) + +* Menu: + +* Recommended installer features:: +* Recommended archiver features:: + + +File: pythonpackagingguide.info, Node: Recommended installer features, Next: Recommended archiver features, Up: Installing a wheel ‘distribution-1 0-py32-none-any whl’ + +5.2.2.6 Recommended installer features +...................................... + +Rewrite ‘#!python’. + + In wheel, scripts are packaged in + ‘{distribution}-{version}.data/scripts/’. If the first line of a + file in ‘scripts/’ starts with exactly ‘b'#!python'’, rewrite to + point to the correct interpreter. Unix installers may need to add + the +x bit to these files if the archive was created on Windows. + + The ‘b'#!pythonw'’ convention is allowed. ‘b'#!pythonw'’ indicates + a GUI script instead of a console script. + +Generate script wrappers. + + In wheel, scripts packaged on Unix systems will certainly not have + accompanying .exe wrappers. Windows installers may want to add + them during install. + + +File: pythonpackagingguide.info, Node: Recommended archiver features, Prev: Recommended installer features, Up: Installing a wheel ‘distribution-1 0-py32-none-any whl’ + +5.2.2.7 Recommended archiver features +..................................... + +Place ‘.dist-info’ at the end of the archive. + + Archivers are encouraged to place the ‘.dist-info’ files physically + at the end of the archive. This enables some potentially + interesting ZIP tricks including the ability to amend the metadata + without rewriting the entire archive. + + +File: pythonpackagingguide.info, Node: File Format, Next: Signed wheel files, Prev: Installing a wheel ‘distribution-1 0-py32-none-any whl’, Up: Details + +5.2.2.8 File Format +................... + +* Menu: + +* File name convention:: +* Escaping and Unicode:: +* File contents:: + + +File: pythonpackagingguide.info, Node: File name convention, Next: Escaping and Unicode, Up: File Format + +5.2.2.9 File name convention +............................ + +The wheel filename is ‘{distribution}-{version}(-{build tag})?-{python +tag}-{abi tag}-{platform tag}.whl’. + +distribution + + Distribution name, e.g. ‘django’, ‘pyramid’. + +version + + Distribution version, e.g. 1.0. + +build tag + + Optional build number. Must start with a digit. Acts as a + tie-breaker if two wheel file names are the same in all other + respects (i.e. name, version, and other tags). Sort as an empty + tuple if unspecified, else sort as a two-item tuple with the first + item being the initial digits as an ‘int’, and the second item + being the remainder of the tag as a ‘str’. + +language implementation and version tag + + E.g. ‘py27’, ‘py2’, ‘py3’. + +abi tag + + E.g. ‘cp33m’, ‘abi3’, ‘none’. + +platform tag + + E.g. ‘linux_x86_64’, ‘any’. + +For example, ‘distribution-1.0-1-py27-none-any.whl’ is the first build +of a package called ‘distribution’, and is compatible with Python 2.7 +(any Python 2.7 implementation), with no ABI (pure Python), on any CPU +architecture. + +The last three components of the filename before the extension are +called “compatibility tags.” The compatibility tags express the +package’s basic interpreter requirements and are detailed in PEP 425. + + +File: pythonpackagingguide.info, Node: Escaping and Unicode, Next: File contents, Prev: File name convention, Up: File Format + +5.2.2.10 Escaping and Unicode +............................. + +As the components of the filename are separated by a dash (‘-’, +HYPHEN-MINUS), this character cannot appear within any component. This +is handled as follows: + + - In distribution names, any run of ‘-_.’ characters (HYPHEN-MINUS, + LOW LINE and FULL STOP) should be replaced with ‘_’ (LOW LINE), and + uppercase characters should be replaced with corresponding + lowercase ones. This is equivalent to PEP 503(1) normalisation + followed by replacing ‘-’ with ‘_’. Tools consuming wheels must be + prepared to accept ‘.’ (FULL STOP) and uppercase letters, however, + as these were allowed by an earlier version of this specification. + + - Version numbers should be normalised according to PEP 440(2). + Normalised version numbers cannot contain ‘-’. + + - The remaining components may not contain ‘-’ characters, so no + escaping is necessary. + +Tools producing wheels should verify that the filename components do not +contain ‘-’, as the resulting file may not be processed correctly if +they do. + +The archive filename is Unicode. It will be some time before the tools +are updated to support non-ASCII filenames, but they are supported in +this specification. + +The filenames `inside' the archive are encoded as UTF-8. Although some +ZIP clients in common use do not properly display UTF-8 filenames, the +encoding is supported by both the ZIP specification and Python’s +‘zipfile’. + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0503 + + (2) https://www.python.org/dev/peps/pep-0440 + + +File: pythonpackagingguide.info, Node: File contents, Prev: Escaping and Unicode, Up: File Format + +5.2.2.11 File contents +...................... + +The contents of a wheel file, where {distribution} is replaced with the +name of the package, e.g. ‘beaglevote’ and {version} is replaced with +its version, e.g. ‘1.0.0’, consist of: + + 1. ‘/’, the root of the archive, contains all files to be installed in + ‘purelib’ or ‘platlib’ as specified in ‘WHEEL’. ‘purelib’ and + ‘platlib’ are usually both ‘site-packages’. + + 2. ‘{distribution}-{version}.dist-info/’ contains metadata. + + 3. ‘{distribution}-{version}.data/’ contains one subdirectory for each + non-empty install scheme key not already covered, where the + subdirectory name is an index into a dictionary of install paths + (e.g. ‘data’, ‘scripts’, ‘headers’, ‘purelib’, ‘platlib’). + + 4. Python scripts must appear in ‘scripts’ and begin with exactly + ‘b'#!python'’ in order to enjoy script wrapper generation and + ‘#!python’ rewriting at install time. They may have any or no + extension. + + 5. ‘{distribution}-{version}.dist-info/METADATA’ is Metadata version + 1.1 or greater format metadata. + + 6. ‘{distribution}-{version}.dist-info/WHEEL’ is metadata about the + archive itself in the same basic key: value format: + + Wheel-Version: 1.0 + Generator: bdist_wheel 1.0 + Root-Is-Purelib: true + Tag: py2-none-any + Tag: py3-none-any + Build: 1 + + 7. ‘Wheel-Version’ is the version number of the Wheel specification. + + 8. ‘Generator’ is the name and optionally the version of the software + that produced the archive. + + 9. ‘Root-Is-Purelib’ is true if the top level directory of the archive + should be installed into purelib; otherwise the root should be + installed into platlib. + + 10. ‘Tag’ is the wheel’s expanded compatibility tags; in the example + the filename would contain ‘py2.py3-none-any’. + + 11. ‘Build’ is the build number and is omitted if there is no build + number. + + 12. A wheel installer should warn if Wheel-Version is greater than the + version it supports, and must fail if Wheel-Version has a greater + major version than the version it supports. + + 13. Wheel, being an installation format that is intended to work + across multiple versions of Python, does not generally include .pyc + files. + + 14. Wheel does not contain setup.py or setup.cfg. + +This version of the wheel specification is based on the distutils +install schemes and does not define how to install files to other +locations. The layout offers a superset of the functionality provided +by the existing wininst and egg binary formats. + +* Menu: + +* The .dist-info directory: The dist-info directory<2>. +* The .data directory: The data directory. + + +File: pythonpackagingguide.info, Node: The dist-info directory<2>, Next: The data directory, Up: File contents + +5.2.2.12 The .dist-info directory +................................. + + 1. Wheel .dist-info directories include at a minimum METADATA, WHEEL, + and RECORD. + + 2. METADATA is the package metadata, the same format as PKG-INFO as + found at the root of sdists. + + 3. WHEEL is the wheel metadata specific to a build of the package. + + 4. RECORD is a list of (almost) all the files in the wheel and their + secure hashes. Unlike PEP 376, every file except RECORD, which + cannot contain a hash of itself, must include its hash. The hash + algorithm must be sha256 or better; specifically, md5 and sha1 are + not permitted, as signed wheel files rely on the strong hashes in + RECORD to validate the integrity of the archive. + + 5. PEP 376’s INSTALLER and REQUESTED are not included in the archive. + + 6. RECORD.jws is used for digital signatures. It is not mentioned in + RECORD. + + 7. RECORD.p7s is allowed as a courtesy to anyone who would prefer to + use S/MIME signatures to secure their wheel files. It is not + mentioned in RECORD. + + 8. During extraction, wheel installers verify all the hashes in RECORD + against the file contents. Apart from RECORD and its signatures, + installation will fail if any file in the archive is not both + mentioned and correctly hashed in RECORD. + + +File: pythonpackagingguide.info, Node: The data directory, Prev: The dist-info directory<2>, Up: File contents + +5.2.2.13 The .data directory +............................ + +Any file that is not normally installed inside site-packages goes into +the .data directory, named as the .dist-info directory but with the +.data/ extension: + + distribution-1.0.dist-info/ + + distribution-1.0.data/ + +The .data directory contains subdirectories with the scripts, headers, +documentation and so forth from the distribution. During installation +the contents of these subdirectories are moved onto their destination +paths. + + +File: pythonpackagingguide.info, Node: Signed wheel files, Next: Comparison to egg, Prev: File Format, Up: Details + +5.2.2.14 Signed wheel files +........................... + +Wheel files include an extended RECORD that enables digital signatures. +PEP 376’s RECORD is altered to include a secure hash +‘digestname=urlsafe_b64encode_nopad(digest)’ (urlsafe base64 encoding +with no trailing = characters) as the second column instead of an +md5sum. All possible entries are hashed, including any generated files +such as .pyc files, but not RECORD which cannot contain its own hash. +For example: + + file.py,sha256=AVTFPZpEKzuHr7OvQZmhaU3LvwKz06AJw8mT\_pNh2yI,3144 + distribution-1.0.dist-info/RECORD,, + +The signature file(s) RECORD.jws and RECORD.p7s are not mentioned in +RECORD at all since they can only be added after RECORD is generated. +Every other file in the archive must have a correct hash in RECORD or +the installation will fail. + +If JSON web signatures are used, one or more JSON Web Signature JSON +Serialization (JWS-JS) signatures is stored in a file RECORD.jws +adjacent to RECORD. JWS is used to sign RECORD by including the SHA-256 +hash of RECORD as the signature’s JSON payload: + + { "hash": "sha256=ADD-r2urObZHcxBW3Cr-vDCu5RJwT4CaRTHiFmbcIYY" } + +(The hash value is the same format used in RECORD.) + +If RECORD.p7s is used, it must contain a detached S/MIME format +signature of RECORD. + +A wheel installer is not required to understand digital signatures but +MUST verify the hashes in RECORD against the extracted file contents. +When the installer checks file hashes against RECORD, a separate +signature checker only needs to establish that RECORD matches the +signature. + +See + + - ‘https://datatracker.ietf.org/doc/html/rfc7515’ + + - + ‘https://tools.ietf.org/id/draft-jones-json-web-signature-json-serialization-01.html’ + + - ‘https://datatracker.ietf.org/doc/html/rfc7517’ + + - + ‘https://tools.ietf.org/id/draft-jones-jose-json-private-key-01.html’ + + +File: pythonpackagingguide.info, Node: Comparison to egg, Prev: Signed wheel files, Up: Details + +5.2.2.15 Comparison to .egg +........................... + + 1. Wheel is an installation format; egg is importable. Wheel archives + do not need to include .pyc and are less tied to a specific Python + version or implementation. Wheel can install (pure Python) + packages built with previous versions of Python so you don’t always + have to wait for the packager to catch up. + + 2. Wheel uses .dist-info directories; egg uses .egg-info. Wheel is + compatible with the new world of Python packaging and the new + concepts it brings. + + 3. Wheel has a richer file naming convention for today’s + multi-implementation world. A single wheel archive can indicate + its compatibility with a number of Python language versions and + implementations, ABIs, and system architectures. Historically the + ABI has been specific to a CPython release, wheel is ready for the + stable ABI. + + 4. Wheel is lossless. The first wheel implementation bdist_wheel + always generates egg-info, and then converts it to a .whl. It is + also possible to convert existing eggs and bdist_wininst + distributions. + + 5. Wheel is versioned. Every wheel file contains the version of the + wheel specification and the implementation that packaged it. + Hopefully the next migration can simply be to Wheel 2.0. + + 6. Wheel is a reference to the other Python. + + +File: pythonpackagingguide.info, Node: FAQ, Next: Changes, Prev: Details, Up: Binary distribution format + +5.2.2.16 FAQ +............ + +* Menu: + +* Wheel defines a .data directory. Should I put all my data there?: Wheel defines a data directory Should I put all my data there?. +* Why does wheel include attached signatures?:: +* Why does wheel allow JWS signatures?:: +* Why does wheel also allow S/MIME signatures?:: +* What’s the deal with “purelib” vs. “platlib”?: What’s the deal with “purelib” vs “platlib”?. +* Is it possible to import Python code directly from a wheel file?:: + + +File: pythonpackagingguide.info, Node: Wheel defines a data directory Should I put all my data there?, Next: Why does wheel include attached signatures?, Up: FAQ + +5.2.2.17 Wheel defines a .data directory. Should I put all my data there? +......................................................................... + + This specification does not have an opinion on how you should + organize your code. The .data directory is just a place for any + files that are not normally installed inside ‘site-packages’ or on + the PYTHONPATH. In other words, you may continue to use + ‘pkgutil.get_data(package, resource)’ even though `those' files + will usually not be distributed in `wheel’s' ‘.data’ directory. + + +File: pythonpackagingguide.info, Node: Why does wheel include attached signatures?, Next: Why does wheel allow JWS signatures?, Prev: Wheel defines a data directory Should I put all my data there?, Up: FAQ + +5.2.2.18 Why does wheel include attached signatures? +.................................................... + + Attached signatures are more convenient than detached signatures + because they travel with the archive. Since only the individual + files are signed, the archive can be recompressed without + invalidating the signature or individual files can be verified + without having to download the whole archive. + + +File: pythonpackagingguide.info, Node: Why does wheel allow JWS signatures?, Next: Why does wheel also allow S/MIME signatures?, Prev: Why does wheel include attached signatures?, Up: FAQ + +5.2.2.19 Why does wheel allow JWS signatures? +............................................. + + The JOSE specifications of which JWS is a part are designed to be + easy to implement, a feature that is also one of wheel’s primary + design goals. JWS yields a useful, concise pure-Python + implementation. + + +File: pythonpackagingguide.info, Node: Why does wheel also allow S/MIME signatures?, Next: What’s the deal with “purelib” vs “platlib”?, Prev: Why does wheel allow JWS signatures?, Up: FAQ + +5.2.2.20 Why does wheel also allow S/MIME signatures? +..................................................... + + S/MIME signatures are allowed for users who need or want to use + existing public key infrastructure with wheel. + + Signed packages are only a basic building block in a secure package + update system. Wheel only provides the building block. + + +File: pythonpackagingguide.info, Node: What’s the deal with “purelib” vs “platlib”?, Next: Is it possible to import Python code directly from a wheel file?, Prev: Why does wheel also allow S/MIME signatures?, Up: FAQ + +5.2.2.21 What’s the deal with “purelib” vs. “platlib”? +...................................................... + + Wheel preserves the “purelib” vs. “platlib” distinction, which is + significant on some platforms. For example, Fedora installs pure + Python packages to ‘/usr/lib/pythonX.Y/site-packages’ and platform + dependent packages to ‘/usr/lib64/pythonX.Y/site-packages’. + + A wheel with “Root-Is-Purelib: false” with all its files in + ‘{name}-{version}.data/purelib’ is equivalent to a wheel with + “Root-Is-Purelib: true” with those same files in the root, and it + is legal to have files in both the “purelib” and “platlib” + categories. + + In practice a wheel should have only one of “purelib” or “platlib” + depending on whether it is pure Python or not and those files + should be at the root with the appropriate setting given for + “Root-is-purelib”. + + +File: pythonpackagingguide.info, Node: Is it possible to import Python code directly from a wheel file?, Prev: What’s the deal with “purelib” vs “platlib”?, Up: FAQ + +5.2.2.22 Is it possible to import Python code directly from a wheel file? +......................................................................... + + Technically, due to the combination of supporting installation via + simple extraction and using an archive format that is compatible + with ‘zipimport’, a subset of wheel files `do' support being placed + directly on ‘sys.path’. However, while this behaviour is a natural + consequence of the format design, actually relying on it is + generally discouraged. + + Firstly, wheel `is' designed primarily as a distribution format, so + skipping the installation step also means deliberately avoiding any + reliance on features that assume full installation (such as being + able to use standard tools like ‘pip’ and ‘virtualenv’ to capture + and manage dependencies in a way that can be properly tracked for + auditing and security update purposes, or integrating fully with + the standard build machinery for C extensions by publishing header + files in the appropriate place). + + Secondly, while some Python software is written to support running + directly from a zip archive, it is still common for code to be + written assuming it has been fully installed. When that assumption + is broken by trying to run the software from a zip archive, the + failures can often be obscure and hard to diagnose (especially when + they occur in third party libraries). The two most common sources + of problems with this are the fact that importing C extensions from + a zip archive is `not' supported by CPython (since doing so is not + supported directly by the dynamic loading machinery on any + platform) and that when running from a zip archive the ‘__file__’ + attribute no longer refers to an ordinary filesystem path, but to a + combination path that includes both the location of the zip archive + on the filesystem and the relative path to the module inside the + archive. Even when software correctly uses the abstract resource + APIs internally, interfacing with external components may still + require the availability of an actual on-disk file. + + Like metaclasses, monkeypatching and metapath importers, if you’re + not already sure you need to take advantage of this feature, you + almost certainly don’t need it. If you `do' decide to use it + anyway, be aware that many projects will require a failure to be + reproduced with a fully installed package before accepting it as a + genuine bug. + + +File: pythonpackagingguide.info, Node: Changes, Next: References<2>, Prev: FAQ, Up: Binary distribution format + +5.2.2.23 Changes +................ + +Since PEP 427(1), this specification has changed as follows: + + - The rules on escaping in wheel filenames were revised, to bring + them into line with what popular tools actually do (February 2021). + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0427 + + +File: pythonpackagingguide.info, Node: References<2>, Next: Appendix, Prev: Changes, Up: Binary distribution format + +5.2.2.24 References +................... + + +File: pythonpackagingguide.info, Node: Appendix, Next: Copyright, Prev: References<2>, Up: Binary distribution format + +5.2.2.25 Appendix +................. + +Example urlsafe-base64-nopad implementation: + + # urlsafe-base64-nopad for Python 3 + import base64 + + def urlsafe_b64encode_nopad(data): + return base64.urlsafe_b64encode(data).rstrip(b'=') + + def urlsafe_b64decode_nopad(data): + pad = b'=' * (4 - (len(data) & 3)) + return base64.urlsafe_b64decode(data + pad) + + +File: pythonpackagingguide.info, Node: Copyright, Prev: Appendix, Up: Binary distribution format + +5.2.2.26 Copyright +.................. + +This document has been placed into the public domain. + + +File: pythonpackagingguide.info, Node: Package Index Interfaces, Prev: Package Distribution File Formats, Up: PyPA specifications + +5.3 Package Index Interfaces +============================ + +* Menu: + +* The .pypirc file: The pypirc file. +* Simple repository API:: + + +File: pythonpackagingguide.info, Node: The pypirc file, Next: Simple repository API, Up: Package Index Interfaces + +5.3.1 The ‘.pypirc’ file +------------------------ + +A ‘.pypirc’ file allows you to define the configuration for *note +package indexes: e9. (referred to here as “repositories”), so that you +don’t have to enter the URL, username, or password whenever you upload a +package with *note twine: 6d. or *note flit: 60. + +The format (originally defined by the *note distutils: be. package) is: + + [distutils] + index-servers = + first-repository + second-repository + + [first-repository] + repository = + username = + password = + + [second-repository] + repository = + username = + password = + +The ‘distutils’ section defines an ‘index-servers’ field that lists the +name of all sections describing a repository. + +Each section describing a repository defines three fields: + + - ‘repository’: The URL of the repository. + + - ‘username’: The registered username on the repository. + + - ‘password’: The password that will used to authenticate the + username. + + Warning: Be aware that this stores your password in plain text. + For better security, consider an alternative like keyring(1), + setting environment variables, or providing the password on the + command line. + + Otherwise, set the permissions on ‘.pypirc’ so that only you can + view or modify it. For example, on Linux or macOS, run: + + chmod 600 ~/.pypirc + +* Menu: + +* Common configurations:: + + ---------- Footnotes ---------- + + (1) https://pypi.org/project/keyring/ + + +File: pythonpackagingguide.info, Node: Common configurations, Up: The pypirc file + +5.3.1.1 Common configurations +............................. + + Note: These examples apply to *note twine: 6d. Other projects + (e.g. *note flit: 60.) also use ‘.pypirc’, but with different + defaults. Please refer to each project’s documentation for more + details and usage instructions. + +Twine’s default configuration mimics a ‘.pypirc’ with repository +sections for PyPI and TestPyPI: + + [distutils] + index-servers = + pypi + testpypi + + [pypi] + repository = https://upload.pypi.org/legacy/ + + [testpypi] + repository = https://test.pypi.org/legacy/ + +Twine will add additional configuration from ‘$HOME/.pypirc’, the +command line, and environment variables to this default configuration. + +* Menu: + +* Using a PyPI token:: +* Using another package index:: + + +File: pythonpackagingguide.info, Node: Using a PyPI token, Next: Using another package index, Up: Common configurations + +5.3.1.2 Using a PyPI token +.......................... + +To set your API token(1) for PyPI, you can create a ‘$HOME/.pypirc’ +similar to: + + [pypi] + username = __token__ + password = + +For *note TestPyPI: f1, add a ‘[testpypi]’ section, using the API token +from your TestPyPI account. + + ---------- Footnotes ---------- + + (1) https://pypi.org/help/#apitoken + + +File: pythonpackagingguide.info, Node: Using another package index, Prev: Using a PyPI token, Up: Common configurations + +5.3.1.3 Using another package index +................................... + +To configure an additional repository, you’ll need to redefine the +‘index-servers’ field to include the repository name. Here is a +complete example of a ‘$HOME/.pypirc’ for PyPI, TestPyPI, and a private +repository: + + [distutils] + index-servers = + pypi + testpypi + private-repository + + [pypi] + username = __token__ + password = + + [testpypi] + username = __token__ + password = + + [private-repository] + repository = + username = + password = + + Warning: Instead of using the ‘password’ field, consider saving + your API tokens and passwords securely using keyring(1) (which is + installed by Twine): + + keyring set https://upload.pypi.org/legacy/ __token__ + keyring set https://test.pypi.org/legacy/ __token__ + keyring set + + ---------- Footnotes ---------- + + (1) https://pypi.org/project/keyring/ + + +File: pythonpackagingguide.info, Node: Simple repository API, Prev: The pypirc file, Up: Package Index Interfaces + +5.3.2 Simple repository API +--------------------------- + +The current interface for querying available package versions and +retrieving packages from an index server is defined in PEP 503(1), with +the addition of “yank” support (allowing a kind of file deletion) in PEP +592(2), specifying the interface version provided by an index server in +PEP 629(3), and providing package metadata independently from a package +in PEP 658(4). + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0503 + + (2) https://www.python.org/dev/peps/pep-0592 + + (3) https://www.python.org/dev/peps/pep-0629 + + (4) https://www.python.org/dev/peps/pep-0658 + + +File: pythonpackagingguide.info, Node: Project Summaries, Next: Glossary, Prev: PyPA specifications, Up: Top + +6 Project Summaries +******************* + +Summaries and links for the most relevant projects in the space of +Python installation and packaging. + +* Menu: + +* PyPA Projects:: +* Non-PyPA Projects:: +* Standard Library Projects:: + + +File: pythonpackagingguide.info, Node: PyPA Projects, Next: Non-PyPA Projects, Up: Project Summaries + +6.1 PyPA Projects +================= + +* Menu: + +* bandersnatch:: +* build:: +* cibuildwheel:: +* distlib:: +* flit:: +* hatch:: +* packaging:: +* pip:: +* Pipenv:: +* Pipfile:: +* pipx:: +* Python Packaging User Guide: Python Packaging User Guide<2>. +* readme_renderer:: +* setuptools:: +* trove-classifiers:: +* twine:: +* virtualenv: virtualenv<2>. +* Warehouse:: +* wheel:: + + +File: pythonpackagingguide.info, Node: bandersnatch, Next: build, Up: PyPA Projects + +6.1.1 bandersnatch +------------------ + +Issues(1) | GitHub(2) | PyPI(3) + +‘bandersnatch’ is a PyPI mirroring client designed to efficiently create +a complete mirror of the contents of PyPI. Organizations thus save +bandwidth and latency on package downloads (especially in the context of +automated tests) and to prevent heavily loading PyPI’s Content Delivery +Network (CDN). + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/bandersnatch/issues + + (2) https://github.com/pypa/bandersnatch + + (3) https://pypi.org/project/bandersnatch + + +File: pythonpackagingguide.info, Node: build, Next: cibuildwheel, Prev: bandersnatch, Up: PyPA Projects + +6.1.2 build +----------- + +Docs(1) | Issues(2) | GitHub(3) | PyPI(4) + +‘build’ is a PEP 517(5) compatible Python package builder. It provides +a CLI to build packages, as well as a Python API. + + ---------- Footnotes ---------- + + (1) https://pypa-build.readthedocs.io/en/stable/index.html + + (2) https://github.com/pypa/build/issues + + (3) https://github.com/pypa/build + + (4) https://pypi.org/project/build + + (5) https://www.python.org/dev/peps/pep-0517 + + +File: pythonpackagingguide.info, Node: cibuildwheel, Next: distlib, Prev: build, Up: PyPA Projects + +6.1.3 cibuildwheel +------------------ + +Docs(1) | Issues(2) | GitHub(3) | PyPI(4) | Discussions(5) | Discord +#cibuildwheel(6) + +‘cibuildwheel’ is a Python package that builds *note wheels: d. for all +common platforms and Python versions on most CI systems. Also see *note +multibuild: 11b. + + ---------- Footnotes ---------- + + (1) https://cibuildwheel.readthedocs.io/ + + (2) https://github.com/pypa/cibuildwheel/issues + + (3) https://github.com/pypa/cibuildwheel + + (4) https://pypi.org/project/cibuildwheel + + (5) https://github.com/pypa/cibuildwheel/discussions + + (6) https://discord.com/invite/pypa + + +File: pythonpackagingguide.info, Node: distlib, Next: flit, Prev: cibuildwheel, Up: PyPA Projects + +6.1.4 distlib +------------- + +Docs(1) | Issues(2) | Bitbucket(3) | PyPI(4) + +‘distlib’ is a library which implements low-level functions that relate +to packaging and distribution of Python software. ‘distlib’ implements +several relevant PEPs (Python Enhancement Proposal standards) and is +useful for developers of third-party packaging tools to make and upload +binary and source *note distributions: b, achieve interoperability, +resolve dependencies, manage package resources, and do other similar +functions. + +Unlike the stricter *note packaging: 253. project (below), which +specifically implements modern Python packaging interoperability +standards, ‘distlib’ also attempts to provide reasonable fallback +behaviours when asked to handle legacy packages and metadata that +predate the modern interoperability standards and fall into the subset +of packages that are incompatible with those standards. + + ---------- Footnotes ---------- + + (1) https://distlib.readthedocs.io/en/latest/index.html + + (2) https://bitbucket.org/pypa/distlib/issues?status=new&status=open + + (3) https://bitbucket.org/pypa/distlib + + (4) https://pypi.org/project/distlib + + +File: pythonpackagingguide.info, Node: flit, Next: hatch, Prev: distlib, Up: PyPA Projects + +6.1.5 flit +---------- + +Docs(1) | Issues(2) | PyPI(3) + +Flit provides a simple way to create and upload pure Python packages and +modules to PyPI. It focuses on making the easy things easy(4) for +packaging. Flit can generate a configuration file to quickly set up a +simple project, build source distributions and wheels, and upload them +to PyPI. + +Flit uses ‘pyproject.toml’ to configure a project. Flit does not rely +on tools such as *note setuptools: 2d. to build distributions, or *note +twine: 6d. to upload them to PyPI. Flit requires Python 3, but you can +use it to distribute modules for Python 2, so long as they can be +imported on Python 3. + + ---------- Footnotes ---------- + + (1) https://flit.readthedocs.io/en/latest/ + + (2) https://github.com/pypa/flit/issues + + (3) https://pypi.org/project/flit + + (4) https://flit.readthedocs.io/en/latest/rationale.html + + +File: pythonpackagingguide.info, Node: hatch, Next: packaging, Prev: flit, Up: PyPA Projects + +6.1.6 hatch +----------- + +GitHub and Docs(1) | PyPI(2) + +Hatch is a unified command-line tool meant to conveniently manage +dependencies and environment isolation for Python developers. Python +package developers use Hatch and its build backend Hatchling to +configure, version, specify dependencies for, and publish packages to +PyPI. Its plugin system allows for easily extending functionality. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/hatch + + (2) https://pypi.org/project/hatch + + +File: pythonpackagingguide.info, Node: packaging, Next: pip, Prev: hatch, Up: PyPA Projects + +6.1.7 packaging +--------------- + +Docs(1) | Issues(2) | GitHub(3) | PyPI(4) + +Core utilities for Python packaging used by *note pip: 2b. and *note +setuptools: 2d. + +The core utilities in the packaging library handle version handling, +specifiers, markers, requirements, tags, and similar attributes and +tasks for Python packages. Most Python users rely on this library +without needing to explicitly call it; developers of the other Python +packaging, distribution, and installation tools listed here often use +its functionality to parse, discover, and otherwise handle dependency +attributes. + +This project specifically focuses on implementing the modern Python +packaging interoperability standards defined at *note PyPA +specifications: 1a1, and will report errors for sufficiently old legacy +packages that are incompatible with those standards. In contrast, the +*note distlib: 251. project is a more permissive library that attempts +to provide a plausible reading of ambiguous metadata in cases where +*note packaging: 253. will instead report on error. + + ---------- Footnotes ---------- + + (1) https://packaging.pypa.io/en/latest/index.html + + (2) https://github.com/pypa/packaging/issues + + (3) https://github.com/pypa/packaging + + (4) https://pypi.org/project/packaging + + +File: pythonpackagingguide.info, Node: pip, Next: Pipenv, Prev: packaging, Up: PyPA Projects + +6.1.8 pip +--------- + +Docs(1) | Issues(2) | GitHub(3) | PyPI(4) + +The most popular tool for installing Python packages, and the one +included with modern versions of Python. + +It provides the essential core features for finding, downloading, and +installing packages from PyPI and other Python package indexes, and can +be incorporated into a wide range of development workflows via its +command-line interface (CLI). + + ---------- Footnotes ---------- + + (1) https://pip.pypa.io/ + + (2) https://github.com/pypa/pip/issues + + (3) https://github.com/pypa/pip + + (4) https://pypi.org/project/pip/ + + +File: pythonpackagingguide.info, Node: Pipenv, Next: Pipfile, Prev: pip, Up: PyPA Projects + +6.1.9 Pipenv +------------ + +Docs(1) | Source(2) | Issues(3) | PyPI(4) + +Pipenv is a project that aims to bring the best of all packaging worlds +to the Python world. It harnesses *note Pipfile: 52, *note pip: 2b, and +*note virtualenv: 32. into one single toolchain. It features very +pretty terminal colors. + +Pipenv aims to help users manage environments, dependencies, and +imported packages on the command line. It also works well on Windows +(which other tools often underserve), makes and checkes file hashes, to +ensure compliance with hash-locked dependency specifiers, and eases +uninstallation of packages and dependencies. It is used by Python users +and system administrators, but has been less maintained since late 2018. + + ---------- Footnotes ---------- + + (1) https://pipenv.pypa.io/en/latest/ + + (2) https://github.com/pypa/pipenv + + (3) https://github.com/pypa/pipenv/issues + + (4) https://pypi.org/project/pipenv + + +File: pythonpackagingguide.info, Node: Pipfile, Next: pipx, Prev: Pipenv, Up: PyPA Projects + +6.1.10 Pipfile +-------------- + +Source(1) + +‘Pipfile’ and its sister ‘Pipfile.lock’ are a higher-level +application-centric alternative to *note pip: 2b.’s lower-level +‘requirements.txt’ file. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/pipfile + + +File: pythonpackagingguide.info, Node: pipx, Next: Python Packaging User Guide<2>, Prev: Pipfile, Up: PyPA Projects + +6.1.11 pipx +----------- + +Docs(1) | GitHub(2) | PyPI(3) + +pipx is a tool to install and run Python command-line applications +without causing dependency conflicts with other packages installed on +the system. + + ---------- Footnotes ---------- + + (1) https://pypa.github.io/pipx/ + + (2) https://github.com/pypa/pipx + + (3) https://pypi.org/project/pipx/ + + +File: pythonpackagingguide.info, Node: Python Packaging User Guide<2>, Next: readme_renderer, Prev: pipx, Up: PyPA Projects + +6.1.12 Python Packaging User Guide +---------------------------------- + +Docs(1) | Issues(2) | GitHub(3) + +This guide! + + ---------- Footnotes ---------- + + (1) https://packaging.python.org/en/latest/ + + (2) https://github.com/pypa/packaging.python.org/issues + + (3) https://github.com/pypa/packaging.python.org + + +File: pythonpackagingguide.info, Node: readme_renderer, Next: setuptools, Prev: Python Packaging User Guide<2>, Up: PyPA Projects + +6.1.13 readme_renderer +---------------------- + +GitHub and docs(1) | PyPI(2) + +‘readme_renderer’ is a library that package developers use to render +their user documentation (README) files into HTML from markup languages +such as Markdown or reStructuredText. Developers call it on its own or +via *note twine: 6d, as part of their release management process, to +check that their package descriptions will properly display on PyPI. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/readme_renderer/ + + (2) https://pypi.org/project/readme-renderer/ + + +File: pythonpackagingguide.info, Node: setuptools, Next: trove-classifiers, Prev: readme_renderer, Up: PyPA Projects + +6.1.14 setuptools +----------------- + +Docs(1) | Issues(2) | GitHub(3) | PyPI(4) + +setuptools (which includes ‘easy_install’) is a collection of +enhancements to the Python distutils that allow you to more easily build +and distribute Python *note distributions: b, especially ones that have +dependencies on other packages. + +distribute(5) was a fork of setuptools that was merged back into +setuptools (in v0.7), thereby making setuptools the primary choice for +Python packaging. + + ---------- Footnotes ---------- + + (1) https://setuptools.readthedocs.io/en/latest/ + + (2) https://github.com/pypa/setuptools/issues + + (3) https://github.com/pypa/setuptools + + (4) https://pypi.org/project/setuptools + + (5) https://pypi.org/project/distribute + + +File: pythonpackagingguide.info, Node: trove-classifiers, Next: twine, Prev: setuptools, Up: PyPA Projects + +6.1.15 trove-classifiers +------------------------ + +Issues(1) | GitHub(2) | PyPI(3) + +trove-classifiers is the canonical source for classifiers on PyPI(4), +which project maintainers use to systematically describe their +projects(5) so that users can better find projects that match their +needs on the PyPI. + +The trove-classifiers package contains a list of valid classifiers and +deprecated classifiers (which are paired with the classifiers that +replace them). Use this package to validate classifiers used in +packages intended for uploading to PyPI. As this list of classifiers is +published as code, you can install and import it, giving you a more +convenient workflow compared to referring to the list published on +PyPI(6). The issue tracker(7) for the project hosts discussions on +proposed classifiers and requests for new classifiers. + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/trove-classifiers/issues + + (2) https://github.com/pypa/trove-classifiers + + (3) https://pypi.org/project/trove-classifiers/ + + (4) https://pypi.org/classifiers/ + + (5) +https://packaging.python.org/specifications/core-metadata/#classifier-multiple-use + + (6) https://pypi.org/classifiers/ + + (7) https://github.com/pypa/trove-classifiers/issues + + +File: pythonpackagingguide.info, Node: twine, Next: virtualenv<2>, Prev: trove-classifiers, Up: PyPA Projects + +6.1.16 twine +------------ + +Docs(1) | Issues(2) | GitHub(3) | PyPI(4) + +Twine is the primary tool developers use to upload packages to the +Python Package Index or other Python package indexes. It is a +command-line program that passes program files and metadata to a web +API. Developers use it because it’s the official PyPI upload tool, it’s +fast and secure, it’s maintained, and it reliably works. + + ---------- Footnotes ---------- + + (1) https://twine.readthedocs.io/en/latest/ + + (2) https://github.com/pypa/twine/issues + + (3) https://github.com/pypa/twine + + (4) https://pypi.org/project/twine + + +File: pythonpackagingguide.info, Node: virtualenv<2>, Next: Warehouse, Prev: twine, Up: PyPA Projects + +6.1.17 virtualenv +----------------- + +Docs(1) | Issues(2) | GitHub(3) | PyPI(4) + +virtualenv is a tool which uses the command-line path environment +variable to create isolated Python *note Virtual Environments: 263, much +as *note venv: 7e. does. virtualenv provides additional functionality, +compared to *note venv: 7e, by supporting Python 2.7 and by providing +convenient features for configuring, maintaining, duplicating, and +troubleshooting the virtual environments. For more information, see the +section on *note Creating Virtual Environments: 31. + + ---------- Footnotes ---------- + + (1) https://virtualenv.pypa.io/en/stable/index.html + + (2) https://github.com/pypa/virtualenv/issues + + (3) https://github.com/pypa/virtualenv + + (4) https://pypi.org/project/virtualenv/ + + +File: pythonpackagingguide.info, Node: Warehouse, Next: wheel, Prev: virtualenv<2>, Up: PyPA Projects + +6.1.18 Warehouse +---------------- + +Docs(1) | Issues(2) | GitHub(3) + +The current codebase powering the *note Python Package Index (PyPI): 39. +It is hosted at pypi.org(4). The default source for *note pip: 2b. +downloads. + + ---------- Footnotes ---------- + + (1) https://warehouse.pypa.io/ + + (2) https://github.com/pypa/warehouse/issues + + (3) https://github.com/pypa/warehouse + + (4) https://pypi.org/ + + +File: pythonpackagingguide.info, Node: wheel, Prev: Warehouse, Up: PyPA Projects + +6.1.19 wheel +------------ + +Docs(1) | Issues(2) | GitHub(3) | PyPI(4) + +Primarily, the wheel project offers the ‘bdist_wheel’ *note setuptools: +2d. extension for creating *note wheel distributions: d. Additionally, +it offers its own command line utility for creating and installing +wheels. + +See also auditwheel(5), a tool that package developers use to check and +fix Python packages they are making in the binary wheel format. It +provides functionality to discover dependencies, check metadata for +compliance, and repair the wheel and metadata to properly link and +include external shared libraries in a package. + + ---------- Footnotes ---------- + + (1) https://wheel.readthedocs.io/en/latest/ + + (2) https://github.com/pypa/wheel/issues + + (3) https://github.com/pypa/wheel + + (4) https://pypi.org/project/wheel + + (5) https://github.com/pypa/auditwheel + + +File: pythonpackagingguide.info, Node: Non-PyPA Projects, Next: Standard Library Projects, Prev: PyPA Projects, Up: Project Summaries + +6.2 Non-PyPA Projects +===================== + +* Menu: + +* buildout:: +* conda:: +* devpi:: +* enscons:: +* Hashdist:: +* multibuild:: +* pdm:: +* pex: pex<2>. +* pip-tools:: +* piwheels:: +* poetry:: +* pypiserver:: +* PyScaffold:: +* scikit-build:: +* shiv:: +* Spack: Spack<2>. +* zest.releaser: zest releaser. + + +File: pythonpackagingguide.info, Node: buildout, Next: conda, Up: Non-PyPA Projects + +6.2.1 buildout +-------------- + +Docs(1) | Issues(2) | PyPI(3) | GitHub(4) + +Buildout is a Python-based build system for creating, assembling and +deploying applications from multiple parts, some of which may be +non-Python-based. It lets you create a buildout configuration and +reproduce the same software later. + + ---------- Footnotes ---------- + + (1) http://www.buildout.org/en/latest/ + + (2) https://bugs.launchpad.net/zc.buildout + + (3) https://pypi.org/project/zc.buildout + + (4) https://github.com/buildout/buildout/ + + +File: pythonpackagingguide.info, Node: conda, Next: devpi, Prev: buildout, Up: Non-PyPA Projects + +6.2.2 conda +----------- + +Docs(1) + +conda is the package management tool for Anaconda(2) Python +installations. Anaconda Python is a distribution from Anaconda, Inc(3) +specifically aimed at the scientific community, and in particular on +Windows where the installation of binary extensions is often difficult. + +Conda is a completely separate tool from *note pip: 2b, virtualenv and +wheel, but provides many of their combined features in terms of package +management, virtual environment management and deployment of binary +extensions. + +Conda does not install packages from PyPI and can install only from the +official Anaconda repositories, or anaconda.org (a place for +user-contributed `conda' packages), or a local (e.g. intranet) package +server. However, note that *note pip: 2b. can be installed into, and +work side-by-side with conda for managing *note distributions: b. from +PyPI. Also, conda skeleton(4) is a tool to make Python packages +installable by conda by first fetching them from PyPI and modifying +their metadata. + + ---------- Footnotes ---------- + + (1) https://conda.io/en/latest/index.html + + (2) https://docs.anaconda.com/anaconda/ + + (3) https://www.anaconda.com/products/individual + + (4) +https://docs.conda.io/projects/conda-build/en/latest/user-guide/tutorials/build-pkgs-skeleton.html + + +File: pythonpackagingguide.info, Node: devpi, Next: enscons, Prev: conda, Up: Non-PyPA Projects + +6.2.3 devpi +----------- + +Docs(1) | Issues(2) | PyPI(3) + +devpi features a powerful PyPI-compatible server and PyPI proxy cache +with a complementary command line tool to drive packaging, testing and +release activities with Python. devpi also provides a browsable and +searchable web interface. + + ---------- Footnotes ---------- + + (1) http://doc.devpi.net/latest/ + + (2) https://github.com/devpi/devpi/issues + + (3) https://pypi.org/project/devpi + + +File: pythonpackagingguide.info, Node: enscons, Next: Hashdist, Prev: devpi, Up: Non-PyPA Projects + +6.2.4 enscons +------------- + +Source(1) | Issues(2) | PyPI(3) + +Enscons is a Python packaging tool based on SCons(4). It builds *note +pip: 2b.-compatible source distributions and wheels without using +distutils or setuptools, including distributions with C extensions. +Enscons has a different architecture and philosophy than *note +distutils: be. Rather than adding build features to a Python packaging +system, enscons adds Python packaging to a general purpose build system. +Enscons helps you to build sdists that can be automatically built by +*note pip: 2b, and wheels that are independent of enscons. + + ---------- Footnotes ---------- + + (1) https://github.com/dholth/enscons + + (2) https://github.com/dholth/enscons/issues + + (3) https://pypi.org/project/enscons + + (4) https://scons.org/ + + +File: pythonpackagingguide.info, Node: Hashdist, Next: multibuild, Prev: enscons, Up: Non-PyPA Projects + +6.2.5 Hashdist +-------------- + +Docs(1) | GitHub(2) + +Hashdist is a library for building non-root software distributions. +Hashdist is trying to be “the Debian of choice for cases where Debian +technology doesn’t work”. The best way for Pythonistas to think about +Hashdist may be a more powerful hybrid of *note virtualenv: 32. and +*note buildout: 169. It is aimed at solving the problem of installing +scientific software, and making package distribution stateless, cached, +and branchable. It is used by some researchers but has been lacking in +maintenance since 2016. + + ---------- Footnotes ---------- + + (1) https://hashdist.readthedocs.io/en/latest/ + + (2) https://github.com/hashdist/hashdist/ + + +File: pythonpackagingguide.info, Node: multibuild, Next: pdm, Prev: Hashdist, Up: Non-PyPA Projects + +6.2.6 multibuild +---------------- + +GitHub(1) + +Multibuild is a set of CI scripts for building and testing Python *note +wheels: d. for Linux, macOS, and (less flexibly) Windows. Also see +*note cibuildwheel: 11a. + + ---------- Footnotes ---------- + + (1) https://github.com/matthew-brett/multibuild + + +File: pythonpackagingguide.info, Node: pdm, Next: pex<2>, Prev: multibuild, Up: Non-PyPA Projects + +6.2.7 pdm +--------- + +Docs(1) | GitHub(2) | PyPI(3) + +PDM is a modern Python package manager with PEP 582(4) support. It +installs and manages packages in a similar way to ‘npm’ that doesn’t +need to create a *note virtual environment: 263. at all. It also uses +*note pyproject.toml: 1e5. to store project metadata as defined in PEP +621(5). + + ---------- Footnotes ---------- + + (1) https://pdm.fming.dev/ + + (2) https://github.com/pdm-project/pdm/ + + (3) https://pypi.org/project/pdm + + (4) https://www.python.org/dev/peps/pep-0582 + + (5) https://www.python.org/dev/peps/pep-0621 + + +File: pythonpackagingguide.info, Node: pex<2>, Next: pip-tools, Prev: pdm, Up: Non-PyPA Projects + +6.2.8 pex +--------- + +Docs(1) | GitHub(2) | PyPI(3) + +pex is both a library and tool for generating ‘.pex’ (Python EXecutable) +files, standalone Python environments in the spirit of *note virtualenv: +32. ‘.pex’ files are just carefully constructed zip files with a +‘#!/usr/bin/env python’ and special ‘__main__.py’, and are designed to +make deployment of Python applications as simple as ‘cp’. + + ---------- Footnotes ---------- + + (1) https://pex.readthedocs.io/en/latest/ + + (2) https://github.com/pantsbuild/pex/ + + (3) https://pypi.org/project/pex + + +File: pythonpackagingguide.info, Node: pip-tools, Next: piwheels, Prev: pex<2>, Up: Non-PyPA Projects + +6.2.9 pip-tools +--------------- + +GitHub and Docs(1) | PyPI(2) + +pip-tools is a suite of tools meant for Python system administrators and +release managers who particularly want to keep their builds +deterministic yet stay up to date with new versions of their +dependencies. Users can specify particular release of their +dependencies via hash, conveniently make a properly formatted list of +requirements from information in other parts of their program, update +all dependencies (a feature *note pip: 2b. currently does not provide), +and create layers of constraints for the program to obey. + + ---------- Footnotes ---------- + + (1) https://github.com/jazzband/pip-tools/ + + (2) https://pypi.org/project/pip-tools/ + + +File: pythonpackagingguide.info, Node: piwheels, Next: poetry, Prev: pip-tools, Up: Non-PyPA Projects + +6.2.10 piwheels +--------------- + +Website(1) | Docs(2) | GitHub(3) + +piwheels is a website, and software underpinning it, that fetches source +code distribution packages from PyPI and compiles them into binary +wheels that are optimized for installation onto Raspberry Pi computers. +Raspberry Pi OS pre-configures pip to use piwheels.org as an additional +index to PyPI. + + ---------- Footnotes ---------- + + (1) https://www.piwheels.org/ + + (2) https://piwheels.readthedocs.io/en/latest/index.html + + (3) https://github.com/piwheels/piwheels/ + + +File: pythonpackagingguide.info, Node: poetry, Next: pypiserver, Prev: piwheels, Up: Non-PyPA Projects + +6.2.11 poetry +------------- + +Docs(1) | GitHub(2) | PyPI(3) + +poetry is a command-line tool to handle dependency installation and +isolation as well as building and packaging of Python packages. It uses +‘pyproject.toml’ and, instead of depending on the resolver functionality +within *note pip: 2b, provides its own dependency resolver. It attempts +to speed users’ experience of installation and dependency resolution by +locally caching metadata about dependencies. + + ---------- Footnotes ---------- + + (1) https://python-poetry.org/ + + (2) https://github.com/python-poetry/poetry + + (3) https://pypi.org/project/poetry/ + + +File: pythonpackagingguide.info, Node: pypiserver, Next: PyScaffold, Prev: poetry, Up: Non-PyPA Projects + +6.2.12 pypiserver +----------------- + +Docs(1) | GitHub(2) | PyPI(3) + +pypiserver is a minimalist application that serves as a private Python +package index within organizations, implementing a simple API and +browser interface. You can upload private packages using standard +upload tools, and users can download and install them with *note pip: +2b, without publishing them publicly. Organizations who use pypiserver +usually download packages both from pypiserver and from PyPI. + + ---------- Footnotes ---------- + + (1) https://github.com/pypiserver/pypiserver/blob/master/README.rst + + (2) https://github.com/pypiserver/pypiserver + + (3) https://pypi.org/project/pypiserver/ + + +File: pythonpackagingguide.info, Node: PyScaffold, Next: scikit-build, Prev: pypiserver, Up: Non-PyPA Projects + +6.2.13 PyScaffold +----------------- + +Docs(1) | GitHub(2) | PyPI(3) + +PyScaffold is a project generator for bootstrapping Python packages, +ready to be shared on PyPI and installable via *note pip: 2b. It relies +on a set of sane default configurations for established tools (such as +*note setuptools: 2d, pytest(4) and Sphinx(5)) to provide a productive +environment so developers can start coding right away. PyScaffold can +also be used with existing projects to make packaging easier. + + ---------- Footnotes ---------- + + (1) https://pyscaffold.org + + (2) https://github.com/pyscaffold/pyscaffold + + (3) https://pypi.org/project/pyscaffold/ + + (4) https://docs.pytest.org/en/stable/ + + (5) https://www.sphinx-doc.org/en/master/ + + +File: pythonpackagingguide.info, Node: scikit-build, Next: shiv, Prev: PyScaffold, Up: Non-PyPA Projects + +6.2.14 scikit-build +------------------- + +Docs(1) | GitHub(2) | PyPI(3) + +Scikit-build is an improved build system generator for CPython +C/C++/Fortran/Cython extensions that integrates with *note setuptools: +2d, *note wheel: 2e. and *note pip: 2b. It internally uses cmake(4) +(available on PyPI) to provide better support for additional compilers, +build systems, cross compilation, and locating dependencies and their +associated build requirements. To speed up and parallelize the build of +large projects, the user can install ninja(5) (also available on PyPI). + + ---------- Footnotes ---------- + + (1) https://scikit-build.readthedocs.io/en/latest/ + + (2) https://github.com/scikit-build/scikit-build/ + + (3) https://pypi.org/project/scikit-build + + (4) https://pypi.org/project/cmake + + (5) https://pypi.org/project/ninja + + +File: pythonpackagingguide.info, Node: shiv, Next: Spack<2>, Prev: scikit-build, Up: Non-PyPA Projects + +6.2.15 shiv +----------- + +Docs(1) | GitHub(2) | PyPI(3) + +shiv is a command line utility for building fully self contained Python +zipapps as outlined in PEP 441(4), but with all their dependencies +included. Its primary goal is making distributing Python applications +and command line tools fast & easy. + + ---------- Footnotes ---------- + + (1) https://shiv.readthedocs.io/en/latest/ + + (2) https://github.com/linkedin/shiv + + (3) https://pypi.org/project/shiv/ + + (4) https://www.python.org/dev/peps/pep-0441 + + +File: pythonpackagingguide.info, Node: Spack<2>, Next: zest releaser, Prev: shiv, Up: Non-PyPA Projects + +6.2.16 Spack +------------ + +Docs(1) | GitHub(2) | Paper(3) | Slides(4) + +A flexible package manager designed to support multiple versions, +configurations, platforms, and compilers. Spack is like Homebrew, but +packages are written in Python and parameterized to allow easy swapping +of compilers, library versions, build options, etc. Arbitrarily many +versions of packages can coexist on the same system. Spack was designed +for rapidly building high performance scientific applications on +clusters and supercomputers. + +Spack is not in PyPI (yet), but it requires no installation and can be +used immediately after cloning from GitHub. + + ---------- Footnotes ---------- + + (1) https://spack.readthedocs.io/en/latest/index.html + + (2) https://github.com/spack/spack + + (3) +https://www.computer.org/csdl/proceedings-article/sc/2015/2807623/12OmNBf94Xq + + (4) https://tgamblin.github.io/files/Gamblin-Spack-SC15-Talk.pdf + + +File: pythonpackagingguide.info, Node: zest releaser, Prev: Spack<2>, Up: Non-PyPA Projects + +6.2.17 zest.releaser +-------------------- + +Docs(1) | GitHub(2) | PyPI(3) + +‘zest.releaser’ is a Python package release tool providing an +abstraction layer on top of *note twine: 6d. Python developers use +‘zest.releaser’ to automate incrementing package version numbers, +updating changelogs, tagging releases in source control, and uploading +new packages to PyPI. + + ---------- Footnotes ---------- + + (1) https://zestreleaser.readthedocs.io/en/latest/ + + (2) https://github.com/zestsoftware/zest.releaser/ + + (3) https://pypi.org/project/zest.releaser/ + + +File: pythonpackagingguide.info, Node: Standard Library Projects, Prev: Non-PyPA Projects, Up: Project Summaries + +6.3 Standard Library Projects +============================= + +* Menu: + +* ensurepip:: +* distutils:: +* venv:: + + +File: pythonpackagingguide.info, Node: ensurepip, Next: distutils, Up: Standard Library Projects + +6.3.1 ensurepip +--------------- + +Docs(1) | Issues(2) + +A package in the Python Standard Library that provides support for +bootstrapping *note pip: 2b. into an existing Python installation or +virtual environment. In most cases, end users won’t use this module, +but rather it will be used during the build of the Python distribution. + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/library/ensurepip.html + + (2) https://bugs.python.org/ + + +File: pythonpackagingguide.info, Node: distutils, Next: venv, Prev: ensurepip, Up: Standard Library Projects + +6.3.2 distutils +--------------- + +Docs(1) | Issues(2) + +The original Python packaging system, added to the standard library in +Python 2.0. + +Due to the challenges of maintaining a packaging system where feature +updates are tightly coupled to language runtime updates, direct usage of +*note distutils: be. is now actively discouraged, with *note setuptools: +2d. being the preferred replacement. *note setuptools: 2d. not only +provides features that plain *note distutils: be. doesn’t offer (such as +dependency declarations and entry point declarations), it also provides +a consistent build interface and feature set across all supported Python +versions. + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/library/distutils.html + + (2) https://bugs.python.org/ + + +File: pythonpackagingguide.info, Node: venv, Prev: distutils, Up: Standard Library Projects + +6.3.3 venv +---------- + +Docs(1) | Issues(2) + +A package in the Python Standard Library (starting with Python 3.3) for +creating *note Virtual Environments: 263. For more information, see the +section on *note Creating Virtual Environments: 31. + +__________________________________________________________________ + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/library/venv.html + + (2) https://bugs.python.org/ + + +File: pythonpackagingguide.info, Node: Glossary, Next: How to Get Support, Prev: Project Summaries, Up: Top + +7 Glossary +********** + +Binary Distribution + + A specific kind of *note Built Distribution: 68. that contains + compiled extensions. + +Built Distribution + + A *note Distribution: b. format containing files and metadata that + only need to be moved to the correct location on the target system, + to be installed. *note Wheel: d. is such a format, whereas + distutil’s *note Source Distribution: 3d. is not, in that it + requires a build step before it can be installed. This format does + not imply that Python files have to be precompiled (*note Wheel: d. + intentionally does not include compiled Python files). + +Distribution Package + + A versioned archive file that contains Python *note packages: a, + *note modules: 5a, and other resource files that are used to + distribute a *note Release: 28b. The archive file is what an + end-user will download from the internet and install. + + A distribution package is more commonly referred to with the single + words “package” or “distribution”, but this guide may use the + expanded term when more clarity is needed to prevent confusion with + an *note Import Package: a. (which is also commonly called a + “package”) or another kind of distribution (e.g. a Linux + distribution or the Python language distribution), which are often + referred to with the single term “distribution”. + +Egg + + A *note Built Distribution: 68. format introduced by *note + setuptools: 2d, which is being replaced by *note Wheel: d. For + details, see ‘ The Internal Structure of Python Eggs(1) and Python + Eggs(2) + +Extension Module + + A *note Module: 5a. written in the low-level language of the Python + implementation: C/C++ for Python, Java for Jython. Typically + contained in a single dynamically loadable pre-compiled file, e.g. + a shared object (.so) file for Python extensions on Unix, a DLL + (given the .pyd extension) for Python extensions on Windows, or a + Java class file for Jython extensions. + +Known Good Set (KGS) + + A set of distributions at specified versions which are compatible + with each other. Typically a test suite will be run which passes + all tests before a specific set of packages is declared a known + good set. This term is commonly used by frameworks and toolkits + which are comprised of multiple individual distributions. + +Import Package + + A Python module which can contain other modules or recursively, + other packages. + + An import package is more commonly referred to with the single word + “package”, but this guide will use the expanded term when more + clarity is needed to prevent confusion with a *note Distribution + Package: b. which is also commonly called a “package”. + +Module + + The basic unit of code reusability in Python, existing in one of + two types: *note Pure Module: 28e, or *note Extension Module: 28c. + +Package Index + + A repository of distributions with a web interface to automate + *note package: b. discovery and consumption. + +Per Project Index + + A private or other non-canonical *note Package Index: e9. indicated + by a specific *note Project: 203. as the index preferred or + required to resolve dependencies of that project. + +Project + + A library, framework, script, plugin, application, or collection of + data or other resources, or some combination thereof that is + intended to be packaged into a *note Distribution: b. + + Since most projects create *note Distributions: b. using either PEP + 518(3) ‘build-system’, *note distutils: be. or *note setuptools: + 2d, another practical way to define projects currently is something + that contains a *note pyproject.toml: 1e5, *note setup.py: 290, or + *note setup.cfg: 291. file at the root of the project source + directory. + + Python projects must have unique names, which are registered on + *note PyPI: 39. Each project will then contain one or more *note + Releases: 28b, and each release may comprise one or more *note + distributions: b. + + Note that there is a strong convention to name a project after the + name of the package that is imported to run that project. However, + this doesn’t have to hold true. It’s possible to install a + distribution from the project ‘foo’ and have it provide a package + importable only as ‘bar’. + +Pure Module + + A *note Module: 5a. written in Python and contained in a single + ‘.py’ file (and possibly associated ‘.pyc’ and/or ‘.pyo’ files). + +Python Packaging Authority (PyPA) + + PyPA is a working group that maintains many of the relevant + projects in Python packaging. They maintain a site at pypa.io(4), + host projects on GitHub(5) and Bitbucket(6), and discuss issues on + the distutils-sig mailing list(7) and the Python Discourse + forum(8). + +Python Package Index (PyPI) + + PyPI(9) is the default *note Package Index: e9. for the Python + community. It is open to all Python developers to consume and + distribute their distributions. + +pypi.org + + pypi.org(10) is the domain name for the *note Python Package Index + (PyPI): 39. It replaced the legacy index domain name, + ‘pypi.python.org’, in 2017. It is powered by *note Warehouse: 265. + +pyproject.toml + + The tool-agnostic *note Project: 203. specification file. Defined + in PEP 518(11). + +Release + + A snapshot of a *note Project: 203. at a particular point in time, + denoted by a version identifier. + + Making a release may entail the publishing of multiple *note + Distributions: b. For example, if version 1.0 of a project was + released, it could be available in both a source distribution + format and a Windows installer distribution format. + +Requirement + + A specification for a *note package: b. to be installed. *note + pip: 2b, the *note PYPA: 292. recommended installer, allows various + forms of specification that can all be considered a “requirement”. + For more information, see the pip install(12) reference. + +Requirement Specifier + + A format used by *note pip: 2b. to install packages from a *note + Package Index: e9. For an EBNF diagram of the format, see the + pkg_resources.Requirement(13) entry in the *note setuptools: 2d. + docs. For example, “foo>=1.3” is a requirement specifier, where + “foo” is the project name, and the “>=1.3” portion is the *note + Version Specifier: 3b. + +Requirements File + + A file containing a list of *note Requirements: 293. that can be + installed using *note pip: 2b. For more information, see the *note + pip: 2b. docs on Requirements Files(14). + +setup.py + +setup.cfg + + The project specification files for *note distutils: be. and *note + setuptools: 2d. See also *note pyproject.toml: 1e5. + +Source Archive + + An archive containing the raw source code for a *note Release: 28b, + prior to creation of a *note Source Distribution: 3d. or *note + Built Distribution: 68. + +Source Distribution (or “sdist”) + + A *note distribution: b. format (usually generated using ‘python + setup.py sdist’) that provides metadata and the essential source + files needed for installing by a tool like *note pip: 2b, or for + generating a *note Built Distribution: 68. + +System Package + + A package provided in a format native to the operating system, e.g. + an rpm or dpkg file. + +Version Specifier + + The version component of a *note Requirement Specifier: 3a. For + example, the “>=1.3” portion of “foo>=1.3”. PEP 440(15) contains a + full specification(16) of the specifiers that Python packaging + currently supports. Support for PEP440 was implemented in *note + setuptools: 2d. v8.0 and *note pip: 2b. v6.0. + +Virtual Environment + + An isolated Python environment that allows packages to be installed + for use by a particular application, rather than being installed + system wide. For more information, see the section on *note + Creating Virtual Environments: 31. + +Wheel + + A *note Built Distribution: 68. format introduced by PEP 427(17), + which is intended to replace the *note Egg: 166. format. Wheel is + currently supported by *note pip: 2b. + +Working Set + + A collection of *note distributions: b. available for importing. + These are the distributions that are on the sys.path(18) variable. + At most, one *note Distribution: b. for a project is possible in a + working set. + + ---------- Footnotes ---------- + + (1) https://setuptools.pypa.io/en/latest/deprecated/python_eggs.html + + (2) http://peak.telecommunity.com/DevCenter/PythonEggs + + (3) https://www.python.org/dev/peps/pep-0518 + + (4) https://www.pypa.io/en/latest/ + + (5) https://github.com/pypa + + (6) https://bitbucket.org/pypa + + (7) https://mail.python.org/mailman3/lists/distutils-sig.python.org/ + + (8) https://discuss.python.org/c/packaging + + (9) https://pypi.org + + (10) https://pypi.org + + (11) https://www.python.org/dev/peps/pep-0518 + + (12) https://pip.pypa.io/en/latest/cli/pip_install/#pip-install + + (13) +https://setuptools.readthedocs.io/en/latest/pkg_resources.html#requirement-objects + + (14) https://pip.pypa.io/en/latest/user_guide/#requirements-files + + (15) https://www.python.org/dev/peps/pep-0440 + + (16) https://www.python.org/dev/peps/pep-0440#version-specifiers + + (17) https://www.python.org/dev/peps/pep-0427 + + (18) https://docs.python.org/2/library/sys.html#sys.path + + +File: pythonpackagingguide.info, Node: How to Get Support, Next: Contribute to this guide, Prev: Glossary, Up: Top + +8 How to Get Support +******************** + +For support related to a specific project, see the links on the *note +Projects: 249. page. + +For something more general, or when you’re just not sure, please open an +issue(1) on the packaging-problems(2) repository on GitHub. + + ---------- Footnotes ---------- + + (1) +https://github.com/pypa/packaging-problems/issues/new?template=general_issue.yml + + (2) https://github.com/pypa/packaging-problems + + +File: pythonpackagingguide.info, Node: Contribute to this guide, Next: News, Prev: How to Get Support, Up: Top + +9 Contribute to this guide +************************** + +The Python Packaging User Guide welcomes contributors! There are lots +of ways to help out, including: + + * Reading the guide and giving feedback + + * Reviewing new contributions + + * Revising existing content + + * Writing new content + + * Translate the guide + +Most of the work on the Python Packaging User Guide takes place on the +project’s GitHub repository(1). To get started, check out the list of +open issues(2) and pull requests(3). If you’re planning to write or +edit the guide, please read the *note style guide: 29b. + +By contributing to the Python Packaging User Guide, you’re expected to +follow the PSF’s Code of Conduct(4). + +* Menu: + +* Documentation types:: +* Translations:: +* Building the guide locally:: +* Where the guide is deployed:: +* Style guide:: + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/ + + (2) https://github.com/pypa/packaging.python.org/issues + + (3) https://github.com/pypa/packaging.python.org/pulls + + (4) https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md + + +File: pythonpackagingguide.info, Node: Documentation types, Next: Translations, Up: Contribute to this guide + +9.1 Documentation types +======================= + +This project consists of four distinct documentation types with specific +purposes. When proposing new additions to the project please pick the +appropriate documentation type. + +* Menu: + +* Tutorials: Tutorials<2>. +* Guides: Guides<2>. +* Discussions: Discussions<2>. +* Specifications:: + + +File: pythonpackagingguide.info, Node: Tutorials<2>, Next: Guides<2>, Up: Documentation types + +9.1.1 Tutorials +--------------- + +Tutorials are focused on teaching the reader new concepts by +accomplishing a goal. They are opinionated step-by-step guides. They +do not include extraneous warnings or information. example +tutorial-style document(1). + + ---------- Footnotes ---------- + + (1) https://docs.djangoproject.com/en/1.11/intro/ + + +File: pythonpackagingguide.info, Node: Guides<2>, Next: Discussions<2>, Prev: Tutorials<2>, Up: Documentation types + +9.1.2 Guides +------------ + +Guides are focused on accomplishing a specific task and can assume some +level of pre-requisite knowledge. These are similar to tutorials, but +have a narrow and clear focus and can provide lots of caveats and +additional information as needed. They may also discuss multiple +approaches to accomplishing the task. *note example guide-style +document: 130. + + +File: pythonpackagingguide.info, Node: Discussions<2>, Next: Specifications, Prev: Guides<2>, Up: Documentation types + +9.1.3 Discussions +----------------- + +Discussions are focused on understanding and information. These explore +a specific topic without a specific goal in mind. *note example +discussion-style document: 197. + + +File: pythonpackagingguide.info, Node: Specifications, Prev: Discussions<2>, Up: Documentation types + +9.1.4 Specifications +-------------------- + +Specifications are reference documention focused on comprehensively +documenting an agreed-upon interface for interoperability between +packaging tools. *note example specification-style document: 1a4. + + +File: pythonpackagingguide.info, Node: Translations, Next: Building the guide locally, Prev: Documentation types, Up: Contribute to this guide + +9.2 Translations +================ + +We use Weblate(1) to manage translations of this project. Please visit +the packaging.python.org(2) project on Weblate to contribute. + +If you are experiencing issues while you are working on translations, +please open an issue on Github(3). + + Tip: Any translations of this project should follow + reStructuredText syntax(4). + +* Menu: + +* Adding a language:: +* Following reStructuredText syntax:: + + ---------- Footnotes ---------- + + (1) https://weblate.org/ + + (2) https://hosted.weblate.org/projects/pypa/packaging-python-org/ + + (3) https://github.com/pypa/packaging.python.org/issues + + (4) +https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html + + +File: pythonpackagingguide.info, Node: Adding a language, Next: Following reStructuredText syntax, Up: Translations + +9.2.1 Adding a language +----------------------- + +If your language is not listed on packaging.python.org(1), click the +button Start new translation at the bottom of the language list and add +the language you want to translate. + + ---------- Footnotes ---------- + + (1) https://hosted.weblate.org/projects/pypa/packaging-python-org/ + + +File: pythonpackagingguide.info, Node: Following reStructuredText syntax, Prev: Adding a language, Up: Translations + +9.2.2 Following reStructuredText syntax +--------------------------------------- + +If you are not familiar with reStructuredText (RST) syntax, please read +this guide(1) before translating on Weblate. + +`Do not translate the text in reference directly' + + When translating the text in reference, please do not translate + them directly. + + Wrong: Translate the following text directly: + + `some ref`_ -> `TRANSLATED TEXT HERE`_ + + Right: Translate the following text with your own language and add the original reference: + + `some ref`_ -> `TRANSLATED TEXT HERE `_ + + ---------- Footnotes ---------- + + (1) https://docutils.sourceforge.io/docs/user/rst/quickref.html + + +File: pythonpackagingguide.info, Node: Building the guide locally, Next: Where the guide is deployed, Prev: Translations, Up: Contribute to this guide + +9.3 Building the guide locally +============================== + +Though not required to contribute, it may be useful to build this guide +locally in order to test your changes. In order to build this guide +locally, you’ll need: + + 1. Nox(1). You can install or upgrade nox using ‘pip’: + + python -m pip install --user nox + + 2. Python 3.8. Our build scripts are usually tested with Python 3.8 + only. See the Hitchhiker’s Guide to Python installation + instructions(2) to install Python 3.8 on your operating system. + +To build the guide, run the following bash command in the source folder: + + nox -s build + +After the process has completed you can find the HTML output in the +‘./build/html’ directory. You can open the ‘index.html’ file to view +the guide in web browser, but it’s recommended to serve the guide using +an HTTP server. + +You can build the guide and serve it via an HTTP server using the +following command: + + nox -s preview + +The guide will be browsable via ‘http://localhost:8000’. + + ---------- Footnotes ---------- + + (1) https://nox.thea.codes/en/latest/index.html + + (2) https://docs.python-guide.org/starting/installation/ + + +File: pythonpackagingguide.info, Node: Where the guide is deployed, Next: Style guide, Prev: Building the guide locally, Up: Contribute to this guide + +9.4 Where the guide is deployed +=============================== + +The guide is deployed via ReadTheDocs and the configuration lives at +‘https://readthedocs.org/projects/python-packaging-user-guide/’. It’s +served from a custom domain and fronted by Fast.ly. + + +File: pythonpackagingguide.info, Node: Style guide, Prev: Where the guide is deployed, Up: Contribute to this guide + +9.5 Style guide +=============== + +This style guide has recommendations for how you should write the Python +Packaging User Guide. Before you start writing, please review it. By +following the style guide, your contributions will help add to a +cohesive whole and make it easier for your contributions to be accepted +into the project. + +* Menu: + +* Purpose:: +* Scope:: +* Audience:: +* Voice and tone:: +* Conventions and mechanics:: + + +File: pythonpackagingguide.info, Node: Purpose, Next: Scope, Up: Style guide + +9.5.1 Purpose +------------- + +The purpose of the Python Packaging User Guide is to be the +authoritative resource on how to package, publish, and install Python +projects using current tools. + + +File: pythonpackagingguide.info, Node: Scope, Next: Audience, Prev: Purpose, Up: Style guide + +9.5.2 Scope +----------- + +The guide is meant to answer questions and solve problems with accurate +and focused recommendations. + +The guide isn’t meant to be comprehensive and it’s not meant to replace +individual projects’ documentation. For example, pip has dozens of +commands, options, and settings. The pip documentation describes each +of them in detail, while this guide describes only the parts of pip that +are needed to complete the specific tasks described in this guide. + + +File: pythonpackagingguide.info, Node: Audience, Next: Voice and tone, Prev: Scope, Up: Style guide + +9.5.3 Audience +-------------- + +The audience of this guide is anyone who uses Python with packages. + +Don’t forget that the Python community is big and welcoming. Readers +may not share your age, gender, education, culture, and more, but they +deserve to learn about packaging just as much as you do. + +In particular, keep in mind that not all people who use Python see +themselves as programmers. The audience of this guide includes +astronomers or painters or students as well as professional software +developers. + + +File: pythonpackagingguide.info, Node: Voice and tone, Next: Conventions and mechanics, Prev: Audience, Up: Style guide + +9.5.4 Voice and tone +-------------------- + +When writing this guide, strive to write with a voice that’s +approachable and humble, even if you have all the answers. + +Imagine you’re working on a Python project with someone you know to be +smart and skilled. You like working with them and they like working +with you. That person has asked you a question and you know the answer. +How do you respond? `That' is how you should write this guide. + +Here’s a quick check: try reading aloud to get a sense for your +writing’s voice and tone. Does it sound like something you would say or +does it sound like you’re acting out a part or giving a speech? Feel +free to use contractions and don’t worry about sticking to fussy grammar +rules. You are hereby granted permission to end a sentence in a +preposition, if that’s what you want to end it with. + +When writing the guide, adjust your tone for the seriousness and +difficulty of the topic. If you’re writing an introductory tutorial, +it’s OK to make a joke, but if you’re covering a sensitive security +recommendation, you might want to avoid jokes altogether. + + +File: pythonpackagingguide.info, Node: Conventions and mechanics, Prev: Voice and tone, Up: Style guide + +9.5.5 Conventions and mechanics +------------------------------- + +`Write to the reader' + + When giving recommendations or steps to take, address the reader as + `you' or use the imperative mood. + + Wrong: To install it, the user runs… + Right: You can install it by running… + Right: To install it, run… + +`State assumptions' + + Avoid making unstated assumptions. Reading on the web means that + any page of the guide may be the first page of the guide that the + reader ever sees. If you’re going to make assumptions, then say + what assumptions that you’re going to make. + +`Cross-reference generously' + + The first time you mention a tool or practice, link to the part of + the guide that covers it, or link to a relevant document elsewhere. + Save the reader a search. + +`Respect naming practices' + + When naming tools, sites, people, and other proper nouns, use their + preferred capitalization. + + Wrong: Pip uses… + Right: pip uses… + + Wrong: …hosted on github. + Right: …hosted on GitHub. + +`Use a gender-neutral style' + + Often, you’ll address the reader directly with `you', `your' and + `yours'. Otherwise, use gender-neutral pronouns `they', `their', + and `theirs' or avoid pronouns entirely. + + Wrong: A maintainer uploads the file. Then he… + Right: A maintainer uploads the file. Then they… + Right: A maintainer uploads the file. Then the maintainer… + +`Headings' + + Write headings that use words the reader is searching for. A good + way to do this is to have your heading complete an implied + question. For example, a reader might want to know `How do I + install MyLibrary?' so a good heading might be `Install + MyLibrary'. + + In section headings, use sentence case. In other words, write + headings as you would write a typical sentence. + + Wrong: Things You Should Know About Python + Right: Things you should know about Python + +`Numbers' + + In body text, write numbers one through nine as words. For other + numbers or numbers in tables, use numerals. + + +File: pythonpackagingguide.info, Node: News, Next: Get started, Prev: Contribute to this guide, Up: Top + +10 News +******* + +* Menu: + +* September 2019:: +* August 2019:: +* July 2019:: +* June 2019:: +* May 2019:: +* April 2019:: +* March 2019:: +* February 2019:: +* January 2019:: +* December 2018:: +* November 2018:: +* October 2018:: +* September 2018:: +* August 2018:: +* July 2018:: +* June 2018:: +* May 2018:: +* April 2018:: +* March 2018:: +* February 2018:: +* January 2018:: +* December 2017:: +* November 2017:: +* October 2017:: +* September 2017:: +* August 2017:: +* July 2017:: +* June 2017:: +* May 2017:: +* April 2017:: +* March 2017:: +* February 2017:: + + +File: pythonpackagingguide.info, Node: September 2019, Next: August 2019, Up: News + +10.1 September 2019 +=================== + + - Added a guide about publishing dists via GitHub Actions. (PR + #647(1)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/647 + + +File: pythonpackagingguide.info, Node: August 2019, Next: July 2019, Prev: September 2019, Up: News + +10.2 August 2019 +================ + + - Updated to use ‘python3 -m’ when installing pipx. (PR #631(1)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/631 + + +File: pythonpackagingguide.info, Node: July 2019, Next: June 2019, Prev: August 2019, Up: News + +10.3 July 2019 +============== + + - Marked all PEP numbers with the :pep: role. (PR #629(1)) + + - Upgraded Sphinx version and removed pypa.io intersphinx. (PR + #625(2)) + + - Mentioned ‘find_namespace_packages’. (PR #622(3)) + + - Updated directory layout examples for consistency. (PR #611(4)) + + - Updated Bandersnatch link to GitHub. (PR #623(5)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/629 + + (2) https://github.com/pypa/packaging.python.org/pull/625 + + (3) https://github.com/pypa/packaging.python.org/pull/622 + + (4) https://github.com/pypa/packaging.python.org/pull/611 + + (5) https://github.com/pypa/packaging.python.org/pull/623 + + +File: pythonpackagingguide.info, Node: June 2019, Next: May 2019, Prev: July 2019, Up: News + +10.4 June 2019 +============== + + - Fixed some typos. (PR #620(1)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/620 + + +File: pythonpackagingguide.info, Node: May 2019, Next: April 2019, Prev: June 2019, Up: News + +10.5 May 2019 +============= + + - Added ‘python_requires’ usage to packaging tutorial. (PR #613(1)) + + - Added a MANIFEST.in guide page. (PR #609(2)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/613 + + (2) https://github.com/pypa/packaging.python.org/pull/609 + + +File: pythonpackagingguide.info, Node: April 2019, Next: March 2019, Prev: May 2019, Up: News + +10.6 April 2019 +=============== + + - Added a mention for ‘shiv’ in the key projects section. (PR + #608(1)) + + - Reduced emphasis on virtualenv. (PR #606(2)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/608 + + (2) https://github.com/pypa/packaging.python.org/pull/606 + + +File: pythonpackagingguide.info, Node: March 2019, Next: February 2019, Prev: April 2019, Up: News + +10.7 March 2019 +=============== + + - Moved single-sourcing guide version option to Python 3. (PR + #605(1)) + + - Covered RTD details for contributing. (PR #600(2)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/605 + + (2) https://github.com/pypa/packaging.python.org/pull/600 + + +File: pythonpackagingguide.info, Node: February 2019, Next: January 2019, Prev: March 2019, Up: News + +10.8 February 2019 +================== + + - Elaborate upon the differences between the tutorial and the real + packaging process. (PR #602(1)) + + - Added instructions to install Python CLI applications. (PR + #594(2)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/602 + + (2) https://github.com/pypa/packaging.python.org/pull/594 + + +File: pythonpackagingguide.info, Node: January 2019, Next: December 2018, Prev: February 2019, Up: News + +10.9 January 2019 +================= + + - Added ‘--no-deps’ to the packaging tutorial. (PR #593(1)) + + - Updated Sphinx and Nox. (PR #591(2)) + + - Referenced Twine from Python3. (PR #581(3)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/593 + + (2) https://github.com/pypa/packaging.python.org/pull/591 + + (3) https://github.com/pypa/packaging.python.org/pull/581 + + +File: pythonpackagingguide.info, Node: December 2018, Next: November 2018, Prev: January 2019, Up: News + +10.10 December 2018 +=================== + + - No programmers in the office! + + +File: pythonpackagingguide.info, Node: November 2018, Next: October 2018, Prev: December 2018, Up: News + +10.11 November 2018 +=================== + + - Removed landing page link to PyPI migration guide. (PR #575(1)) + + - Changed bumpversion to bump2version. (PR #572(2)) + + - Added single-sourcing package version example. (PR #573(3)) + + - Added a guide for creating documentation. (PR #568(4)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/575 + + (2) https://github.com/pypa/packaging.python.org/pull/572 + + (3) https://github.com/pypa/packaging.python.org/pull/573 + + (4) https://github.com/pypa/packaging.python.org/pull/568 + + +File: pythonpackagingguide.info, Node: October 2018, Next: September 2018, Prev: November 2018, Up: News + +10.12 October 2018 +================== + + - Updated Nox package name. (PR #566(1)) + + - Mentioned Sphinx extensions in guides. (PR #562(2)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/566 + + (2) https://github.com/pypa/packaging.python.org/pull/562 + + +File: pythonpackagingguide.info, Node: September 2018, Next: August 2018, Prev: October 2018, Up: News + +10.13 September 2018 +==================== + + - Added a section on checking RST markup. (PR #554(1)) + + - Updated user installs page. (PR #558(2)) + + - Updated Google BigQuery urls. (PR #556(3)) + + - Replaced tar command with working command. (PR #552(4)) + + - Changed to double quotes in the pip install SomeProject==1.4. (PR + #550(5)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/554 + + (2) https://github.com/pypa/packaging.python.org/pull/558 + + (3) https://github.com/pypa/packaging.python.org/pull/556 + + (4) https://github.com/pypa/packaging.python.org/pull/552 + + (5) https://github.com/pypa/packaging.python.org/pull/550 + + +File: pythonpackagingguide.info, Node: August 2018, Next: July 2018, Prev: September 2018, Up: News + +10.14 August 2018 +================= + + - Removed the recommendation to store passwords in cleartext. (PR + #546(1)) + + - Moved the Overview to a task based lead in along with the others. + (PR #540(2)) + + - Updated Python version supported by virtualenv. (PR #538(3)) + + - Added outline/rough draft of new Overview page. (PR #519(4)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/546 + + (2) https://github.com/pypa/packaging.python.org/pull/540 + + (3) https://github.com/pypa/packaging.python.org/pull/538 + + (4) https://github.com/pypa/packaging.python.org/pull/519 + + +File: pythonpackagingguide.info, Node: July 2018, Next: June 2018, Prev: August 2018, Up: News + +10.15 July 2018 +=============== + + - Improved binary extension docs. (PR #531(1)) + + - Added scikit-build to key projects. (PR #530(2)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/531 + + (2) https://github.com/pypa/packaging.python.org/pull/530 + + +File: pythonpackagingguide.info, Node: June 2018, Next: May 2018, Prev: July 2018, Up: News + +10.16 June 2018 +=============== + + - Fixed categories of interop PEP for pypa.io. (PR #527(1)) + + - Updated Markdown descriptions explanation. (PR #522(2)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/527 + + (2) https://github.com/pypa/packaging.python.org/pull/522 + + +File: pythonpackagingguide.info, Node: May 2018, Next: April 2018, Prev: June 2018, Up: News + +10.17 May 2018 +============== + + - Noted issues with Provides-Dist and Obsoletes-Dist. (PR #513(1)) + + - Removed outdated warning about Python version mixing with Pipenv. + (PR #501(2)) + + - Simplified packaging tutorial. (PR #498(3)) + + - Updated Windows users instructions for clarity. (PR #493(4)) + + - Updated the license section description for completeness. (PR + #492(5)) + + - Added specification-style document to contributing section. (PR + #489(6)) + + - Added documentation types to contributing guide. (PR #485(7)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/513 + + (2) https://github.com/pypa/packaging.python.org/pull/501 + + (3) https://github.com/pypa/packaging.python.org/pull/498 + + (4) https://github.com/pypa/packaging.python.org/pull/493 + + (5) https://github.com/pypa/packaging.python.org/pull/492 + + (6) https://github.com/pypa/packaging.python.org/pull/489 + + (7) https://github.com/pypa/packaging.python.org/pull/485 + + +File: pythonpackagingguide.info, Node: April 2018, Next: March 2018, Prev: May 2018, Up: News + +10.18 April 2018 +================ + + - Added README guide. (PR #461(1)) + + - Updated instructions and status for PyPI launch. (PR #475(2)) + + - Added instructions for Warehouse. (PR #471(3)) + + - Removed GPG references from publishing tutorial. (PR #466(4)) + + - Added ‘What’s in which Python 3.4–3.6?’. (PR #468(5)) + + - Added a guide for phasing out Python versions. (PR #459(6)) + + - Made default Description-Content-Type variant GFM. (PR #462(7)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/461 + + (2) https://github.com/pypa/packaging.python.org/pull/475 + + (3) https://github.com/pypa/packaging.python.org/pull/471 + + (4) https://github.com/pypa/packaging.python.org/pull/466 + + (5) https://github.com/pypa/packaging.python.org/pull/468 + + (6) https://github.com/pypa/packaging.python.org/pull/459 + + (7) https://github.com/pypa/packaging.python.org/pull/462 + + +File: pythonpackagingguide.info, Node: March 2018, Next: February 2018, Prev: April 2018, Up: News + +10.19 March 2018 +================ + + - Updated “installing scientific packages”. (PR #455(1)) + + - Added ‘long_description_content_type’ to follow PEP 556. (PR + #457(2)) + + - Clarified a long description classifier on pypi.org. (PR #456(3)) + + - Updated Core Metadata spec to follw PEP 556. (PR #412(4)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/455 + + (2) https://github.com/pypa/packaging.python.org/pull/457 + + (3) https://github.com/pypa/packaging.python.org/pull/456 + + (4) https://github.com/pypa/packaging.python.org/pull/412 + + +File: pythonpackagingguide.info, Node: February 2018, Next: January 2018, Prev: March 2018, Up: News + +10.20 February 2018 +=================== + + - Added python3-venv and python3-pip to Debian installation + instructions. (PR #445(1)) + + - Updated PyPI migration info. (PR #439(2)) + + - Added a warning about managing multiple versions with pipenv. (PR + #430(3)) + + - Added example of multiple emails to Core Metadata. (PR #429(4)) + + - Added explanation of “legacy” in test.pypi.org/legacy. (PR + #426(5)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/445 + + (2) https://github.com/pypa/packaging.python.org/pull/439 + + (3) https://github.com/pypa/packaging.python.org/pull/430 + + (4) https://github.com/pypa/packaging.python.org/pull/429 + + (5) https://github.com/pypa/packaging.python.org/pull/426 + + +File: pythonpackagingguide.info, Node: January 2018, Next: December 2017, Prev: February 2018, Up: News + +10.21 January 2018 +================== + + - Added a link to PyPI’s list of classifiers. (PR #425(1)) + + - Updated README.rst explanation. (PR #419(2)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/425 + + (2) https://github.com/pypa/packaging.python.org/pull/419 + + +File: pythonpackagingguide.info, Node: December 2017, Next: November 2017, Prev: January 2018, Up: News + +10.22 December 2017 +=================== + + - Replaced ‘~’ with ‘$HOME’ in guides and tutorials. (PR #418(1)) + + - Noted which fields can be used with environment markers. (PR + #416(2)) + + - Updated Requires-Python section. (PR #414(3)) + + - Added news page. (PR #404(4)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/418 + + (2) https://github.com/pypa/packaging.python.org/pull/416 + + (3) https://github.com/pypa/packaging.python.org/pull/414 + + (4) https://github.com/pypa/packaging.python.org/pull/404 + + +File: pythonpackagingguide.info, Node: November 2017, Next: October 2017, Prev: December 2017, Up: News + +10.23 November 2017 +=================== + + - Introduced a new dependency management tutorial based on Pipenv. + (PR #402(1)) + + - Updated the `Single Sourcing Package Version' tutorial to reflect + pip’s current strategy. (PR #400(2)) + + - Added documentation about the ‘py_modules’ argument to ‘setup’. + (PR #398(3)) + + - Simplified the wording for the ‘manifest.in’ section. (PR #395(4)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/402 + + (2) https://github.com/pypa/packaging.python.org/pull/400 + + (3) https://github.com/pypa/packaging.python.org/pull/398 + + (4) https://github.com/pypa/packaging.python.org/pull/395 + + +File: pythonpackagingguide.info, Node: October 2017, Next: September 2017, Prev: November 2017, Up: News + +10.24 October 2017 +================== + + - Added a specification for the ‘entry_points.txt’ file. (PR + #398(1)) + + - Created a new guide for managing packages using ‘pip’ and + ‘virtualenv’. (PR #385(2)) + + - Split the specifications page into multiple pages. (PR #386(3)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/398 + + (2) https://github.com/pypa/packaging.python.org/pull/385 + + (3) https://github.com/pypa/packaging.python.org/pull/386 + + +File: pythonpackagingguide.info, Node: September 2017, Next: August 2017, Prev: October 2017, Up: News + +10.25 September 2017 +==================== + + - Encouraged using ‘readme_renderer’ to validate ‘README.rst’. (PR + #379(1)) + + - Recommended using the ‘--user-base’ option. (PR #374(2)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/379 + + (2) https://github.com/pypa/packaging.python.org/pull/374 + + +File: pythonpackagingguide.info, Node: August 2017, Next: July 2017, Prev: September 2017, Up: News + +10.26 August 2017 +================= + + - Added a new, experimental tutorial on installing packages using + ‘Pipenv’. (PR #369(1)) + + - Added a new guide on how to use ‘TestPyPI’. (PR #366(2)) + + - Added ‘pypi.org’ as a term. (PR #365(3)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/369 + + (2) https://github.com/pypa/packaging.python.org/pull/366 + + (3) https://github.com/pypa/packaging.python.org/pull/365 + + +File: pythonpackagingguide.info, Node: July 2017, Next: June 2017, Prev: August 2017, Up: News + +10.27 July 2017 +=============== + + - Added ‘flit’ to the key projects list. (PR #358(1)) + + - Added ‘enscons’ to the list of key projects. (PR #357(2)) + + - Updated this guide’s ‘readme’ with instructions on how to build the + guide locally. (PR #356(3)) + + - Made the new ‘TestPyPI’ URL more visible, adding note to homepage + about pypi.org. (PR #354(4)) + + - Added a note about the removal of the explicit registration API. + (PR #347(5)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/358 + + (2) https://github.com/pypa/packaging.python.org/pull/357 + + (3) https://github.com/pypa/packaging.python.org/pull/356 + + (4) https://github.com/pypa/packaging.python.org/pull/354 + + (5) https://github.com/pypa/packaging.python.org/pull/347 + + +File: pythonpackagingguide.info, Node: June 2017, Next: May 2017, Prev: July 2017, Up: News + +10.28 June 2017 +=============== + + - Added a document on migrating uploads to ‘PyPI.org’. (PR #339(1)) + + - Added documentation for ‘python_requires’. (PR #338(2)) + + - Added a note about PyPI migration in the `Tool Recommendations' + tutorial. (PR #335(3)) + + - Added a note that ‘manifest.in’ does not affect wheels. (PR + #332(4)) + + - Added a license section to the distributing guide. (PR #331(5)) + + - Expanded the section on the ‘name’ argument. (PR #329(6)) + + - Adjusted the landing page. (PR #327(7), PR #326(8), PR #324(9)) + + - Updated to Sphinx 1.6.2. (PR #323(10)) + + - Switched to the PyPA theme. (PR #305(11)) + + - Re-organized the documentation into the new structure. (PR + #318(12)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/339 + + (2) https://github.com/pypa/packaging.python.org/pull/338 + + (3) https://github.com/pypa/packaging.python.org/pull/335 + + (4) https://github.com/pypa/packaging.python.org/pull/332 + + (5) https://github.com/pypa/packaging.python.org/pull/331 + + (6) https://github.com/pypa/packaging.python.org/pull/329 + + (7) https://github.com/pypa/packaging.python.org/pull/327 + + (8) https://github.com/pypa/packaging.python.org/pull/326 + + (9) https://github.com/pypa/packaging.python.org/pull/324 + + (10) https://github.com/pypa/packaging.python.org/pull/323 + + (11) https://github.com/pypa/packaging.python.org/pull/305 + + (12) https://github.com/pypa/packaging.python.org/pull/318 + + +File: pythonpackagingguide.info, Node: May 2017, Next: April 2017, Prev: June 2017, Up: News + +10.29 May 2017 +============== + + - Added documentation for the ‘Description-Content-Type’ field. (PR + #258(1)) + + - Added contributor and style guide. (PR #307(2)) + + - Documented ‘pip’ and ‘easy_install’’s differences for per-project + indexes. (PR #233(3)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/258 + + (2) https://github.com/pypa/packaging.python.org/pull/307 + + (3) https://github.com/pypa/packaging.python.org/pull/233 + + +File: pythonpackagingguide.info, Node: April 2017, Next: March 2017, Prev: May 2017, Up: News + +10.30 April 2017 +================ + + - Added travis configuration for testing pull requests. (PR #300(1)) + + - Mentioned the requirement of the ‘wheel’ package for creating + wheels (PR #299(2)) + + - Removed the ‘twine register’ reference in the `Distributing + Packages' tutorial. (PR #271(3)) + + - Added a topic on plugin discovery. (PR #294(4), PR #296(5)) + + - Added a topic on namespace packages. (PR #290(6)) + + - Added documentation explaining prominently how to install ‘pip’ in + ‘/usr/local’. (PR #230(7)) + + - Updated development mode documentation to mention that order of + local packages matters. (PR #208(8)) + + - Convert readthedocs link for their ‘.org’ -> ‘.io’ migration for + hosted projects (PR #239(9)) + + - Swaped order of ‘setup.py’ arguments for the upload command, as + order is significant. (PR #260(10)) + + - Explained how to install from unsupported sources using a helper + application. (PR #289(11)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/300 + + (2) https://github.com/pypa/packaging.python.org/pull/299 + + (3) https://github.com/pypa/packaging.python.org/pull/271 + + (4) https://github.com/pypa/packaging.python.org/pull/294 + + (5) https://github.com/pypa/packaging.python.org/pull/296 + + (6) https://github.com/pypa/packaging.python.org/pull/290 + + (7) https://github.com/pypa/packaging.python.org/pull/230 + + (8) https://github.com/pypa/packaging.python.org/pull/208 + + (9) https://github.com/pypa/packaging.python.org/pull/239 + + (10) https://github.com/pypa/packaging.python.org/pull/260 + + (11) https://github.com/pypa/packaging.python.org/pull/289 + + +File: pythonpackagingguide.info, Node: March 2017, Next: February 2017, Prev: April 2017, Up: News + +10.31 March 2017 +================ + + - Covered ‘manylinux1’ in `Platform Wheels'. (PR #283(1)) + + ---------- Footnotes ---------- + + (1) https://github.com/pypa/packaging.python.org/pull/283 + + +File: pythonpackagingguide.info, Node: February 2017, Prev: March 2017, Up: News + +10.32 February 2017 +=================== + + - Added PEP 518(1). (PR #281(2)) + +Welcome to the `Python Packaging User Guide', a collection of tutorials +and references to help you distribute and install Python packages with +modern tools. + +This guide is maintained on GitHub(3) by the Python Packaging +Authority(4). We happily accept any *note contributions and feedback: +299. 😊 + + ---------- Footnotes ---------- + + (1) https://www.python.org/dev/peps/pep-0518 + + (2) https://github.com/pypa/packaging.python.org/pull/281 + + (3) https://github.com/pypa/packaging.python.org + + (4) https://www.pypa.io/en/latest/ + + +File: pythonpackagingguide.info, Node: Get started, Next: Learn more, Prev: News, Up: Top + +11 Get started +************** + +Essential tools and concepts for working within the Python development +ecosystem are covered in our *note Tutorials: 20. section: + + * To learn how to install packages, see the *note tutorial on + installing packages: 23. + + * To learn how to manage dependencies in a version controlled + project, see the *note tutorial on managing application + dependencies: 4a. + + * To learn how to package and distribute your projects, see the *note + tutorial on packaging and distributing: e. + + * To get an overview of packaging options for Python libraries and + applications, see the *note Overview of Python Packaging: 1. + + +File: pythonpackagingguide.info, Node: Learn more, Next: Index, Prev: Get started, Up: Top + +12 Learn more +************* + +Beyond our *note Tutorials: 20, this guide has several other resources: + + * The *note Guides: 22. section for walk throughs, such as *note + Installing pip/setuptools/wheel with Linux Package Managers: 2c. or + *note Packaging binary extensions: 70. + + * The *note Discussions: 181. section for in-depth references on + topics such as *note Deploying Python applications: 184. or *note + pip vs easy_install: 194. + + * The *note PyPA specifications: 1a0. section for packaging + interoperability specifications. + +Additionally, there is a list of *note other projects: 249. maintained +by members of the Python Packaging Authority. + + +File: pythonpackagingguide.info, Node: Index, Prev: Learn more, Up: Top + +Index +***** + +[index] +* Menu: + +* Binary Distribution: Glossary. (line 6) +* Built Distribution: Glossary. (line 9) +* Distribution Package: Glossary. (line 19) +* Egg: Glossary. (line 34) +* environment variable; PATH: Installing to the User Site. + (line 21) +* environment variable; PATH <1>: Installing to the User Site. + (line 22) +* environment variable; PATH <2>: Installing to the User Site. + (line 24) +* Extension Module: Glossary. (line 41) +* Import Package: Glossary. (line 58) +* Known Good Set (KGS): Glossary. (line 50) +* Module: Glossary. (line 68) +* Package Index: Glossary. (line 74) +* PATH: Installing to the User Site. + (line 21) +* PATH <1>: Installing to the User Site. + (line 22) +* PATH <2>: Installing to the User Site. + (line 24) +* Per Project Index: Glossary. (line 78) +* Project: Glossary. (line 84) +* Pure Module: Glossary. (line 108) +* pypi.org: Glossary. (line 127) +* pyproject.toml: Glossary. (line 134) +* Python Enhancement Proposals; PEP 1: History and change workflow. + (line 9) +* Python Enhancement Proposals; PEP 301: Classifier multiple use. + (line 9) +* Python Enhancement Proposals; PEP 345: Version specifiers. (line 10) +* Python Enhancement Proposals; PEP 345 <1>: Dependency specifiers. + (line 10) +* Python Enhancement Proposals; PEP 376: Wheel vs Egg. (line 33) +* Python Enhancement Proposals; PEP 376 <1>: History and change workflow. + (line 6) +* Python Enhancement Proposals; PEP 376 <2>: File format. (line 8) +* Python Enhancement Proposals; PEP 397: console_scripts. (line 27) +* Python Enhancement Proposals; PEP 420: Creating a namespace package. + (line 10) +* Python Enhancement Proposals; PEP 420 <1>: Native namespace packages. + (line 6) +* Python Enhancement Proposals; PEP 425: Pure Python Wheels. (line 16) +* Python Enhancement Proposals; PEP 425 <1>: Platform Wheels. (line 17) +* Python Enhancement Proposals; PEP 425 <2>: Wheel vs Egg. (line 36) +* Python Enhancement Proposals; PEP 425 <3>: Platform compatibility tags. + (line 12) +* Python Enhancement Proposals; PEP 425 <4>: Platform tags for Windows. + (line 6) +* Python Enhancement Proposals; PEP 425 <5>: Platform tags for macOS Mac OS X. + (line 6) +* Python Enhancement Proposals; PEP 425 <6>: Platform tags for common Linux distributions. + (line 6) +* Python Enhancement Proposals; PEP 425 <7>: Platform tags for other *nix platforms. + (line 6) +* Python Enhancement Proposals; PEP 427: Wheel vs Egg. (line 12) +* Python Enhancement Proposals; PEP 427 <1>: Wheel vs Egg. (line 21) +* Python Enhancement Proposals; PEP 427 <2>: File format. (line 8) +* Python Enhancement Proposals; PEP 427 <3>: Binary distribution format. + (line 7) +* Python Enhancement Proposals; PEP 427 <4>: Changes. (line 6) +* Python Enhancement Proposals; PEP 427 <5>: Glossary. (line 214) +* Python Enhancement Proposals; PEP 427#is-it-possible-to-import-python-code-directly-from-a-wheel-file: Wheel vs Egg. + (line 57) +* Python Enhancement Proposals; PEP 438: pip vs easy_install. (line 38) +* Python Enhancement Proposals; PEP 440: Installing from PyPI. + (line 9) +* Python Enhancement Proposals; PEP 440 <1>: Installing from PyPI. + (line 46) +* Python Enhancement Proposals; PEP 440 <2>: Configuring metadata. + (line 66) +* Python Enhancement Proposals; PEP 440 <3>: Configuring metadata. + (line 167) +* Python Enhancement Proposals; PEP 440 <4>: python_requires. (line 7) +* Python Enhancement Proposals; PEP 440 <5>: Standards compliance for interoperability. + (line 8) +* Python Enhancement Proposals; PEP 440 <6>: Standards compliance for interoperability. + (line 24) +* Python Enhancement Proposals; PEP 440 <7>: Metadata-Version. + (line 14) +* Python Enhancement Proposals; PEP 440 <8>: Version. (line 9) +* Python Enhancement Proposals; PEP 440 <9>: Requires-External multiple use. + (line 22) +* Python Enhancement Proposals; PEP 440 <10>: Version specifiers. + (line 7) +* Python Enhancement Proposals; PEP 440 <11>: version<2>. (line 10) +* Python Enhancement Proposals; PEP 440 <12>: Escaping and Unicode. + (line 18) +* Python Enhancement Proposals; PEP 440 <13>: Glossary. (line 200) +* Python Enhancement Proposals; PEP 440#compatible-release: Installing from PyPI. + (line 29) +* Python Enhancement Proposals; PEP 440#compatible-release <1>: Semantic versioning preferred. + (line 20) +* Python Enhancement Proposals; PEP 440#local-version-identifiers: Local version identifiers. + (line 8) +* Python Enhancement Proposals; PEP 440#normalization: Standards compliance for interoperability. + (line 24) +* Python Enhancement Proposals; PEP 440#normalization <1>: The dist-info directory. + (line 12) +* Python Enhancement Proposals; PEP 440#public-version-identifiers: Standards compliance for interoperability. + (line 8) +* Python Enhancement Proposals; PEP 440#version-specifiers: Installing from PyPI. + (line 10) +* Python Enhancement Proposals; PEP 440#version-specifiers <1>: Glossary. + (line 201) +* Python Enhancement Proposals; PEP 441: pex. (line 8) +* Python Enhancement Proposals; PEP 441 <1>: shiv. (line 9) +* Python Enhancement Proposals; PEP 453: Installation tool recommendations. + (line 30) +* Python Enhancement Proposals; PEP 453 <1>: Installation tool recommendations. + (line 34) +* Python Enhancement Proposals; PEP 453#rationale: Installation tool recommendations. + (line 33) +* Python Enhancement Proposals; PEP 503: Installing from other sources. + (line 7) +* Python Enhancement Proposals; PEP 503 <1>: Hosting your own simple repository. + (line 30) +* Python Enhancement Proposals; PEP 503 <2>: “Manual” repository. + (line 8) +* Python Enhancement Proposals; PEP 503 <3>: Name. (line 26) +* Python Enhancement Proposals; PEP 503 <4>: name<2>. (line 12) +* Python Enhancement Proposals; PEP 503 <5>: Source distribution file name. + (line 8) +* Python Enhancement Proposals; PEP 503 <6>: Escaping and Unicode. + (line 13) +* Python Enhancement Proposals; PEP 503 <7>: Simple repository API. + (line 7) +* Python Enhancement Proposals; PEP 503#normalized-names: The dist-info directory. + (line 12) +* Python Enhancement Proposals; PEP 508: name. (line 9) +* Python Enhancement Proposals; PEP 508 <1>: Name. (line 8) +* Python Enhancement Proposals; PEP 508 <2>: Requires-Dist multiple use. + (line 31) +* Python Enhancement Proposals; PEP 508 <3>: Dependency specifiers. + (line 7) +* Python Enhancement Proposals; PEP 508 <4>: dependencies/optional-dependencies. + (line 6) +* Python Enhancement Proposals; PEP 508 <5>: dependencies/optional-dependencies. + (line 7) +* Python Enhancement Proposals; PEP 508 <6>: dependencies/optional-dependencies. + (line 17) +* Python Enhancement Proposals; PEP 508 <7>: dependencies/optional-dependencies. + (line 22) +* Python Enhancement Proposals; PEP 508 <8>: File format. (line 33) +* Python Enhancement Proposals; PEP 513: Platform Wheels. (line 22) +* Python Enhancement Proposals; PEP 513 <1>: Platform tags for common Linux distributions. + (line 20) +* Python Enhancement Proposals; PEP 517: Other Tools for Application Dependency Management. + (line 23) +* Python Enhancement Proposals; PEP 517 <1>: Creating pyproject toml. + (line 25) +* Python Enhancement Proposals; PEP 517 <2>: Checking out the project and building distributions. + (line 21) +* Python Enhancement Proposals; PEP 517 <3>: Source distribution format. + (line 8) +* Python Enhancement Proposals; PEP 517 <4>: Source trees. (line 9) +* Python Enhancement Proposals; PEP 517 <5>: build. (line 8) +* Python Enhancement Proposals; PEP 518: Creating pyproject toml. + (line 25) +* Python Enhancement Proposals; PEP 518 <1>: Checking out the project and building distributions. + (line 21) +* Python Enhancement Proposals; PEP 518 <2>: Declaring build system dependencies. + (line 7) +* Python Enhancement Proposals; PEP 518 <3>: Source trees. (line 9) +* Python Enhancement Proposals; PEP 518 <4>: Glossary. (line 92) +* Python Enhancement Proposals; PEP 518 <5>: Glossary. (line 138) +* Python Enhancement Proposals; PEP 518 <6>: February 2017. (line 6) +* Python Enhancement Proposals; PEP 566: Core metadata specifications. + (line 28) +* Python Enhancement Proposals; PEP 566 <1>: Core metadata specifications. + (line 33) +* Python Enhancement Proposals; PEP 571: Platform tags for common Linux distributions. + (line 24) +* Python Enhancement Proposals; PEP 582: Other Tools for Application Dependency Management. + (line 20) +* Python Enhancement Proposals; PEP 582 <1>: pdm. (line 8) +* Python Enhancement Proposals; PEP 592: Simple repository API. + (line 8) +* Python Enhancement Proposals; PEP 599: Platform tags for common Linux distributions. + (line 28) +* Python Enhancement Proposals; PEP 600: Platform tags for common Linux distributions. + (line 11) +* Python Enhancement Proposals; PEP 600 <1>: Platform tags for common Linux distributions. + (line 33) +* Python Enhancement Proposals; PEP 610: Recording the Direct URL Origin of installed distributions. + (line 9) +* Python Enhancement Proposals; PEP 621: Other Tools for Application Dependency Management. + (line 23) +* Python Enhancement Proposals; PEP 621 <1>: Declaring project metadata. + (line 6) +* Python Enhancement Proposals; PEP 621 <2>: pdm. (line 11) +* Python Enhancement Proposals; PEP 627: History and change workflow. + (line 7) +* Python Enhancement Proposals; PEP 629: Simple repository API. + (line 9) +* Python Enhancement Proposals; PEP 632: Configuring metadata. + (line 227) +* Python Enhancement Proposals; PEP 643: Dynamic multiple use. + (line 34) +* Python Enhancement Proposals; PEP 658: Simple repository API. + (line 11) +* Python Enhancement Proposals; PEP 685: Provides-Extra multiple use. + (line 8) +* Python Enhancement Proposals; PEP 685 <1>: Dependency specifiers. + (line 12) +* Python Enhancement Proposals; PEP 685 <2>: File format. (line 34) +* Python Package Index (PyPI): Glossary. (line 121) +* Python Packaging Authority (PyPA): Glossary. (line 113) +* Release: Glossary. (line 138) +* Requirement: Glossary. (line 148) +* Requirement Specifier: Glossary. (line 155) +* Requirements File: Glossary. (line 164) +* RFC; RFC 7763: Description-Content-Type. + (line 14) +* RFC; RFC 7764#section-3.2: Description-Content-Type. + (line 50) +* RFC; RFC 7764#section-3.5: Description-Content-Type. + (line 52) +* RFC; RFC 8089: Specification. (line 73) +* RFC; RFC 822: authors/maintainers. (line 22) +* RFC; RFC 822#section-3.1.1: Description. (line 50) +* RFC; RFC 8259: Specification. (line 13) +* setup.cfg: Glossary. (line 173) +* setup.py: Glossary. (line 170) +* Source Archive: Glossary. (line 177) +* Source Distribution (or "sdist"): Glossary. (line 183) +* System Package: Glossary. (line 190) +* Version Specifier: Glossary. (line 195) +* Virtual Environment: Glossary. (line 203) +* Wheel: Glossary. (line 210) +* Working Set: Glossary. (line 216) + + + +Tag Table: +Node: Top410 +Ref: index doc689 +Ref: 0689 +Node: An Overview of Packaging for Python17215 +Ref: overview doc17334 +Ref: 117334 +Ref: overview an-overview-of-packaging-for-python17334 +Ref: 217334 +Ref: overview python-packaging-user-guide17334 +Ref: 317334 +Node: Thinking about deployment18267 +Ref: overview thinking-about-deployment18423 +Ref: 418423 +Node: Packaging Python libraries and tools19354 +Ref: overview packaging-python-libraries-and-tools19548 +Ref: 519548 +Node: Python modules20264 +Ref: overview python-modules20401 +Ref: 820401 +Ref: Python modules-Footnote-121145 +Ref: Python modules-Footnote-221184 +Node: Python source distributions21251 +Ref: overview python-source-distributions21424 +Ref: 921424 +Ref: Python source distributions-Footnote-123257 +Ref: Python source distributions-Footnote-223317 +Ref: Python source distributions-Footnote-323363 +Ref: Python source distributions-Footnote-423402 +Ref: Python source distributions-Footnote-523441 +Ref: Python source distributions-Footnote-623479 +Node: Python binary distributions23520 +Ref: overview python-binary-distributions23670 +Ref: c23670 +Ref: Python binary distributions-Footnote-125215 +Node: Packaging Python applications25267 +Ref: overview packaging-applications25449 +Ref: 725449 +Ref: overview packaging-python-applications25449 +Ref: f25449 +Ref: Packaging Python applications-Footnote-126820 +Node: Depending on a framework26892 +Ref: overview depending-on-a-framework27040 +Ref: 1027040 +Node: Service platforms27977 +Ref: overview service-platforms28114 +Ref: 1128114 +Ref: Service platforms-Footnote-128867 +Ref: Service platforms-Footnote-228941 +Ref: Service platforms-Footnote-328997 +Ref: Service platforms-Footnote-429037 +Ref: Service platforms-Footnote-529096 +Node: Web browsers and mobile applications29135 +Ref: overview web-browsers-and-mobile-applications29272 +Ref: 1229272 +Ref: Web browsers and mobile applications-Footnote-130022 +Ref: Web browsers and mobile applications-Footnote-230048 +Ref: Web browsers and mobile applications-Footnote-330075 +Ref: Web browsers and mobile applications-Footnote-430105 +Node: Depending on a pre-installed Python30153 +Ref: overview depending-on-a-pre-installed-python30365 +Ref: 1330365 +Ref: Depending on a pre-installed Python-Footnote-131423 +Ref: Depending on a pre-installed Python-Footnote-231482 +Ref: Depending on a pre-installed Python-Footnote-331536 +Node: Depending on a separate software distribution ecosystem31595 +Ref: overview depending-on-a-separate-ecosystem31818 +Ref: 1431818 +Ref: overview depending-on-a-separate-software-distribution-ecosystem31818 +Ref: 1531818 +Ref: Depending on a separate software distribution ecosystem-Footnote-133006 +Ref: Depending on a separate software distribution ecosystem-Footnote-233031 +Ref: Depending on a separate software distribution ecosystem-Footnote-333100 +Ref: Depending on a separate software distribution ecosystem-Footnote-433226 +Ref: Depending on a separate software distribution ecosystem-Footnote-533315 +Ref: Depending on a separate software distribution ecosystem-Footnote-633418 +Ref: Depending on a separate software distribution ecosystem-Footnote-733467 +Node: Bringing your own Python executable33503 +Ref: overview bringing-your-own-python33718 +Ref: 1633718 +Ref: overview bringing-your-own-python-executable33718 +Ref: 1733718 +Ref: Bringing your own Python executable-Footnote-134784 +Ref: Bringing your own Python executable-Footnote-234838 +Ref: Bringing your own Python executable-Footnote-334890 +Ref: Bringing your own Python executable-Footnote-434935 +Ref: Bringing your own Python executable-Footnote-534966 +Ref: Bringing your own Python executable-Footnote-635015 +Ref: Bringing your own Python executable-Footnote-735058 +Ref: Bringing your own Python executable-Footnote-835100 +Node: Bringing your own userspace35163 +Ref: overview bringing-your-own-userspace35347 +Ref: 1835347 +Ref: Bringing your own userspace-Footnote-136050 +Ref: Bringing your own userspace-Footnote-236127 +Ref: Bringing your own userspace-Footnote-336157 +Ref: Bringing your own userspace-Footnote-436209 +Ref: Bringing your own userspace-Footnote-536238 +Node: Bringing your own kernel36268 +Ref: overview bringing-your-own-kernel36443 +Ref: 1936443 +Ref: Bringing your own kernel-Footnote-137155 +Ref: Bringing your own kernel-Footnote-237190 +Ref: Bringing your own kernel-Footnote-337246 +Ref: Bringing your own kernel-Footnote-437305 +Ref: Bringing your own kernel-Footnote-537372 +Node: Bringing your own hardware37423 +Ref: overview bringing-your-own-hardware37562 +Ref: 1a37562 +Ref: Bringing your own hardware-Footnote-138470 +Ref: Bringing your own hardware-Footnote-238520 +Node: What about…38553 +Ref: overview what-about38706 +Ref: 1b38706 +Node: Operating system packages38925 +Ref: overview operating-system-packages39033 +Ref: 1c39033 +Ref: Operating system packages-Footnote-139719 +Ref: Operating system packages-Footnote-239775 +Ref: Operating system packages-Footnote-339833 +Node: virtualenv39909 +Ref: overview virtualenv40034 +Ref: 1d40034 +Ref: virtualenv-Footnote-140664 +Ref: virtualenv-Footnote-240719 +Ref: virtualenv-Footnote-340788 +Node: Security40831 +Ref: overview security40922 +Ref: 1e40922 +Ref: Security-Footnote-141540 +Node: Wrap up41618 +Ref: overview wrap-up41733 +Ref: 1f41733 +Node: Tutorials42124 +Ref: tutorials/index doc42246 +Ref: 2042246 +Ref: tutorials/index tutorials42246 +Ref: 2142246 +Node: Installing Packages42582 +Ref: tutorials/installing-packages doc42703 +Ref: 2342703 +Ref: tutorials/installing-packages id142703 +Ref: 2442703 +Ref: tutorials/installing-packages installing-packages42703 +Ref: 2542703 +Node: Requirements for Installing Packages43907 +Ref: tutorials/installing-packages installing-requirements44051 +Ref: 2644051 +Ref: tutorials/installing-packages requirements-for-installing-packages44051 +Ref: 2744051 +Node: Ensure you can run Python from the command line44519 +Ref: tutorials/installing-packages ensure-you-can-run-python-from-the-command-line44706 +Ref: 2844706 +Ref: Ensure you can run Python from the command line-Footnote-147046 +Ref: Ensure you can run Python from the command line-Footnote-247077 +Ref: Ensure you can run Python from the command line-Footnote-347151 +Node: Ensure you can run pip from the command line47257 +Ref: tutorials/installing-packages ensure-you-can-run-pip-from-the-command-line47499 +Ref: 2947499 +Ref: tutorials/installing-packages python-org47499 +Ref: 2a47499 +Ref: Ensure you can run pip from the command line-Footnote-149125 +Ref: Ensure you can run pip from the command line-Footnote-249156 +Ref: Ensure you can run pip from the command line-Footnote-349180 +Ref: Ensure you can run pip from the command line-Footnote-449225 +Ref: Ensure you can run pip from the command line-Footnote-549386 +Node: Ensure pip setuptools and wheel are up to date49616 +Ref: tutorials/installing-packages ensure-pip-setuptools-and-wheel-are-up-to-date49850 +Ref: 2f49850 +Node: Optionally create a virtual environment50312 +Ref: tutorials/installing-packages optionally-create-a-virtual-environment50493 +Ref: 3050493 +Ref: Optionally create a virtual environment-Footnote-151074 +Ref: Optionally create a virtual environment-Footnote-251126 +Node: Creating Virtual Environments51354 +Ref: tutorials/installing-packages creating-and-using-virtual-environments51529 +Ref: 3151529 +Ref: tutorials/installing-packages creating-virtual-environments51529 +Ref: 3351529 +Ref: Creating Virtual Environments-Footnote-154461 +Ref: Creating Virtual Environments-Footnote-254513 +Ref: Creating Virtual Environments-Footnote-354565 +Ref: Creating Virtual Environments-Footnote-454617 +Node: Use pip for Installing54673 +Ref: tutorials/installing-packages use-pip-for-installing54832 +Ref: 3754832 +Ref: Use pip for Installing-Footnote-155113 +Ref: Use pip for Installing-Footnote-255152 +Node: Installing from PyPI55195 +Ref: tutorials/installing-packages installing-from-pypi55355 +Ref: 3855355 +Ref: Installing from PyPI-Footnote-156599 +Ref: Installing from PyPI-Footnote-256648 +Ref: Installing from PyPI-Footnote-356716 +Ref: Installing from PyPI-Footnote-456784 +Node: Source Distributions vs Wheels56975 +Ref: tutorials/installing-packages source-distributions-vs-wheels57131 +Ref: 3c57131 +Ref: Source Distributions vs Wheels-Footnote-157890 +Node: Upgrading packages57963 +Ref: tutorials/installing-packages upgrading-packages58126 +Ref: 3e58126 +Node: Installing to the User Site58368 +Ref: tutorials/installing-packages id658519 +Ref: 3f58519 +Ref: tutorials/installing-packages installing-to-the-user-site58519 +Ref: 4058519 +Ref: Installing to the User Site-Footnote-160489 +Ref: Installing to the User Site-Footnote-260553 +Ref: Installing to the User Site-Footnote-360620 +Ref: Installing to the User Site-Footnote-460665 +Node: Requirements files60774 +Ref: tutorials/installing-packages control-panel60926 +Ref: 4160926 +Ref: tutorials/installing-packages requirements-files60926 +Ref: 4260926 +Ref: Requirements files-Footnote-161196 +Node: Installing from VCS61265 +Ref: tutorials/installing-packages installing-from-vcs61419 +Ref: 4361419 +Ref: Installing from VCS-Footnote-162470 +Node: Installing from other Indexes62537 +Ref: tutorials/installing-packages installing-from-other-indexes62705 +Ref: 4462705 +Node: Installing from a local src tree63266 +Ref: tutorials/installing-packages installing-from-a-local-src-tree63445 +Ref: 4563445 +Ref: Installing from a local src tree-Footnote-163943 +Node: Installing from local archives64021 +Ref: tutorials/installing-packages installing-from-local-archives64200 +Ref: 4664200 +Node: Installing from other sources65039 +Ref: tutorials/installing-packages installing-from-other-sources65208 +Ref: 4765208 +Ref: Installing from other sources-Footnote-165668 +Node: Installing Prereleases65717 +Ref: tutorials/installing-packages installing-prereleases65890 +Ref: 4865890 +Node: Installing Setuptools “Extras”66183 +Ref: tutorials/installing-packages installing-setuptools-extras66318 +Ref: 4966318 +Ref: Installing Setuptools “Extras”-Footnote-166891 +Node: Managing Application Dependencies67003 +Ref: tutorials/managing-dependencies doc67158 +Ref: 4a67158 +Ref: tutorials/managing-dependencies managing-application-dependencies67158 +Ref: 4b67158 +Ref: tutorials/managing-dependencies managing-dependencies67158 +Ref: 3567158 +Ref: tutorials/managing-dependencies setuptools-extras67158 +Ref: 4c67158 +Node: Installing Pipenv68497 +Ref: tutorials/managing-dependencies installing-pipenv68643 +Ref: 4e68643 +Ref: tutorials/managing-dependencies pipenv-user-base69205 +Ref: 4f69205 +Ref: Installing Pipenv-Footnote-169566 +Ref: Installing Pipenv-Footnote-269597 +Ref: Installing Pipenv-Footnote-369625 +Ref: Installing Pipenv-Footnote-469689 +Node: Installing packages for your project69756 +Ref: tutorials/managing-dependencies installing-packages-for-your-project69935 +Ref: 5069935 +Ref: tutorials/managing-dependencies user-installation69935 +Ref: 5169935 +Ref: Installing packages for your project-Footnote-171870 +Node: Using installed packages71913 +Ref: tutorials/managing-dependencies requests72085 +Ref: 5372085 +Ref: tutorials/managing-dependencies using-installed-packages72085 +Ref: 5472085 +Node: Next steps72751 +Ref: tutorials/managing-dependencies next-steps72936 +Ref: 5572936 +Node: Other Tools for Application Dependency Management73553 +Ref: tutorials/managing-dependencies other-dependency-management-tools73705 +Ref: 5773705 +Ref: tutorials/managing-dependencies other-tools-for-application-dependency-management73705 +Ref: 4d73705 +Ref: Other Tools for Application Dependency Management-Footnote-175403 +Ref: Other Tools for Application Dependency Management-Footnote-275441 +Ref: Other Tools for Application Dependency Management-Footnote-375494 +Ref: Other Tools for Application Dependency Management-Footnote-475537 +Ref: Other Tools for Application Dependency Management-Footnote-575586 +Ref: Other Tools for Application Dependency Management-Footnote-675635 +Ref: Other Tools for Application Dependency Management-Footnote-775684 +Ref: Other Tools for Application Dependency Management-Footnote-875730 +Node: Packaging Python Projects75778 +Ref: tutorials/packaging-projects doc75936 +Ref: e75936 +Ref: tutorials/packaging-projects packaging-python-projects75936 +Ref: 5875936 +Ref: Packaging Python Projects-Footnote-177137 +Ref: Packaging Python Projects-Footnote-277338 +Node: A simple project77389 +Ref: tutorials/packaging-projects a-simple-project77516 +Ref: 5977516 +Ref: A simple project-Footnote-178614 +Node: Creating the package files78679 +Ref: tutorials/packaging-projects creating-the-package-files78840 +Ref: 5b78840 +Ref: tutorials/packaging-projects python-documentation-for-packages-and-modules78840 +Ref: 5c78840 +Node: Creating a test directory79338 +Ref: tutorials/packaging-projects creating-a-test-directory79506 +Ref: 5d79506 +Node: Creating pyproject toml79643 +Ref: tutorials/packaging-projects creating-pyproject-toml79805 +Ref: 5e79805 +Ref: Creating pyproject toml-Footnote-180818 +Ref: Creating pyproject toml-Footnote-280867 +Node: Configuring metadata80916 +Ref: tutorials/packaging-projects configuring-metadata81071 +Ref: 6281071 +Ref: Configuring metadata-Footnote-191589 +Ref: Configuring metadata-Footnote-291676 +Ref: Configuring metadata-Footnote-391736 +Ref: Configuring metadata-Footnote-491785 +Ref: Configuring metadata-Footnote-591834 +Ref: Configuring metadata-Footnote-692373 +Node: Creating README md92422 +Ref: tutorials/packaging-projects creating-readme-md92572 +Ref: 6392572 +Node: Creating a LICENSE93171 +Ref: tutorials/packaging-projects creating-a-license93322 +Ref: 6593322 +Node: Including other files94912 +Ref: tutorials/packaging-projects including-other-files95077 +Ref: 6695077 +Ref: Including other files-Footnote-195627 +Ref: Including other files-Footnote-295697 +Node: Generating distribution archives95753 +Ref: tutorials/packaging-projects generating-archives95935 +Ref: 6495935 +Ref: tutorials/packaging-projects generating-distribution-archives95935 +Ref: 6995935 +Node: Uploading the distribution archives97362 +Ref: tutorials/packaging-projects uploading-the-distribution-archives97561 +Ref: 6b97561 +Ref: Uploading the distribution archives-Footnote-199892 +Node: Installing your newly uploaded package99937 +Ref: tutorials/packaging-projects installing-your-newly-uploaded-package100117 +Ref: 6e100117 +Node: Next steps<2>102084 +Ref: tutorials/packaging-projects next-steps102220 +Ref: 6f102220 +Node: Creating Documentation103980 +Ref: tutorials/creating-documentation doc104096 +Ref: 72104096 +Ref: tutorials/creating-documentation creating-documentation104096 +Ref: 73104096 +Ref: tutorials/creating-documentation id1104096 +Ref: 74104096 +Ref: Creating Documentation-Footnote-1104405 +Ref: Creating Documentation-Footnote-2104440 +Node: Installing Sphinx104473 +Ref: tutorials/creating-documentation installing-sphinx104599 +Ref: 75104599 +Ref: tutorials/creating-documentation read-the-docs104599 +Ref: 76104599 +Ref: Installing Sphinx-Footnote-1104887 +Node: Getting Started With Sphinx104956 +Ref: tutorials/creating-documentation getting-started-with-sphinx105104 +Ref: 77105104 +Ref: Getting Started With Sphinx-Footnote-1105755 +Node: Other Sources105825 +Ref: tutorials/creating-documentation guide105947 +Ref: 78105947 +Ref: tutorials/creating-documentation other-sources105947 +Ref: 79105947 +Ref: Other Sources-Footnote-1106171 +Node: Guides106232 +Ref: guides/index doc106330 +Ref: 22106330 +Ref: guides/index documentation-tutorial106330 +Ref: 7a106330 +Ref: guides/index guides106330 +Ref: 7b106330 +Node: Installing packages using pip and virtual environments107567 +Ref: guides/installing-using-pip-and-virtual-environments doc107728 +Ref: 7c107728 +Ref: guides/installing-using-pip-and-virtual-environments installing-packages-using-pip-and-virtual-environments107728 +Ref: 7d107728 +Node: Installing pip108889 +Ref: guides/installing-using-pip-and-virtual-environments installing-pip109038 +Ref: 7f109038 +Ref: Installing pip-Footnote-1110214 +Node: Installing virtualenv110276 +Ref: guides/installing-using-pip-and-virtual-environments installing-virtualenv110464 +Ref: 80110464 +Ref: Installing virtualenv-Footnote-1111206 +Node: Creating a virtual environment111270 +Ref: guides/installing-using-pip-and-virtual-environments creating-a-virtual-environment111476 +Ref: 81111476 +Node: Activating a virtual environment112690 +Ref: guides/installing-using-pip-and-virtual-environments activating-a-virtual-environment112906 +Ref: 82112906 +Node: Leaving the virtual environment113793 +Ref: guides/installing-using-pip-and-virtual-environments leaving-the-virtual-environment113998 +Ref: 83113998 +Node: Installing packages114367 +Ref: guides/installing-using-pip-and-virtual-environments installing-packages114568 +Ref: 84114568 +Ref: Installing packages-Footnote-1115674 +Node: Installing specific versions115717 +Ref: guides/installing-using-pip-and-virtual-environments installing-specific-versions115904 +Ref: 85115904 +Ref: guides/installing-using-pip-and-virtual-environments requests115904 +Ref: 86115904 +Node: Installing extras116597 +Ref: guides/installing-using-pip-and-virtual-environments installing-extras116787 +Ref: 87116787 +Ref: Installing extras-Footnote-1117096 +Node: Installing from source117208 +Ref: guides/installing-using-pip-and-virtual-environments extras117409 +Ref: 88117409 +Ref: guides/installing-using-pip-and-virtual-environments installing-from-source117409 +Ref: 89117409 +Ref: Installing from source-Footnote-1117982 +Node: Installing from version control systems118060 +Ref: guides/installing-using-pip-and-virtual-environments installing-from-version-control-systems118277 +Ref: 8a118277 +Ref: Installing from version control systems-Footnote-1118751 +Node: Installing from local archives<2>118818 +Ref: guides/installing-using-pip-and-virtual-environments installing-from-local-archives119040 +Ref: 8b119040 +Node: Using other package indexes119875 +Ref: guides/installing-using-pip-and-virtual-environments using-other-package-indexes120079 +Ref: 8c120079 +Node: Upgrading packages<2>120843 +Ref: guides/installing-using-pip-and-virtual-environments upgrading-packages121038 +Ref: 8d121038 +Node: Using requirements files121361 +Ref: guides/installing-using-pip-and-virtual-environments using-requirements-files121550 +Ref: 8e121550 +Ref: Using requirements files-Footnote-1122083 +Node: Freezing dependencies122152 +Ref: guides/installing-using-pip-and-virtual-environments freezing-dependencies122311 +Ref: 8f122311 +Ref: Freezing dependencies-Footnote-1122998 +Node: Installing stand alone command line tools123067 +Ref: guides/installing-stand-alone-command-line-tools doc123296 +Ref: 34123296 +Ref: guides/installing-stand-alone-command-line-tools installing-stand-alone-command-line-tools123296 +Ref: 90123296 +Ref: Installing stand alone command line tools-Footnote-1126280 +Ref: Installing stand alone command line tools-Footnote-2126319 +Ref: Installing stand alone command line tools-Footnote-3126359 +Node: Installing pip/setuptools/wheel with Linux Package Managers126396 +Ref: guides/installing-using-linux-tools doc126601 +Ref: 2c126601 +Ref: guides/installing-using-linux-tools id1126601 +Ref: 92126601 +Ref: guides/installing-using-linux-tools installing-pip-setuptools-wheel-with-linux-package-managers126601 +Ref: 93126601 +Ref: Installing pip/setuptools/wheel with Linux Package Managers-Footnote-1127952 +Node: Fedora127983 +Ref: guides/installing-using-linux-tools fedora128119 +Ref: 94128119 +Ref: Fedora-Footnote-1128359 +Ref: Fedora-Footnote-2128451 +Ref: Fedora-Footnote-3128511 +Node: CentOS/RHEL128549 +Ref: guides/installing-using-linux-tools centos-rhel128702 +Ref: 95128702 +Ref: guides/installing-using-linux-tools fedora-loves-python128702 +Ref: 96128702 +Ref: CentOS/RHEL-Footnote-1130375 +Ref: CentOS/RHEL-Footnote-2130419 +Ref: CentOS/RHEL-Footnote-3130506 +Ref: CentOS/RHEL-Footnote-4130565 +Ref: CentOS/RHEL-Footnote-5130644 +Ref: CentOS/RHEL-Footnote-6130797 +Ref: CentOS/RHEL-Footnote-7130826 +Node: openSUSE130885 +Ref: guides/installing-using-linux-tools opensuse131045 +Ref: 97131045 +Node: Debian/Ubuntu131152 +Ref: guides/installing-using-linux-tools debian-ubuntu131311 +Ref: 98131311 +Ref: Debian/Ubuntu-Footnote-1131718 +Node: Arch Linux131782 +Ref: guides/installing-using-linux-tools arch-linux131924 +Ref: 99131924 +Node: Installing scientific packages132064 +Ref: guides/installing-scientific-packages doc132250 +Ref: 9a132250 +Ref: guides/installing-scientific-packages installing-scientific-packages132250 +Ref: 9b132250 +Ref: guides/installing-scientific-packages numpy-and-the-science-stack132250 +Ref: 9c132250 +Ref: Installing scientific packages-Footnote-1133709 +Ref: Installing scientific packages-Footnote-2133736 +Ref: Installing scientific packages-Footnote-3133774 +Node: Building from source133811 +Ref: guides/installing-scientific-packages building-from-source133948 +Ref: 9d133948 +Node: Linux distribution packages134347 +Ref: guides/installing-scientific-packages linux-distribution-packages134511 +Ref: 9e134511 +Node: Windows installers134991 +Ref: guides/installing-scientific-packages windows-installers135172 +Ref: 9f135172 +Ref: Windows installers-Footnote-1136423 +Node: macOS installers and package managers136475 +Ref: guides/installing-scientific-packages mac-os-x-installers-and-package-managers136648 +Ref: a0136648 +Ref: guides/installing-scientific-packages macos-installers-and-package-managers136648 +Ref: a1136648 +Ref: macOS installers and package managers-Footnote-1137125 +Node: SciPy distributions137164 +Ref: guides/installing-scientific-packages scipy-distributions137324 +Ref: a2137324 +Ref: SciPy distributions-Footnote-1137661 +Node: Spack137710 +Ref: guides/installing-scientific-packages spack137873 +Ref: a3137873 +Ref: Spack-Footnote-1138919 +Node: The conda cross-platform package manager138958 +Ref: guides/installing-scientific-packages the-conda-cross-platform-package-manager139093 +Ref: a4139093 +Ref: The conda cross-platform package manager-Footnote-1140449 +Node: Multi-version installs140503 +Ref: guides/multi-version-installs doc140662 +Ref: a5140662 +Ref: guides/multi-version-installs id1140662 +Ref: a6140662 +Ref: guides/multi-version-installs multi-version-installs140662 +Ref: a7140662 +Ref: Multi-version installs-Footnote-1142571 +Node: Package index mirrors and caches142662 +Ref: guides/index-mirrors-and-caches doc142825 +Ref: a8142825 +Ref: guides/index-mirrors-and-caches package-index-mirrors-and-caches142825 +Ref: a9142825 +Ref: guides/index-mirrors-and-caches pypi-mirrors-and-caches142825 +Ref: aa142825 +Node: Caching with pip143492 +Ref: guides/index-mirrors-and-caches caching-with-pip143618 +Ref: ab143618 +Ref: Caching with pip-Footnote-1144266 +Ref: Caching with pip-Footnote-2144348 +Node: Caching with devpi144411 +Ref: guides/index-mirrors-and-caches caching-with-devpi144579 +Ref: ac144579 +Ref: Caching with devpi-Footnote-1144846 +Node: Complete mirror with bandersnatch144927 +Ref: guides/index-mirrors-and-caches complete-mirror-with-bandersnatch145070 +Ref: ad145070 +Ref: guides/index-mirrors-and-caches id1145070 +Ref: ae145070 +Ref: Complete mirror with bandersnatch-Footnote-1145568 +Node: Hosting your own simple repository145614 +Ref: guides/hosting-your-own-index doc145790 +Ref: af145790 +Ref: guides/hosting-your-own-index hosting-your-own-simple-repository145790 +Ref: b0145790 +Ref: guides/hosting-your-own-index id1145790 +Ref: b1145790 +Ref: Hosting your own simple repository-Footnote-1146807 +Ref: Hosting your own simple repository-Footnote-2146937 +Node: “Manual” repository147003 +Ref: guides/hosting-your-own-index manual-repository147111 +Ref: b2147111 +Ref: “Manual” repository-Footnote-1148162 +Ref: “Manual” repository-Footnote-2148211 +Node: Packaging and distributing projects148246 +Ref: guides/distributing-packages-using-setuptools doc148446 +Ref: 6148446 +Ref: guides/distributing-packages-using-setuptools distributing-packages148446 +Ref: 56148446 +Ref: guides/distributing-packages-using-setuptools packaging-and-distributing-projects148446 +Ref: b3148446 +Ref: guides/distributing-packages-using-setuptools twisted148446 +Ref: b4148446 +Ref: Packaging and distributing projects-Footnote-1149534 +Node: Requirements for packaging and distributing149600 +Ref: guides/distributing-packages-using-setuptools requirements-for-packaging-and-distributing149762 +Ref: b5149762 +Ref: Requirements for packaging and distributing-Footnote-1150258 +Node: Configuring your project150488 +Ref: guides/distributing-packages-using-setuptools configuring-your-project150692 +Ref: b7150692 +Node: Initial files150844 +Ref: guides/distributing-packages-using-setuptools initial-files150951 +Ref: b8150951 +Node: setup py151177 +Ref: guides/distributing-packages-using-setuptools setup-py151267 +Ref: b9151267 +Ref: setup py-Footnote-1152098 +Ref: setup py-Footnote-2152163 +Node: setup cfg152209 +Ref: guides/distributing-packages-using-setuptools setup-cfg152330 +Ref: bb152330 +Ref: setup cfg-Footnote-1152563 +Ref: setup cfg-Footnote-2152629 +Node: README rst / README md152675 +Ref: guides/distributing-packages-using-setuptools readme-rst-readme-md152799 +Ref: bc152799 +Ref: README rst / README md-Footnote-1153816 +Ref: README rst / README md-Footnote-2153865 +Ref: README rst / README md-Footnote-3153919 +Ref: README rst / README md-Footnote-4153985 +Node: MANIFEST in154031 +Ref: guides/distributing-packages-using-setuptools manifest-in154157 +Ref: bf154157 +Ref: MANIFEST in-Footnote-1154858 +Node: LICENSE txt154904 +Ref: guides/distributing-packages-using-setuptools license-txt155022 +Ref: c0155022 +Ref: LICENSE txt-Footnote-1155524 +Ref: LICENSE txt-Footnote-2155560 +Ref: LICENSE txt-Footnote-3155628 +Node: 155674 +Ref: guides/distributing-packages-using-setuptools your-package155772 +Ref: c1155772 +Ref: -Footnote-1156159 +Ref: -Footnote-2156226 +Node: setup args156272 +Ref: guides/distributing-packages-using-setuptools id10156416 +Ref: c3156416 +Ref: guides/distributing-packages-using-setuptools setup-args156416 +Ref: ba156416 +Ref: setup args-Footnote-1157105 +Ref: setup args-Footnote-2157170 +Node: name157216 +Ref: guides/distributing-packages-using-setuptools name157297 +Ref: c4157297 +Ref: guides/distributing-packages-using-setuptools setup-name157297 +Ref: c2157297 +Ref: name-Footnote-1158064 +Node: version158113 +Ref: guides/distributing-packages-using-setuptools version158214 +Ref: c5158214 +Node: description159030 +Ref: guides/distributing-packages-using-setuptools description159130 +Ref: bd159130 +Ref: guides/distributing-packages-using-setuptools id13159130 +Ref: c8159130 +Ref: description-Footnote-1160284 +Ref: description-Footnote-2160386 +Ref: description-Footnote-3160478 +Node: url160532 +Ref: guides/distributing-packages-using-setuptools url160631 +Ref: c9160631 +Node: author160756 +Ref: guides/distributing-packages-using-setuptools author160851 +Ref: ca160851 +Node: license161003 +Ref: guides/distributing-packages-using-setuptools license161106 +Ref: cb161106 +Node: classifiers161831 +Ref: guides/distributing-packages-using-setuptools classifiers161936 +Ref: cc161936 +Node: keywords163620 +Ref: guides/distributing-packages-using-setuptools keywords163730 +Ref: ce163730 +Node: project_urls163866 +Ref: guides/distributing-packages-using-setuptools project-urls163973 +Ref: cf163973 +Node: packages164610 +Ref: guides/distributing-packages-using-setuptools packages164719 +Ref: d0164719 +Node: py_modules165238 +Ref: guides/distributing-packages-using-setuptools py-modules165351 +Ref: d1165351 +Node: install_requires165661 +Ref: guides/distributing-packages-using-setuptools install-requires165781 +Ref: d2165781 +Node: python_requires166196 +Ref: guides/distributing-packages-using-setuptools id15166318 +Ref: d4166318 +Ref: guides/distributing-packages-using-setuptools python-requires166318 +Ref: cd166318 +Ref: python_requires-Footnote-1167542 +Node: package_data167591 +Ref: guides/distributing-packages-using-setuptools id16167707 +Ref: d6167707 +Ref: guides/distributing-packages-using-setuptools package-data167707 +Ref: d7167707 +Ref: package_data-Footnote-1168447 +Ref: package_data-Footnote-2168517 +Node: data_files168573 +Ref: guides/distributing-packages-using-setuptools data-files168681 +Ref: d8168681 +Ref: guides/distributing-packages-using-setuptools id17168681 +Ref: d9168681 +Ref: data_files-Footnote-1170069 +Ref: data_files-Footnote-2170117 +Node: scripts170206 +Ref: guides/distributing-packages-using-setuptools scripts170314 +Ref: da170314 +Ref: scripts-Footnote-1170620 +Node: entry_points170711 +Ref: guides/distributing-packages-using-setuptools entry-points170800 +Ref: dc170800 +Ref: entry_points-Footnote-1171297 +Node: console_scripts171412 +Ref: guides/distributing-packages-using-setuptools console-scripts171490 +Ref: db171490 +Ref: guides/distributing-packages-using-setuptools id18171490 +Ref: dd171490 +Ref: console_scripts-Footnote-1172035 +Ref: console_scripts-Footnote-2172150 +Ref: console_scripts-Footnote-3172494 +Ref: console_scripts-Footnote-4172616 +Node: Choosing a versioning scheme172672 +Ref: guides/distributing-packages-using-setuptools choosing-a-versioning-scheme172794 +Ref: c6172794 +Ref: guides/distributing-packages-using-setuptools id20172794 +Ref: de172794 +Node: Standards compliance for interoperability173003 +Ref: guides/distributing-packages-using-setuptools standards-compliance-for-interoperability173146 +Ref: df173146 +Ref: Standards compliance for interoperability-Footnote-1174172 +Ref: Standards compliance for interoperability-Footnote-2174249 +Ref: Standards compliance for interoperability-Footnote-3174298 +Ref: Standards compliance for interoperability-Footnote-4174347 +Node: Scheme choices174410 +Ref: guides/distributing-packages-using-setuptools scheme-choices174584 +Ref: e0174584 +Node: Semantic versioning preferred174776 +Ref: guides/distributing-packages-using-setuptools semantic-versioning-preferred174900 +Ref: e1174900 +Ref: Semantic versioning preferred-Footnote-1175894 +Ref: Semantic versioning preferred-Footnote-2175922 +Ref: Semantic versioning preferred-Footnote-3175990 +Node: Date based versioning176018 +Ref: guides/distributing-packages-using-setuptools date-based-versioning176168 +Ref: e2176168 +Node: Serial versioning176743 +Ref: guides/distributing-packages-using-setuptools serial-versioning176878 +Ref: e3176878 +Node: Hybrid schemes177255 +Ref: guides/distributing-packages-using-setuptools hybrid-schemes177360 +Ref: e4177360 +Node: Pre-release versioning177715 +Ref: guides/distributing-packages-using-setuptools pre-release-versioning177873 +Ref: e5177873 +Node: Local version identifiers178459 +Ref: guides/distributing-packages-using-setuptools local-version-identifiers178594 +Ref: e6178594 +Ref: Local version identifiers-Footnote-1179310 +Node: Working in “development mode”179386 +Ref: guides/distributing-packages-using-setuptools working-in-development-mode179569 +Ref: e7179569 +Ref: Working in “development mode”-Footnote-1181753 +Ref: Working in “development mode”-Footnote-2181822 +Ref: Working in “development mode”-Footnote-3181889 +Ref: Working in “development mode”-Footnote-4181967 +Node: Packaging your project182028 +Ref: guides/distributing-packages-using-setuptools id21182217 +Ref: e8182217 +Ref: guides/distributing-packages-using-setuptools packaging-your-project182217 +Ref: d5182217 +Node: Source distributions182700 +Ref: guides/distributing-packages-using-setuptools source-distributions182808 +Ref: ea182808 +Node: Wheels183336 +Ref: guides/distributing-packages-using-setuptools wheels183444 +Ref: eb183444 +Node: Pure Python Wheels184416 +Ref: guides/distributing-packages-using-setuptools id22184515 +Ref: ee184515 +Ref: guides/distributing-packages-using-setuptools pure-python-wheels184515 +Ref: ec184515 +Ref: Pure Python Wheels-Footnote-1185172 +Node: Platform Wheels185221 +Ref: guides/distributing-packages-using-setuptools id23185320 +Ref: ef185320 +Ref: guides/distributing-packages-using-setuptools platform-wheels185320 +Ref: ed185320 +Ref: Platform Wheels-Footnote-1186078 +Ref: Platform Wheels-Footnote-2186127 +Node: Uploading your Project to PyPI186176 +Ref: guides/distributing-packages-using-setuptools id24186323 +Ref: f0186323 +Ref: guides/distributing-packages-using-setuptools uploading-your-project-to-pypi186323 +Ref: b6186323 +Ref: Uploading your Project to PyPI-Footnote-1188159 +Node: Create an account188190 +Ref: guides/distributing-packages-using-setuptools create-an-account188322 +Ref: f2188322 +Ref: guides/distributing-packages-using-setuptools register-your-project189244 +Ref: f4189244 +Ref: Create an account-Footnote-1189281 +Ref: Create an account-Footnote-2189324 +Ref: Create an account-Footnote-3189364 +Node: Upload your distributions189404 +Ref: guides/distributing-packages-using-setuptools api-token189536 +Ref: f5189536 +Ref: guides/distributing-packages-using-setuptools upload-your-distributions189536 +Ref: f6189536 +Node: Including files in source distributions with MANIFEST in190419 +Ref: guides/using-manifest-in doc190620 +Ref: f7190620 +Ref: guides/using-manifest-in including-files-in-source-distributions-with-manifest-in190620 +Ref: f8190620 +Ref: guides/using-manifest-in using-manifest-in190620 +Ref: 67190620 +Node: How files are included in an sdist191618 +Ref: guides/using-manifest-in how-files-are-included-in-an-sdist191788 +Ref: f9191788 +Node: MANIFEST in commands193476 +Ref: guides/using-manifest-in manifest-in-commands193646 +Ref: fa193646 +Node: Single-sourcing the package version198169 +Ref: guides/single-sourcing-package-version doc198370 +Ref: fb198370 +Ref: guides/single-sourcing-package-version single-sourcing-the-package-version198370 +Ref: fc198370 +Ref: guides/single-sourcing-package-version single-sourcing-the-version198370 +Ref: c7198370 +Ref: Single-sourcing the package version-Footnote-1203911 +Ref: Single-sourcing the package version-Footnote-2203970 +Ref: Single-sourcing the package version-Footnote-3204016 +Ref: Single-sourcing the package version-Footnote-4204057 +Ref: Single-sourcing the package version-Footnote-5204101 +Ref: Single-sourcing the package version-Footnote-6204148 +Ref: Single-sourcing the package version-Footnote-7204260 +Ref: Single-sourcing the package version-Footnote-8204336 +Node: Supporting multiple Python versions204385 +Ref: guides/supporting-multiple-python-versions doc204572 +Ref: fd204572 +Ref: guides/supporting-multiple-python-versions id1204572 +Ref: fe204572 +Ref: guides/supporting-multiple-python-versions supporting-multiple-python-versions204572 +Ref: ff204572 +Node: Automated testing and continuous integration206318 +Ref: guides/supporting-multiple-python-versions automated-testing-and-continuous-integration206496 +Ref: 100206496 +Ref: Automated testing and continuous integration-Footnote-1208115 +Ref: Automated testing and continuous integration-Footnote-2208142 +Ref: Automated testing and continuous integration-Footnote-3208172 +Ref: Automated testing and continuous integration-Footnote-4208257 +Ref: Automated testing and continuous integration-Footnote-5208287 +Ref: Automated testing and continuous integration-Footnote-6208321 +Ref: Automated testing and continuous integration-Footnote-7208351 +Ref: Automated testing and continuous integration-Footnote-8208385 +Node: Tools for single-source Python packages208410 +Ref: guides/supporting-multiple-python-versions tools-for-single-source-python-packages208622 +Ref: 101208622 +Ref: Tools for single-source Python packages-Footnote-1210451 +Ref: Tools for single-source Python packages-Footnote-2210489 +Ref: Tools for single-source Python packages-Footnote-3210527 +Ref: Tools for single-source Python packages-Footnote-4210565 +Ref: Tools for single-source Python packages-Footnote-5210608 +Ref: Tools for single-source Python packages-Footnote-6210646 +Ref: Tools for single-source Python packages-Footnote-7210684 +Ref: Tools for single-source Python packages-Footnote-8210731 +Ref: Tools for single-source Python packages-Footnote-9210769 +Ref: Tools for single-source Python packages-Footnote-10210816 +Ref: Tools for single-source Python packages-Footnote-11210855 +Ref: Tools for single-source Python packages-Footnote-12210903 +Ref: Tools for single-source Python packages-Footnote-13210947 +Ref: Tools for single-source Python packages-Footnote-14210986 +Ref: Tools for single-source Python packages-Footnote-15211034 +Ref: Tools for single-source Python packages-Footnote-16211073 +Ref: Tools for single-source Python packages-Footnote-17211121 +Node: What’s in which Python?211169 +Ref: guides/supporting-multiple-python-versions what-s-in-which-python211328 +Ref: 102211328 +Ref: What’s in which Python?-Footnote-1211781 +Ref: What’s in which Python?-Footnote-2211854 +Ref: What’s in which Python?-Footnote-3211930 +Node: Dropping support for older Python versions212009 +Ref: guides/dropping-older-python-versions doc212188 +Ref: 103212188 +Ref: guides/dropping-older-python-versions dropping-support-for-older-python-versions212188 +Ref: 104212188 +Ref: guides/dropping-older-python-versions id1212188 +Ref: 105212188 +Node: Requirements213226 +Ref: guides/dropping-older-python-versions requirements213373 +Ref: 107213373 +Node: Dealing with the universal wheels213721 +Ref: guides/dropping-older-python-versions dealing-with-the-universal-wheels213913 +Ref: 108213913 +Node: Defining the Python version required214825 +Ref: guides/dropping-older-python-versions defining-the-python-version-required215030 +Ref: 109215030 +Node: 1 Download the newest version of Setuptools215503 +Ref: guides/dropping-older-python-versions download-the-newest-version-of-setuptools215705 +Ref: 10a215705 +Node: 2 Specify the version ranges for supported Python distributions216131 +Ref: guides/dropping-older-python-versions specify-the-version-ranges-for-supported-python-distributions216385 +Ref: 10b216385 +Node: 3 Validating the Metadata before publishing217123 +Ref: guides/dropping-older-python-versions validating-the-metadata-before-publishing217358 +Ref: 10c217358 +Node: 4 Using Twine to publish218165 +Ref: guides/dropping-older-python-versions using-twine-to-publish218328 +Ref: 10d218328 +Node: Dropping a Python release218582 +Ref: guides/dropping-older-python-versions dropping-a-python-release218745 +Ref: 10e218745 +Node: Packaging binary extensions219376 +Ref: guides/packaging-binary-extensions doc219553 +Ref: 70219553 +Ref: guides/packaging-binary-extensions binary-extensions219553 +Ref: 10f219553 +Ref: guides/packaging-binary-extensions packaging-binary-extensions219553 +Ref: 110219553 +Node: An overview of binary extensions220179 +Ref: guides/packaging-binary-extensions an-overview-of-binary-extensions220328 +Ref: 111220328 +Node: Use cases220592 +Ref: guides/packaging-binary-extensions use-cases220706 +Ref: 112220706 +Ref: Use cases-Footnote-1223218 +Ref: Use cases-Footnote-2223286 +Ref: Use cases-Footnote-3223365 +Ref: Use cases-Footnote-4223434 +Ref: Use cases-Footnote-5223514 +Node: Disadvantages223585 +Ref: guides/packaging-binary-extensions disadvantages223753 +Ref: 113223753 +Node: Alternatives to handcoded accelerator modules225388 +Ref: guides/packaging-binary-extensions alternatives-to-handcoded-accelerator-modules225588 +Ref: 114225588 +Ref: Alternatives to handcoded accelerator modules-Footnote-1228084 +Ref: Alternatives to handcoded accelerator modules-Footnote-2228114 +Ref: Alternatives to handcoded accelerator modules-Footnote-3228142 +Node: Alternatives to handcoded wrapper modules228175 +Ref: guides/packaging-binary-extensions alternatives-to-handcoded-wrapper-modules228402 +Ref: 115228402 +Ref: Alternatives to handcoded wrapper modules-Footnote-1231540 +Ref: Alternatives to handcoded wrapper modules-Footnote-2231568 +Ref: Alternatives to handcoded wrapper modules-Footnote-3231622 +Ref: Alternatives to handcoded wrapper modules-Footnote-4231683 +Ref: Alternatives to handcoded wrapper modules-Footnote-5231762 +Ref: Alternatives to handcoded wrapper modules-Footnote-6231819 +Node: Alternatives for low level system access231848 +Ref: guides/packaging-binary-extensions alternatives-for-low-level-system-access232021 +Ref: 116232021 +Node: Implementing binary extensions233007 +Ref: guides/packaging-binary-extensions implementing-binary-extensions233191 +Ref: 117233191 +Ref: Implementing binary extensions-Footnote-1233834 +Ref: Implementing binary extensions-Footnote-2233889 +Node: Building binary extensions233948 +Ref: guides/packaging-binary-extensions building-binary-extensions234128 +Ref: 118234128 +Node: Building extensions for multiple platforms234352 +Ref: guides/packaging-binary-extensions building-extensions-for-multiple-platforms234509 +Ref: 119234509 +Node: Binary extensions for Windows235069 +Ref: guides/packaging-binary-extensions binary-extensions-for-windows235262 +Ref: 11c235262 +Ref: Binary extensions for Windows-Footnote-1236756 +Node: Binary extensions for Linux236810 +Ref: guides/packaging-binary-extensions binary-extensions-for-linux236988 +Ref: 11d236988 +Ref: Binary extensions for Linux-Footnote-1237345 +Node: Binary extensions for macOS237387 +Ref: guides/packaging-binary-extensions binary-extensions-for-macos237527 +Ref: 11e237527 +Ref: Binary extensions for macOS-Footnote-1238107 +Node: Publishing binary extensions238170 +Ref: guides/packaging-binary-extensions publishing-binary-extensions238340 +Ref: 11f238340 +Ref: Publishing binary extensions-Footnote-1238850 +Node: Additional resources238914 +Ref: guides/packaging-binary-extensions additional-resources239049 +Ref: 120239049 +Node: Cross-platform wheel generation with scikit-build239618 +Ref: guides/packaging-binary-extensions cross-platform-wheel-generation-with-scikit-build239786 +Ref: 121239786 +Ref: Cross-platform wheel generation with scikit-build-Footnote-1240234 +Ref: Cross-platform wheel generation with scikit-build-Footnote-2240289 +Node: Introduction to C/C++ extension modules240359 +Ref: guides/packaging-binary-extensions introduction-to-c-c-extension-modules240527 +Ref: 122240527 +Ref: Introduction to C/C++ extension modules-Footnote-1240915 +Ref: Introduction to C/C++ extension modules-Footnote-2240980 +Ref: Introduction to C/C++ extension modules-Footnote-3241036 +Node: Supporting Windows using Appveyor241096 +Ref: guides/supporting-windows-using-appveyor doc241259 +Ref: 123241259 +Ref: guides/supporting-windows-using-appveyor supporting-windows-using-appveyor241259 +Ref: 124241259 +Ref: Supporting Windows using Appveyor-Footnote-1241781 +Node: Background241815 +Ref: guides/supporting-windows-using-appveyor background241928 +Ref: 125241928 +Ref: Background-Footnote-1242951 +Ref: Background-Footnote-2242982 +Node: Setting up243009 +Ref: guides/supporting-windows-using-appveyor setting-up243170 +Ref: 126243170 +Ref: Setting up-Footnote-1243887 +Ref: Setting up-Footnote-2243926 +Ref: Setting up-Footnote-3243953 +Node: Adding Appveyor support to your project243984 +Ref: guides/supporting-windows-using-appveyor adding-appveyor-support-to-your-project244151 +Ref: 127244151 +Node: appveyor yml245084 +Ref: guides/supporting-windows-using-appveyor appveyor-yml245209 +Ref: 128245209 +Ref: appveyor yml-Footnote-1249574 +Node: Support script249700 +Ref: guides/supporting-windows-using-appveyor support-script249860 +Ref: 129249860 +Ref: Support script-Footnote-1250744 +Node: Access to the built wheels250867 +Ref: guides/supporting-windows-using-appveyor access-to-the-built-wheels251006 +Ref: 12a251006 +Node: Additional notes251544 +Ref: guides/supporting-windows-using-appveyor additional-notes251692 +Ref: 12b251692 +Node: Testing with tox251853 +Ref: guides/supporting-windows-using-appveyor testing-with-tox251975 +Ref: 12c251975 +Ref: Testing with tox-Footnote-1254907 +Node: Automatically uploading wheels254953 +Ref: guides/supporting-windows-using-appveyor automatically-uploading-wheels255105 +Ref: 12d255105 +Node: External dependencies255746 +Ref: guides/supporting-windows-using-appveyor external-dependencies255897 +Ref: 12e255897 +Node: Support scripts256478 +Ref: guides/supporting-windows-using-appveyor support-scripts256590 +Ref: 12f256590 +Node: Packaging namespace packages257664 +Ref: guides/packaging-namespace-packages doc257832 +Ref: 130257832 +Ref: guides/packaging-namespace-packages bitbucket257832 +Ref: 131257832 +Ref: guides/packaging-namespace-packages packaging-namespace-packages257832 +Ref: 132257832 +Node: Creating a namespace package259488 +Ref: guides/packaging-namespace-packages creating-a-namespace-package259595 +Ref: 133259595 +Ref: Creating a namespace package-Footnote-1260927 +Node: Native namespace packages260976 +Ref: guides/packaging-namespace-packages native-namespace-packages261121 +Ref: 134261121 +Ref: Native namespace packages-Footnote-1262802 +Ref: Native namespace packages-Footnote-2262851 +Node: pkgutil-style namespace packages262929 +Ref: guides/packaging-namespace-packages pkgutil-style-namespace-packages263121 +Ref: 135263121 +Ref: pkgutil-style namespace packages-Footnote-1264396 +Ref: pkgutil-style namespace packages-Footnote-2264451 +Ref: pkgutil-style namespace packages-Footnote-3264527 +Node: pkg_resources-style namespace packages264606 +Ref: guides/packaging-namespace-packages pkg-resources-style-namespace-packages264764 +Ref: 136264764 +Ref: guides/packaging-namespace-packages pkgutil-namespace-example-project264764 +Ref: 137264764 +Ref: pkg_resources-style namespace packages-Footnote-1267388 +Ref: pkg_resources-style namespace packages-Footnote-2267444 +Ref: pkg_resources-style namespace packages-Footnote-3267542 +Node: Creating and discovering plugins267627 +Ref: guides/creating-and-discovering-plugins doc267783 +Ref: 138267783 +Ref: guides/creating-and-discovering-plugins creating-and-discovering-plugins267783 +Ref: 139267783 +Ref: guides/creating-and-discovering-plugins pkg-resources-namespace-example-project267783 +Ref: 13a267783 +Node: Using naming convention268439 +Ref: guides/creating-and-discovering-plugins using-naming-convention268578 +Ref: 13b268578 +Ref: Using naming convention-Footnote-1269664 +Ref: Using naming convention-Footnote-2269741 +Ref: Using naming convention-Footnote-3269781 +Ref: Using naming convention-Footnote-4269832 +Ref: Using naming convention-Footnote-5269880 +Node: Using namespace packages269944 +Ref: guides/creating-and-discovering-plugins simple-api270114 +Ref: 13e270114 +Ref: guides/creating-and-discovering-plugins using-namespace-packages270114 +Ref: 13c270114 +Ref: Using namespace packages-Footnote-1272922 +Ref: Using namespace packages-Footnote-2272999 +Node: Using package metadata273076 +Ref: guides/creating-and-discovering-plugins using-package-metadata273214 +Ref: 13d273214 +Ref: Using package metadata-Footnote-1274804 +Ref: Using package metadata-Footnote-2274860 +Ref: Using package metadata-Footnote-3274932 +Ref: Using package metadata-Footnote-4274993 +Ref: Using package metadata-Footnote-5275065 +Node: Migrating to PyPI org275131 +Ref: guides/migrating-to-pypi-org doc275276 +Ref: 13f275276 +Ref: guides/migrating-to-pypi-org backport275276 +Ref: 140275276 +Ref: guides/migrating-to-pypi-org id1275276 +Ref: 141275276 +Ref: guides/migrating-to-pypi-org migrating-to-pypi-org275276 +Ref: 142275276 +Node: Publishing releases275814 +Ref: guides/migrating-to-pypi-org publishing-releases275950 +Ref: 144275950 +Node: Registering package names & metadata277941 +Ref: guides/migrating-to-pypi-org registering-package-names-metadata278100 +Ref: 145278100 +Node: Using TestPyPI278721 +Ref: guides/migrating-to-pypi-org using-testpypi278890 +Ref: 146278890 +Ref: Using TestPyPI-Footnote-1279559 +Node: Registering new user accounts279589 +Ref: guides/migrating-to-pypi-org registering-new-user-accounts279739 +Ref: 147279739 +Node: Browsing packages280015 +Ref: guides/migrating-to-pypi-org browsing-packages280171 +Ref: 148280171 +Node: Downloading packages280479 +Ref: guides/migrating-to-pypi-org downloading-packages280646 +Ref: 149280646 +Node: Managing published packages and releases280765 +Ref: guides/migrating-to-pypi-org managing-published-packages-and-releases280906 +Ref: 14a280906 +Node: Using TestPyPI<2>281126 +Ref: guides/using-testpypi doc281268 +Ref: 6c281268 +Ref: guides/using-testpypi using-test-pypi281268 +Ref: f1281268 +Ref: guides/using-testpypi using-testpypi281268 +Ref: 14b281268 +Ref: Using TestPyPI<2>-Footnote-1281743 +Node: Registering your account281773 +Ref: guides/using-testpypi registering-your-account281899 +Ref: 14c281899 +Node: Using TestPyPI with Twine282294 +Ref: guides/using-testpypi using-testpypi-with-twine282452 +Ref: 14d282452 +Node: Using TestPyPI with pip282954 +Ref: guides/using-testpypi using-testpypi-with-pip283117 +Ref: 14e283117 +Node: Setting up TestPyPI in pypirc283944 +Ref: guides/using-testpypi setting-up-testpypi-in-pypirc284073 +Ref: 14f284073 +Node: Making a PyPI-friendly README284389 +Ref: guides/making-a-pypi-friendly-readme doc284587 +Ref: 150284587 +Ref: guides/making-a-pypi-friendly-readme making-a-pypi-friendly-readme284587 +Ref: 151284587 +Node: Creating a README file285034 +Ref: guides/making-a-pypi-friendly-readme creating-a-readme-file285195 +Ref: 152285195 +Ref: Creating a README file-Footnote-1285824 +Ref: Creating a README file-Footnote-2285872 +Ref: Creating a README file-Footnote-3285921 +Ref: Creating a README file-Footnote-4285960 +Node: Including your README in your package’s metadata285992 +Ref: guides/making-a-pypi-friendly-readme including-your-readme-in-your-package-s-metadata286196 +Ref: 153286196 +Node: Validating reStructuredText markup288281 +Ref: guides/making-a-pypi-friendly-readme validating-restructuredtext-markup288454 +Ref: 156288454 +Ref: Validating reStructuredText markup-Footnote-1289667 +Ref: Validating reStructuredText markup-Footnote-2289747 +Node: Publishing package distribution releases using GitHub Actions CI/CD workflows289785 +Ref: guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows doc289986 +Ref: 157289986 +Ref: guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows publishing-package-distribution-releases-using-github-actions-ci-cd-workflows289986 +Ref: 158289986 +Ref: Publishing package distribution releases using GitHub Actions CI/CD workflows-Footnote-1290966 +Ref: Publishing package distribution releases using GitHub Actions CI/CD workflows-Footnote-2291010 +Node: Saving credentials on GitHub291070 +Ref: guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows saving-credentials-on-github291265 +Ref: 159291265 +Ref: Saving credentials on GitHub-Footnote-1292605 +Ref: Saving credentials on GitHub-Footnote-2292645 +Node: Creating a workflow definition292716 +Ref: guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows creating-a-workflow-definition292955 +Ref: 15a292955 +Node: Defining a workflow job environment293410 +Ref: guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows defining-a-workflow-job-environment293672 +Ref: 15b293672 +Node: Checking out the project and building distributions294072 +Ref: guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows checking-out-the-project-and-building-distributions294352 +Ref: 15c294352 +Ref: Checking out the project and building distributions-Footnote-1295588 +Ref: Checking out the project and building distributions-Footnote-2295637 +Node: Publishing the distribution to PyPI and TestPyPI295686 +Ref: guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows publishing-the-distribution-to-pypi-and-testpypi295950 +Ref: 15d295950 +Ref: Publishing the distribution to PyPI and TestPyPI-Footnote-1296846 +Node: That’s all folks!296901 +Ref: guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows that-s-all-folks297105 +Ref: 15e297105 +Node: Tool recommendations297450 +Ref: guides/tool-recommendations doc297654 +Ref: 15f297654 +Ref: guides/tool-recommendations id1297654 +Ref: 160297654 +Ref: guides/tool-recommendations secrets297654 +Ref: 161297654 +Ref: guides/tool-recommendations tool-recommendations297654 +Ref: 162297654 +Node: Application dependency management298001 +Ref: guides/tool-recommendations application-dependency-management298147 +Ref: 163298147 +Ref: Application dependency management-Footnote-1298697 +Ref: Application dependency management-Footnote-2298759 +Ref: Application dependency management-Footnote-3298811 +Ref: Application dependency management-Footnote-4299098 +Ref: Application dependency management-Footnote-5299144 +Node: Installation tool recommendations299179 +Ref: guides/tool-recommendations installation-tool-recommendations299364 +Ref: 164299364 +Ref: guides/tool-recommendations poetry299364 +Ref: 165299364 +Ref: Installation tool recommendations-Footnote-1300186 +Ref: Installation tool recommendations-Footnote-2300443 +Ref: Installation tool recommendations-Footnote-3300788 +Ref: Installation tool recommendations-Footnote-4301105 +Ref: Installation tool recommendations-Footnote-5301157 +Node: Packaging tool recommendations301444 +Ref: guides/tool-recommendations packaging-tool-recommendations301625 +Ref: 16d301625 +Ref: Packaging tool recommendations-Footnote-1302131 +Ref: Packaging tool recommendations-Footnote-2302962 +Ref: Packaging tool recommendations-Footnote-3303163 +Node: Publishing platform migration303202 +Ref: guides/tool-recommendations publishing-platform-migration303341 +Ref: 16e303341 +Ref: Publishing platform migration-Footnote-1303831 +Ref: Publishing platform migration-Footnote-2303863 +Node: Analyzing PyPI package downloads303888 +Ref: guides/analyzing-pypi-package-downloads doc304006 +Ref: 16f304006 +Ref: guides/analyzing-pypi-package-downloads analyzing-pypi-package-downloads304006 +Ref: 170304006 +Ref: guides/analyzing-pypi-package-downloads distribute304006 +Ref: 171304006 +Node: Background<2>304442 +Ref: guides/analyzing-pypi-package-downloads background304561 +Ref: 172304561 +Ref: Background<2>-Footnote-1305902 +Node: Public dataset306024 +Ref: guides/analyzing-pypi-package-downloads public-dataset306159 +Ref: 173306159 +Ref: Public dataset-Footnote-1306450 +Ref: Public dataset-Footnote-2306491 +Ref: Public dataset-Footnote-3306533 +Node: Getting set up306657 +Ref: guides/analyzing-pypi-package-downloads getting-set-up306756 +Ref: 174306756 +Ref: Getting set up-Footnote-1307351 +Ref: Getting set up-Footnote-2307393 +Ref: Getting set up-Footnote-3307487 +Ref: Getting set up-Footnote-4307607 +Ref: Getting set up-Footnote-5307657 +Ref: Getting set up-Footnote-6307746 +Node: Data schema307824 +Ref: guides/analyzing-pypi-package-downloads data-schema307946 +Ref: 175307946 +Ref: Data schema-Footnote-1309383 +Node: Useful queries309498 +Ref: guides/analyzing-pypi-package-downloads useful-queries309597 +Ref: 177309597 +Ref: Useful queries-Footnote-1310061 +Node: Counting package downloads310111 +Ref: guides/analyzing-pypi-package-downloads counting-package-downloads310238 +Ref: 178310238 +Node: Package downloads over time311237 +Ref: guides/analyzing-pypi-package-downloads package-downloads-over-time311398 +Ref: 179311398 +Node: Python versions over time312575 +Ref: guides/analyzing-pypi-package-downloads python-versions-over-time312701 +Ref: 17a312701 +Node: Caveats313730 +Ref: guides/analyzing-pypi-package-downloads caveats313868 +Ref: 17b313868 +Node: Additional tools314258 +Ref: guides/analyzing-pypi-package-downloads additional-tools314392 +Ref: 17c314392 +Node: google-cloud-bigquery314629 +Ref: guides/analyzing-pypi-package-downloads google-cloud-bigquery314733 +Ref: 17d314733 +Ref: google-cloud-bigquery-Footnote-1315755 +Node: pypinfo315822 +Ref: guides/analyzing-pypi-package-downloads pypinfo315945 +Ref: 17e315945 +Ref: pypinfo-Footnote-1316540 +Ref: pypinfo-Footnote-2316603 +Node: pandas-gbq316666 +Ref: guides/analyzing-pypi-package-downloads pandas-gbq316759 +Ref: 17f316759 +Ref: pandas-gbq-Footnote-1316921 +Ref: pandas-gbq-Footnote-2316974 +Node: References317009 +Ref: guides/analyzing-pypi-package-downloads references317127 +Ref: 180317127 +Node: Discussions317164 +Ref: discussions/index doc317272 +Ref: 181317272 +Ref: discussions/index discussions317272 +Ref: 182317272 +Ref: discussions/index pandas317272 +Ref: 183317272 +Node: Deploying Python applications317585 +Ref: discussions/deploying-python-applications doc317704 +Ref: 184317704 +Ref: discussions/deploying-python-applications deploying-python-applications317704 +Ref: 185317704 +Node: Overview317932 +Ref: discussions/deploying-python-applications overview318054 +Ref: 186318054 +Node: Supporting multiple hardware platforms318138 +Ref: discussions/deploying-python-applications supporting-multiple-hardware-platforms318235 +Ref: 187318235 +Node: OS packaging & installers319011 +Ref: discussions/deploying-python-applications os-packaging-installers319161 +Ref: 188319161 +Node: Windows319462 +Ref: discussions/deploying-python-applications windows319545 +Ref: 189319545 +Node: Pynsist319668 +Ref: discussions/deploying-python-applications pynsist319733 +Ref: 18a319733 +Ref: Pynsist-Footnote-1320675 +Ref: Pynsist-Footnote-2320716 +Node: Application bundles320776 +Ref: discussions/deploying-python-applications application-bundles320942 +Ref: 18b320942 +Node: Windows<2>321145 +Ref: discussions/deploying-python-applications id1321239 +Ref: 18c321239 +Node: py2exe321293 +Ref: discussions/deploying-python-applications py2exe321360 +Ref: 18d321360 +Ref: py2exe-Footnote-1321936 +Ref: py2exe-Footnote-2321977 +Node: macOS322040 +Ref: discussions/deploying-python-applications id2322173 +Ref: 18e322173 +Ref: discussions/deploying-python-applications macos322173 +Ref: 18f322173 +Node: py2app322223 +Ref: discussions/deploying-python-applications py2app322285 +Ref: 190322285 +Ref: py2app-Footnote-1322652 +Node: Unix including Linux and macOS322693 +Ref: discussions/deploying-python-applications unix-including-linux-and-macos322807 +Ref: 191322807 +Node: pex322908 +Ref: discussions/deploying-python-applications pex322992 +Ref: 192322992 +Ref: pex-Footnote-1323509 +Ref: pex-Footnote-2323547 +Node: Configuration management323596 +Ref: discussions/deploying-python-applications configuration-management323728 +Ref: 193323728 +Node: pip vs easy_install323861 +Ref: discussions/pip-vs-easy-install doc324027 +Ref: 194324027 +Ref: discussions/pip-vs-easy-install id1324027 +Ref: 195324027 +Ref: discussions/pip-vs-easy-install pip-vs-easy-install324027 +Ref: 167324027 +Ref: pip vs easy_install-Footnote-1328144 +Ref: pip vs easy_install-Footnote-2328217 +Ref: pip vs easy_install-Footnote-3328286 +Ref: pip vs easy_install-Footnote-4328355 +Ref: pip vs easy_install-Footnote-5328404 +Ref: pip vs easy_install-Footnote-6328457 +Node: install_requires vs requirements files328572 +Ref: discussions/install-requires-vs-requirements doc328721 +Ref: 197328721 +Ref: discussions/install-requires-vs-requirements id1328721 +Ref: 198328721 +Ref: discussions/install-requires-vs-requirements install-requires-vs-requirements-files328721 +Ref: d3328721 +Ref: discussions/install-requires-vs-requirements pylauncher-support328721 +Ref: 199328721 +Node: install_requires<2>328904 +Ref: discussions/install-requires-vs-requirements install-requires329042 +Ref: 19a329042 +Ref: install_requires<2>-Footnote-1330714 +Node: Requirements files<2>330851 +Ref: discussions/install-requires-vs-requirements requirements-files330989 +Ref: 19b330989 +Ref: Requirements files<2>-Footnote-1332176 +Ref: Requirements files<2>-Footnote-2332245 +Ref: Requirements files<2>-Footnote-3332312 +Ref: Requirements files<2>-Footnote-4332381 +Ref: Requirements files<2>-Footnote-5332445 +Node: Wheel vs Egg332582 +Ref: discussions/wheel-vs-egg doc332703 +Ref: 19c332703 +Ref: discussions/wheel-vs-egg id1332703 +Ref: 19d332703 +Ref: discussions/wheel-vs-egg wheel-vs-egg332703 +Ref: 19e332703 +Ref: Wheel vs Egg-Footnote-1334657 +Ref: Wheel vs Egg-Footnote-2334706 +Ref: Wheel vs Egg-Footnote-3334755 +Ref: Wheel vs Egg-Footnote-4335015 +Ref: Wheel vs Egg-Footnote-5335064 +Ref: Wheel vs Egg-Footnote-6335113 +Node: PyPA specifications335190 +Ref: specifications/index doc335309 +Ref: 1a0335309 +Ref: specifications/index packaging-specifications335309 +Ref: 1a1335309 +Ref: specifications/index pypa-specifications335309 +Ref: 1a2335309 +Ref: PyPA specifications-Footnote-1335715 +Node: Package Distribution Metadata335769 +Ref: specifications/index package-distribution-metadata335910 +Ref: 1a3335910 +Node: Core metadata specifications336301 +Ref: specifications/core-metadata doc336436 +Ref: 1a4336436 +Ref: specifications/core-metadata core-metadata336436 +Ref: 106336436 +Ref: specifications/core-metadata core-metadata-specifications336436 +Ref: 1a5336436 +Ref: Core metadata specifications-Footnote-1338792 +Ref: Core metadata specifications-Footnote-2338873 +Ref: Core metadata specifications-Footnote-3338956 +Ref: Core metadata specifications-Footnote-4339005 +Node: Metadata-Version339054 +Ref: specifications/core-metadata metadata-version339162 +Ref: 1a8339162 +Ref: Metadata-Version-Footnote-1339895 +Node: Name339944 +Ref: specifications/core-metadata core-metadata-name340068 +Ref: 1a9340068 +Ref: specifications/core-metadata name340068 +Ref: 1aa340068 +Ref: Name-Footnote-1340962 +Ref: Name-Footnote-2341011 +Node: Version341060 +Ref: specifications/core-metadata core-metadata-version341188 +Ref: 1ab341188 +Ref: specifications/core-metadata version341188 +Ref: 1ac341188 +Ref: Version-Footnote-1341426 +Node: Dynamic multiple use341475 +Ref: specifications/core-metadata dynamic-multiple-use341620 +Ref: 1ad341620 +Ref: Dynamic multiple use-Footnote-1342969 +Node: Platform multiple use343018 +Ref: specifications/core-metadata platform-multiple-use343187 +Ref: 1ae343187 +Node: Supported-Platform multiple use343520 +Ref: specifications/core-metadata supported-platform-multiple-use343676 +Ref: 1af343676 +Node: Summary344127 +Ref: specifications/core-metadata core-metadata-summary344273 +Ref: 1b0344273 +Ref: specifications/core-metadata summary344273 +Ref: 1b1344273 +Ref: specifications/core-metadata description-optional344447 +Ref: 154344447 +Node: Description344447 +Ref: specifications/core-metadata core-metadata-description344586 +Ref: 1b2344586 +Ref: specifications/core-metadata description344586 +Ref: 1b3344586 +Ref: specifications/core-metadata description-content-type-optional346188 +Ref: 155346188 +Ref: Description-Footnote-1346226 +Ref: Description-Footnote-2346302 +Node: Description-Content-Type346420 +Ref: specifications/core-metadata core-metadata-description-content-type346560 +Ref: 1b4346560 +Ref: specifications/core-metadata description-content-type346560 +Ref: 1b5346560 +Ref: specifications/core-metadata keywords-optional349568 +Ref: 1b6349568 +Ref: Description-Content-Type-Footnote-1349606 +Ref: Description-Content-Type-Footnote-2349682 +Ref: Description-Content-Type-Footnote-3349736 +Ref: Description-Content-Type-Footnote-4349785 +Ref: Description-Content-Type-Footnote-5349850 +Ref: Description-Content-Type-Footnote-6349911 +Node: Keywords349972 +Ref: specifications/core-metadata core-metadata-keywords350110 +Ref: 1b7350110 +Ref: specifications/core-metadata keywords350110 +Ref: 1b8350110 +Node: Home-page350628 +Ref: specifications/core-metadata home-page350754 +Ref: 1b9350754 +Ref: specifications/core-metadata home-page-optional350754 +Ref: 1ba350754 +Node: Download-URL350946 +Ref: specifications/core-metadata download-url351070 +Ref: 1bb351070 +Ref: specifications/core-metadata author-optional351364 +Ref: 1bc351364 +Node: Author351365 +Ref: specifications/core-metadata author351492 +Ref: 1bd351492 +Ref: specifications/core-metadata core-metadata-author351492 +Ref: 1be351492 +Ref: specifications/core-metadata author-email-optional351774 +Ref: 1bf351774 +Node: Author-email351775 +Ref: specifications/core-metadata author-email351900 +Ref: 1c0351900 +Ref: specifications/core-metadata core-metadata-author-email351900 +Ref: 1c1351900 +Ref: specifications/core-metadata maintainer-optional352319 +Ref: 1c2352319 +Node: Maintainer352320 +Ref: specifications/core-metadata core-metadata-maintainer352455 +Ref: 1c3352455 +Ref: specifications/core-metadata maintainer352455 +Ref: 1c4352455 +Ref: specifications/core-metadata maintainer-email-optional352930 +Ref: 1c5352930 +Node: Maintainer-email352931 +Ref: specifications/core-metadata core-metadata-maintainer-email353061 +Ref: 1c6353061 +Ref: specifications/core-metadata maintainer-email353061 +Ref: 1c7353061 +Ref: specifications/core-metadata license-optional353683 +Ref: 1c8353683 +Node: License353684 +Ref: specifications/core-metadata core-metadata-license353827 +Ref: 1c9353827 +Ref: specifications/core-metadata license353827 +Ref: 1ca353827 +Ref: specifications/core-metadata metadata-classifier354464 +Ref: 1cb354464 +Node: Classifier multiple use354465 +Ref: specifications/core-metadata classifier-multiple-use354618 +Ref: 1cc354618 +Ref: specifications/core-metadata core-metadata-classifier354618 +Ref: 1cd354618 +Ref: Classifier multiple use-Footnote-1355147 +Ref: Classifier multiple use-Footnote-2355196 +Node: Requires-Dist multiple use355234 +Ref: specifications/core-metadata core-metadata-requires-dist355395 +Ref: 1ce355395 +Ref: specifications/core-metadata requires-dist-multiple-use355395 +Ref: 1cf355395 +Ref: Requires-Dist multiple use-Footnote-1356877 +Ref: Requires-Dist multiple use-Footnote-2356926 +Node: Requires-Python356952 +Ref: specifications/core-metadata core-metadata-requires-python357120 +Ref: 1d1357120 +Ref: specifications/core-metadata requires-python357120 +Ref: 1d2357120 +Node: Requires-External multiple use357627 +Ref: specifications/core-metadata requires-external-multiple-use357793 +Ref: 1d3357793 +Ref: Requires-External multiple use-Footnote-1358963 +Node: Project-URL multiple-use359012 +Ref: specifications/core-metadata core-metadata-project-url359190 +Ref: 1d4359190 +Ref: specifications/core-metadata project-url-multiple-use359190 +Ref: 1d5359190 +Ref: specifications/core-metadata metadata-provides-extra359515 +Ref: 1d6359515 +Ref: specifications/core-metadata core-metadata-provides-extra359515 +Ref: 1d7359515 +Node: Provides-Extra multiple use359517 +Ref: specifications/core-metadata provides-extra-multiple-use359683 +Ref: 1d8359683 +Ref: specifications/core-metadata provides-extra-optional-multiple-use359683 +Ref: 1d9359683 +Ref: Provides-Extra multiple use-Footnote-1361946 +Node: Rarely Used Fields361995 +Ref: specifications/core-metadata rarely-used-fields362128 +Ref: 1da362128 +Ref: Rarely Used Fields-Footnote-1363011 +Node: Provides-Dist multiple use363036 +Ref: specifications/core-metadata provides-dist-multiple-use363167 +Ref: 1db363167 +Node: Obsoletes-Dist multiple use364864 +Ref: specifications/core-metadata obsoletes-dist-multiple-use364995 +Ref: 1dc364995 +Node: Version specifiers366006 +Ref: specifications/version-specifiers doc366171 +Ref: 1d0366171 +Ref: specifications/version-specifiers id1366171 +Ref: 1dd366171 +Ref: specifications/version-specifiers version-specifiers366171 +Ref: 1de366171 +Ref: Version specifiers-Footnote-1366480 +Ref: Version specifiers-Footnote-2366529 +Node: Dependency specifiers366578 +Ref: specifications/dependency-specifiers doc366750 +Ref: 1df366750 +Ref: specifications/dependency-specifiers dependency-specifiers366750 +Ref: 1e0366750 +Ref: specifications/dependency-specifiers id1366750 +Ref: 1e1366750 +Ref: Dependency specifiers-Footnote-1367115 +Ref: Dependency specifiers-Footnote-2367164 +Ref: Dependency specifiers-Footnote-3367213 +Node: Declaring build system dependencies367262 +Ref: specifications/declaring-build-dependencies doc367442 +Ref: 1e2367442 +Ref: specifications/declaring-build-dependencies declaring-build-dependencies367442 +Ref: 1e3367442 +Ref: specifications/declaring-build-dependencies declaring-build-system-dependencies367442 +Ref: 1e4367442 +Ref: Declaring build system dependencies-Footnote-1367813 +Node: Declaring project metadata367862 +Ref: specifications/declaring-project-metadata doc368048 +Ref: 1e6368048 +Ref: specifications/declaring-project-metadata declaring-project-metadata368048 +Ref: 1e7368048 +Ref: specifications/declaring-project-metadata id1368048 +Ref: 1e8368048 +Ref: Declaring project metadata-Footnote-1369787 +Node: name<2>369836 +Ref: specifications/declaring-project-metadata name369939 +Ref: 1e9369939 +Ref: name<2>-Footnote-1370244 +Ref: name<2>-Footnote-2370268 +Node: version<2>370317 +Ref: specifications/declaring-project-metadata version370443 +Ref: 1ea370443 +Ref: version<2>-Footnote-1370737 +Ref: version<2>-Footnote-2370761 +Node: description<2>370810 +Ref: specifications/declaring-project-metadata description370935 +Ref: 1eb370935 +Ref: description<2>-Footnote-1371161 +Node: readme371185 +Ref: specifications/declaring-project-metadata readme371315 +Ref: 1ec371315 +Ref: readme-Footnote-1373256 +Node: requires-python373280 +Ref: specifications/declaring-project-metadata requires-python373406 +Ref: 1ed373406 +Ref: requires-python-Footnote-1373661 +Node: license<2>373685 +Ref: specifications/declaring-project-metadata license373824 +Ref: 1ee373824 +Ref: license<2>-Footnote-1374415 +Node: authors/maintainers374439 +Ref: specifications/declaring-project-metadata authors-maintainers374574 +Ref: 1ef374574 +Ref: authors/maintainers-Footnote-1376154 +Ref: authors/maintainers-Footnote-2376178 +Node: keywords<2>376226 +Ref: specifications/declaring-project-metadata keywords376365 +Ref: 1f0376365 +Ref: keywords<2>-Footnote-1376586 +Node: classifiers<2>376610 +Ref: specifications/declaring-project-metadata classifiers376734 +Ref: 1f1376734 +Ref: classifiers<2>-Footnote-1376984 +Node: urls377008 +Ref: specifications/declaring-project-metadata urls377133 +Ref: 1f2377133 +Ref: urls-Footnote-1377427 +Node: Entry points377451 +Ref: specifications/declaring-project-metadata entry-points377596 +Ref: 1f3377596 +Ref: Entry points-Footnote-1378855 +Node: dependencies/optional-dependencies378879 +Ref: specifications/declaring-project-metadata dependencies-optional-dependencies379027 +Ref: 1f5379027 +Ref: dependencies/optional-dependencies-Footnote-1380120 +Ref: dependencies/optional-dependencies-Footnote-2380144 +Ref: dependencies/optional-dependencies-Footnote-3380193 +Ref: dependencies/optional-dependencies-Footnote-4380242 +Ref: dependencies/optional-dependencies-Footnote-5380291 +Node: dynamic380340 +Ref: specifications/declaring-project-metadata dynamic380467 +Ref: 1f6380467 +Ref: dynamic-Footnote-1382401 +Node: Platform compatibility tags382425 +Ref: specifications/platform-compatibility-tags doc382604 +Ref: 1f7382604 +Ref: specifications/platform-compatibility-tags id1382604 +Ref: 1f8382604 +Ref: specifications/platform-compatibility-tags platform-compatibility-tags382604 +Ref: 1f9382604 +Ref: specifications/platform-compatibility-tags toml382604 +Ref: 1fa382604 +Ref: Platform compatibility tags-Footnote-1383248 +Node: Platform tags for Windows383297 +Ref: specifications/platform-compatibility-tags platform-tags-for-windows383441 +Ref: 1fb383441 +Ref: Platform tags for Windows-Footnote-1383650 +Node: Platform tags for macOS Mac OS X383699 +Ref: specifications/platform-compatibility-tags platform-tags-for-macos-mac-os-x383896 +Ref: 1fc383896 +Ref: Platform tags for macOS Mac OS X-Footnote-1384152 +Node: Platform tags for common Linux distributions384201 +Ref: specifications/platform-compatibility-tags platform-tags-for-common-linux-distributions384411 +Ref: 1fd384411 +Ref: specifications/platform-compatibility-tags manylinux384518 +Ref: 1fe384518 +Ref: Platform tags for common Linux distributions-Footnote-1386750 +Ref: Platform tags for common Linux distributions-Footnote-2386799 +Ref: Platform tags for common Linux distributions-Footnote-3386848 +Ref: Platform tags for common Linux distributions-Footnote-4386897 +Ref: Platform tags for common Linux distributions-Footnote-5386946 +Ref: Platform tags for common Linux distributions-Footnote-6386995 +Node: Manylinux compatibility support387044 +Ref: specifications/platform-compatibility-tags manylinux-compatibility-support387170 +Ref: 1ff387170 +Ref: Manylinux compatibility support-Footnote-1388492 +Node: Platform tags for other *nix platforms388577 +Ref: specifications/platform-compatibility-tags platform-tags-for-other-nix-platforms388746 +Ref: 200388746 +Ref: Platform tags for other *nix platforms-Footnote-1389139 +Node: Recording installed projects389188 +Ref: specifications/recording-installed-packages doc389367 +Ref: 1a7389367 +Ref: specifications/recording-installed-packages recording-installed-packages389367 +Ref: 201389367 +Ref: specifications/recording-installed-packages recording-installed-projects389367 +Ref: 202389367 +Node: History and change workflow390264 +Ref: specifications/recording-installed-packages history-and-change-workflow390402 +Ref: 204390402 +Ref: History and change workflow-Footnote-1390990 +Ref: History and change workflow-Footnote-2391039 +Ref: History and change workflow-Footnote-3391088 +Node: The dist-info directory391137 +Ref: specifications/recording-installed-packages the-dist-info-directory391301 +Ref: 205391301 +Ref: The dist-info directory-Footnote-1394224 +Ref: The dist-info directory-Footnote-2394290 +Ref: The dist-info directory-Footnote-3394353 +Node: The METADATA file394413 +Ref: specifications/recording-installed-packages the-metadata-file394565 +Ref: 207394565 +Node: The RECORD file394938 +Ref: specifications/recording-installed-packages the-record-file395085 +Ref: 208395085 +Node: The INSTALLER file398660 +Ref: specifications/recording-installed-packages the-installer-file398814 +Ref: 209398814 +Node: The direct_url json file399548 +Ref: specifications/recording-installed-packages the-direct-url-json-file399678 +Ref: 20a399678 +Node: Entry points specification400131 +Ref: specifications/entry-points doc400341 +Ref: 20c400341 +Ref: specifications/entry-points entry-points400341 +Ref: 1f4400341 +Ref: specifications/entry-points entry-points-specification400341 +Ref: 20d400341 +Node: Data model401692 +Ref: specifications/entry-points data-model401799 +Ref: 20e401799 +Node: File format404680 +Ref: specifications/entry-points file-format404811 +Ref: 20f404811 +Ref: File format-Footnote-1406707 +Ref: File format-Footnote-2406756 +Ref: File format-Footnote-3406805 +Ref: File format-Footnote-4406886 +Ref: File format-Footnote-5406935 +Node: Use for scripts406984 +Ref: specifications/entry-points use-for-scripts407096 +Ref: 210407096 +Node: Recording the Direct URL Origin of installed distributions408834 +Ref: specifications/direct-url doc409007 +Ref: 211409007 +Ref: specifications/direct-url direct-url409007 +Ref: 20b409007 +Ref: specifications/direct-url recording-the-direct-url-origin-of-installed-distributions409007 +Ref: 212409007 +Ref: Recording the Direct URL Origin of installed distributions-Footnote-1409503 +Node: Specification409552 +Ref: specifications/direct-url specification409697 +Ref: 213409697 +Ref: Specification-Footnote-1414347 +Ref: Specification-Footnote-2414396 +Node: Registered VCS414445 +Ref: specifications/direct-url registered-vcs414607 +Ref: 214414607 +Node: Git415225 +Ref: specifications/direct-url git415311 +Ref: 215415311 +Node: Mercurial415983 +Ref: specifications/direct-url mercurial416084 +Ref: 216416084 +Node: Bazaar416397 +Ref: specifications/direct-url bazaar416505 +Ref: 217416505 +Node: Subversion416758 +Ref: specifications/direct-url subversion416848 +Ref: 218416848 +Node: Examples417364 +Ref: specifications/direct-url examples417504 +Ref: 219417504 +Node: Example direct_url json417719 +Ref: specifications/direct-url example-direct-url-json417866 +Ref: 21a417866 +Node: Example pip commands and their effect on direct_url json418707 +Ref: specifications/direct-url example-pip-commands-and-their-effect-on-direct-url-json418854 +Ref: 21b418854 +Node: Package Distribution File Formats419826 +Ref: specifications/index package-distribution-file-formats420000 +Ref: 21c420000 +Node: Source distribution format420149 +Ref: specifications/source-distribution-format doc420294 +Ref: 21d420294 +Ref: specifications/source-distribution-format id1420294 +Ref: 21e420294 +Ref: specifications/source-distribution-format source-distribution-format420294 +Ref: 21f420294 +Ref: Source distribution format-Footnote-1421271 +Node: Source trees421320 +Ref: specifications/source-distribution-format source-trees421447 +Ref: 220421447 +Ref: Source trees-Footnote-1421922 +Ref: Source trees-Footnote-2421971 +Node: Source distribution file name422020 +Ref: specifications/source-distribution-format source-distribution-file-name422187 +Ref: 221422187 +Ref: Source distribution file name-Footnote-1422804 +Node: Source distribution file format422853 +Ref: specifications/source-distribution-format source-distribution-file-format422999 +Ref: 222422999 +Node: Binary distribution format423919 +Ref: specifications/binary-distribution-format doc424064 +Ref: 1a6424064 +Ref: specifications/binary-distribution-format binary-distribution-format424064 +Ref: 206424064 +Ref: specifications/binary-distribution-format id1424064 +Ref: 223424064 +Ref: Binary distribution format-Footnote-1424450 +Node: Abstract424499 +Ref: specifications/binary-distribution-format abstract424607 +Ref: 224424607 +Node: PEP Acceptance425202 +Ref: specifications/binary-distribution-format pep-acceptance425328 +Ref: 225425328 +Ref: PEP Acceptance-Footnote-1425524 +Node: Rationale425630 +Ref: specifications/binary-distribution-format rationale425755 +Ref: 226425755 +Node: Details426552 +Ref: specifications/binary-distribution-format details426666 +Ref: 227426666 +Node: Installing a wheel ‘distribution-1 0-py32-none-any whl’426913 +Ref: specifications/binary-distribution-format installing-a-wheel-distribution-1-0-py32-none-any-whl427050 +Ref: 228427050 +Node: Recommended installer features428688 +Ref: specifications/binary-distribution-format recommended-installer-features428866 +Ref: 229428866 +Node: Recommended archiver features429629 +Ref: specifications/binary-distribution-format recommended-archiver-features429807 +Ref: 22a429807 +Node: File Format430191 +Ref: specifications/binary-distribution-format file-format430355 +Ref: 22b430355 +Node: File name convention430474 +Ref: specifications/binary-distribution-format file-name-convention430585 +Ref: 22c430585 +Node: Escaping and Unicode431934 +Ref: specifications/binary-distribution-format escaping-and-unicode432067 +Ref: 22d432067 +Ref: Escaping and Unicode-Footnote-1433613 +Ref: Escaping and Unicode-Footnote-2433662 +Node: File contents433711 +Ref: specifications/binary-distribution-format file-contents433815 +Ref: 22e433815 +Node: The dist-info directory<2>436632 +Ref: specifications/binary-distribution-format the-dist-info-directory436749 +Ref: 22f436749 +Node: The data directory438077 +Ref: specifications/binary-distribution-format the-data-directory438194 +Ref: 230438194 +Node: Signed wheel files438694 +Ref: specifications/binary-distribution-format signed-wheel-files438816 +Ref: 231438816 +Node: Comparison to egg440706 +Ref: specifications/binary-distribution-format comparison-to-egg440808 +Ref: 232440808 +Node: FAQ442194 +Ref: specifications/binary-distribution-format faq442306 +Ref: 233442306 +Node: Wheel defines a data directory Should I put all my data there?442797 +Ref: specifications/binary-distribution-format wheel-defines-a-data-directory-should-i-put-all-my-data-there442965 +Ref: 234442965 +Node: Why does wheel include attached signatures?443537 +Ref: specifications/binary-distribution-format why-does-wheel-include-attached-signatures443750 +Ref: 235443750 +Node: Why does wheel allow JWS signatures?444180 +Ref: specifications/binary-distribution-format why-does-wheel-allow-jws-signatures444375 +Ref: 236444375 +Node: Why does wheel also allow S/MIME signatures?444694 +Ref: specifications/binary-distribution-format why-does-wheel-also-allow-s-mime-signatures444900 +Ref: 237444900 +Node: What’s the deal with “purelib” vs “platlib”?445266 +Ref: specifications/binary-distribution-format what-s-the-deal-with-purelib-vs-platlib445500 +Ref: 238445500 +Node: Is it possible to import Python code directly from a wheel file?446465 +Ref: specifications/binary-distribution-format is-it-possible-to-import-python-code-directly-from-a-wheel-file446646 +Ref: 239446646 +Node: Changes449232 +Ref: specifications/binary-distribution-format changes449350 +Ref: 23a449350 +Ref: Changes-Footnote-1449626 +Node: References<2>449675 +Ref: specifications/binary-distribution-format references449798 +Ref: 23b449798 +Node: Appendix449839 +Ref: specifications/binary-distribution-format appendix449964 +Ref: 23c449964 +Node: Copyright450347 +Ref: specifications/binary-distribution-format copyright450450 +Ref: 23d450450 +Node: Package Index Interfaces450544 +Ref: specifications/index package-index-interfaces450680 +Ref: 23e450680 +Node: The pypirc file450812 +Ref: specifications/pypirc doc450932 +Ref: 23f450932 +Ref: specifications/pypirc pypirc450932 +Ref: f3450932 +Ref: specifications/pypirc the-pypirc-file450932 +Ref: 240450932 +Ref: The pypirc file-Footnote-1452587 +Node: Common configurations452629 +Ref: specifications/pypirc common-configurations452716 +Ref: 241452716 +Ref: specifications/pypirc keyring452716 +Ref: 242452716 +Node: Using a PyPI token453537 +Ref: specifications/pypirc using-a-pypi-token453663 +Ref: 243453663 +Ref: Using a PyPI token-Footnote-1454012 +Node: Using another package index454052 +Ref: specifications/pypirc api-token454178 +Ref: 244454178 +Ref: specifications/pypirc using-another-package-index454178 +Ref: 245454178 +Ref: Using another package index-Footnote-1455294 +Node: Simple repository API455336 +Ref: specifications/simple-repository-api doc455456 +Ref: 246455456 +Ref: specifications/simple-repository-api id1455456 +Ref: 247455456 +Ref: specifications/simple-repository-api simple-repository-api455456 +Ref: 248455456 +Ref: Simple repository API-Footnote-1455924 +Ref: Simple repository API-Footnote-2455973 +Ref: Simple repository API-Footnote-3456022 +Ref: Simple repository API-Footnote-4456071 +Node: Project Summaries456120 +Ref: key_projects doc456236 +Ref: 249456236 +Ref: key_projects project-summaries456236 +Ref: 24a456236 +Ref: key_projects projects456236 +Ref: 24b456236 +Node: PyPA Projects456460 +Ref: key_projects id1456567 +Ref: 24c456567 +Ref: key_projects pypa-projects456567 +Ref: 24d456567 +Node: bandersnatch456926 +Ref: key_projects bandersnatch457016 +Ref: 176457016 +Ref: key_projects id2457016 +Ref: 24e457016 +Ref: bandersnatch-Footnote-1457431 +Ref: bandersnatch-Footnote-2457483 +Ref: bandersnatch-Footnote-3457528 +Node: build457574 +Ref: key_projects build457685 +Ref: 5f457685 +Ref: key_projects id3457685 +Ref: 24f457685 +Ref: build-Footnote-1457916 +Ref: build-Footnote-2457979 +Ref: build-Footnote-3458024 +Ref: build-Footnote-4458062 +Ref: build-Footnote-5458101 +Node: cibuildwheel458150 +Ref: key_projects cibuildwheel458256 +Ref: 11a458256 +Ref: key_projects id4458256 +Ref: 250458256 +Ref: cibuildwheel-Footnote-1458585 +Ref: cibuildwheel-Footnote-2458630 +Ref: cibuildwheel-Footnote-3458682 +Ref: cibuildwheel-Footnote-4458727 +Ref: cibuildwheel-Footnote-5458773 +Ref: cibuildwheel-Footnote-6458830 +Node: distlib458870 +Ref: key_projects distlib458975 +Ref: 251458975 +Ref: key_projects id5458975 +Ref: 252458975 +Ref: distlib-Footnote-1459922 +Ref: distlib-Footnote-2459982 +Ref: distlib-Footnote-3460055 +Ref: distlib-Footnote-4460098 +Node: flit460139 +Ref: key_projects flit460237 +Ref: 60460237 +Ref: key_projects id6460237 +Ref: 254460237 +Ref: flit-Footnote-1460925 +Ref: flit-Footnote-2460972 +Ref: flit-Footnote-3461016 +Ref: flit-Footnote-4461054 +Node: hatch461115 +Ref: key_projects hatch461215 +Ref: 71461215 +Ref: key_projects id7461215 +Ref: 255461215 +Ref: hatch-Footnote-1461644 +Ref: hatch-Footnote-2461682 +Node: packaging461721 +Ref: key_projects id8461820 +Ref: 256461820 +Ref: key_projects packaging461820 +Ref: 253461820 +Ref: packaging-Footnote-1462907 +Ref: packaging-Footnote-2462962 +Ref: packaging-Footnote-3463011 +Ref: packaging-Footnote-4463053 +Node: pip463096 +Ref: key_projects id9463196 +Ref: 257463196 +Ref: key_projects pip463196 +Ref: 2b463196 +Ref: pip-Footnote-1463644 +Ref: pip-Footnote-2463673 +Ref: pip-Footnote-3463716 +Ref: pip-Footnote-4463752 +Node: Pipenv463790 +Ref: key_projects id10463888 +Ref: 258463888 +Ref: key_projects pipenv463888 +Ref: 36463888 +Ref: Pipenv-Footnote-1464653 +Ref: Pipenv-Footnote-2464695 +Ref: Pipenv-Footnote-3464734 +Ref: Pipenv-Footnote-4464780 +Node: Pipfile464820 +Ref: key_projects id11464919 +Ref: 259464919 +Ref: key_projects pipfile464919 +Ref: 52464919 +Ref: Pipfile-Footnote-1465160 +Node: pipx465200 +Ref: key_projects id12465323 +Ref: 25a465323 +Ref: key_projects pipx465323 +Ref: 91465323 +Ref: pipx-Footnote-1465565 +Ref: pipx-Footnote-2465602 +Ref: pipx-Footnote-3465639 +Node: Python Packaging User Guide<2>465678 +Ref: key_projects python-packaging-user-guide465809 +Ref: 25b465809 +Ref: Python Packaging User Guide<2>-Footnote-1465962 +Ref: Python Packaging User Guide<2>-Footnote-2466010 +Ref: Python Packaging User Guide<2>-Footnote-3466070 +Node: readme_renderer466123 +Ref: key_projects id13466260 +Ref: 25c466260 +Ref: key_projects readme-renderer466260 +Ref: 25d466260 +Ref: key_projects setuptools466691 +Ref: 2d466691 +Ref: readme_renderer-Footnote-1466729 +Ref: readme_renderer-Footnote-2466778 +Node: setuptools466828 +Ref: key_projects easy-install466952 +Ref: 196466952 +Ref: key_projects id14466952 +Ref: 25e466952 +Ref: setuptools-Footnote-1467467 +Ref: setuptools-Footnote-2467520 +Ref: setuptools-Footnote-3467570 +Ref: setuptools-Footnote-4467613 +Ref: setuptools-Footnote-5467657 +Node: trove-classifiers467701 +Ref: key_projects id15467815 +Ref: 25f467815 +Ref: key_projects trove-classifiers467815 +Ref: 260467815 +Ref: trove-classifiers-Footnote-1468689 +Ref: trove-classifiers-Footnote-2468746 +Ref: trove-classifiers-Footnote-3468796 +Ref: trove-classifiers-Footnote-4468848 +Ref: trove-classifiers-Footnote-5468886 +Ref: trove-classifiers-Footnote-6468978 +Ref: trove-classifiers-Footnote-7469016 +Node: twine469073 +Ref: key_projects id16469190 +Ref: 261469190 +Ref: key_projects twine469190 +Ref: 6d469190 +Ref: twine-Footnote-1469631 +Ref: twine-Footnote-2469679 +Ref: twine-Footnote-3469724 +Ref: twine-Footnote-4469762 +Node: virtualenv<2>469801 +Ref: key_projects id17469910 +Ref: 262469910 +Ref: key_projects virtualenv469910 +Ref: 32469910 +Ref: virtualenv<2>-Footnote-1470500 +Ref: virtualenv<2>-Footnote-2470556 +Ref: virtualenv<2>-Footnote-3470606 +Ref: virtualenv<2>-Footnote-4470649 +Node: Warehouse470694 +Ref: key_projects id18470803 +Ref: 264470803 +Ref: key_projects warehouse470803 +Ref: 265470803 +Ref: Warehouse-Footnote-1471060 +Ref: Warehouse-Footnote-2471095 +Ref: Warehouse-Footnote-3471144 +Ref: Warehouse-Footnote-4471186 +Node: wheel471212 +Ref: key_projects id19471299 +Ref: 266471299 +Ref: key_projects wheel471299 +Ref: 2e471299 +Ref: wheel-Footnote-1471953 +Ref: wheel-Footnote-2472001 +Ref: wheel-Footnote-3472046 +Ref: wheel-Footnote-4472084 +Ref: wheel-Footnote-5472123 +Node: Non-PyPA Projects472166 +Ref: key_projects non-pypa-projects472307 +Ref: 267472307 +Node: buildout472603 +Ref: key_projects buildout472693 +Ref: 169472693 +Ref: key_projects id20472693 +Ref: 268472693 +Ref: buildout-Footnote-1473040 +Ref: buildout-Footnote-2473083 +Ref: buildout-Footnote-3473130 +Ref: buildout-Footnote-4473175 +Node: conda473221 +Ref: key_projects conda473325 +Ref: 16c473325 +Ref: key_projects id21473325 +Ref: 269473325 +Ref: conda-Footnote-1474388 +Ref: conda-Footnote-2474434 +Ref: conda-Footnote-3474478 +Ref: conda-Footnote-4474531 +Node: devpi474639 +Ref: key_projects devpi474742 +Ref: 26a474742 +Ref: key_projects id22474742 +Ref: 26b474742 +Ref: devpi-Footnote-1475071 +Ref: devpi-Footnote-2475108 +Ref: devpi-Footnote-3475154 +Node: enscons475193 +Ref: key_projects enscons475299 +Ref: 26c475299 +Ref: key_projects id23475299 +Ref: 26d475299 +Ref: enscons-Footnote-1475939 +Ref: enscons-Footnote-2475981 +Ref: enscons-Footnote-3476030 +Ref: enscons-Footnote-4476071 +Node: Hashdist476098 +Ref: key_projects hashdist476209 +Ref: 16b476209 +Ref: key_projects id24476209 +Ref: 26e476209 +Ref: Hashdist-Footnote-1476820 +Ref: Hashdist-Footnote-2476871 +Node: multibuild476917 +Ref: key_projects id25477024 +Ref: 26f477024 +Ref: key_projects multibuild477024 +Ref: 11b477024 +Ref: multibuild-Footnote-1477272 +Node: pdm477324 +Ref: key_projects id26477429 +Ref: 270477429 +Ref: key_projects pdm477429 +Ref: 271477429 +Ref: pdm-Footnote-1477811 +Ref: pdm-Footnote-2477842 +Ref: pdm-Footnote-3477886 +Ref: pdm-Footnote-4477923 +Ref: pdm-Footnote-5477972 +Node: pex<2>478021 +Ref: key_projects id27478125 +Ref: 272478125 +Ref: key_projects pex478125 +Ref: 273478125 +Ref: pex<2>-Footnote-1478575 +Ref: pex<2>-Footnote-2478621 +Ref: pex<2>-Footnote-3478664 +Node: pip-tools478701 +Ref: key_projects id28478810 +Ref: 274478810 +Ref: key_projects pip-tools478810 +Ref: 275478810 +Ref: pip-tools-Footnote-1479435 +Ref: pip-tools-Footnote-2479482 +Node: piwheels479526 +Ref: key_projects id29479635 +Ref: 276479635 +Ref: key_projects piwheels479635 +Ref: 277479635 +Ref: piwheels-Footnote-1480038 +Ref: piwheels-Footnote-2480072 +Ref: piwheels-Footnote-3480133 +Node: poetry480179 +Ref: key_projects id30480289 +Ref: 278480289 +Ref: key_projects poetry480289 +Ref: 61480289 +Ref: poetry-Footnote-1480796 +Ref: poetry-Footnote-2480831 +Ref: poetry-Footnote-3480879 +Node: pypiserver480920 +Ref: key_projects id31481032 +Ref: 279481032 +Ref: key_projects pypiserver481032 +Ref: 27a481032 +Ref: pypiserver-Footnote-1481545 +Ref: pypiserver-Footnote-2481617 +Ref: pypiserver-Footnote-3481666 +Node: PyScaffold481711 +Ref: key_projects id32481829 +Ref: 27b481829 +Ref: key_projects pyscaffold481829 +Ref: 27c481829 +Ref: PyScaffold-Footnote-1482351 +Ref: PyScaffold-Footnote-2482382 +Ref: PyScaffold-Footnote-3482431 +Ref: PyScaffold-Footnote-4482476 +Ref: PyScaffold-Footnote-5482519 +Node: scikit-build482565 +Ref: key_projects id33482677 +Ref: 27d482677 +Ref: key_projects scikit-build482677 +Ref: 27e482677 +Ref: scikit-build-Footnote-1483276 +Ref: scikit-build-Footnote-2483331 +Ref: scikit-build-Footnote-3483385 +Ref: scikit-build-Footnote-4483431 +Ref: scikit-build-Footnote-5483470 +Node: shiv483509 +Ref: key_projects id34483619 +Ref: 27f483619 +Ref: key_projects shiv483619 +Ref: 280483619 +Ref: shiv-Footnote-1483958 +Ref: shiv-Footnote-2484005 +Ref: shiv-Footnote-3484046 +Ref: shiv-Footnote-4484085 +Node: Spack<2>484134 +Ref: key_projects id35484245 +Ref: 281484245 +Ref: key_projects spack484245 +Ref: 16a484245 +Ref: Spack<2>-Footnote-1484915 +Ref: Spack<2>-Footnote-2484973 +Ref: Spack<2>-Footnote-3485012 +Ref: Spack<2>-Footnote-4485099 +Node: zest releaser485168 +Ref: key_projects zest-releaser485266 +Ref: 282485266 +Ref: key_projects zestreleaser485266 +Ref: 283485266 +Ref: zest releaser-Footnote-1485674 +Ref: zest releaser-Footnote-2485729 +Ref: zest releaser-Footnote-3485784 +Node: Standard Library Projects485832 +Ref: key_projects standard-library-projects485951 +Ref: 284485951 +Node: ensurepip486059 +Ref: key_projects ensurepip486162 +Ref: 168486162 +Ref: key_projects id36486162 +Ref: 285486162 +Ref: ensurepip-Footnote-1486533 +Ref: ensurepip-Footnote-2486590 +Node: distutils486623 +Ref: key_projects distutils486739 +Ref: be486739 +Ref: key_projects id37486739 +Ref: 286486739 +Ref: distutils-Footnote-1487429 +Ref: distutils-Footnote-2487486 +Node: venv487519 +Ref: key_projects id38487617 +Ref: 287487617 +Ref: key_projects venv487617 +Ref: 7e487617 +Ref: venv-Footnote-1487963 +Ref: venv-Footnote-2488015 +Node: Glossary488048 +Ref: glossary doc488163 +Ref: 288488163 +Ref: glossary glossary488163 +Ref: 289488163 +Ref: glossary pytest488163 +Ref: 28a488163 +Ref: glossary term-Binary-Distribution488186 +Ref: 19f488186 +Ref: glossary term-Built-Distribution488300 +Ref: 68488300 +Ref: glossary term-Distribution-Package488805 +Ref: b488805 +Ref: glossary term-Egg489575 +Ref: 166489575 +Ref: glossary term-Extension-Module489801 +Ref: 28c489801 +Ref: glossary term-Known-Good-Set-KGS490216 +Ref: 28d490216 +Ref: glossary term-Import-Package490583 +Ref: a490583 +Ref: glossary term-Module490970 +Ref: 5a490970 +Ref: glossary term-Package-Index491122 +Ref: e9491122 +Ref: glossary term-Per-Project-Index491255 +Ref: 28f491255 +Ref: glossary term-Project491468 +Ref: 203491468 +Ref: glossary term-Pure-Module492608 +Ref: 28e492608 +Ref: glossary term-Python-Packaging-Authority-PyPA492773 +Ref: 292492773 +Ref: glossary term-Python-Package-Index-PyPI493097 +Ref: 39493097 +Ref: glossary term-pypi org493300 +Ref: 143493300 +Ref: glossary term-pyproject toml493521 +Ref: 1e5493521 +Ref: glossary term-Release493630 +Ref: 28b493630 +Ref: glossary term-Requirement494010 +Ref: 293494010 +Ref: glossary term-Requirement-Specifier494304 +Ref: 3a494304 +Ref: glossary term-Requirements-File494715 +Ref: 294494715 +Ref: glossary term-setup py494924 +Ref: 290494924 +Ref: glossary term-setup cfg494934 +Ref: 291494934 +Ref: glossary term-Source-Archive495076 +Ref: 6a495076 +Ref: glossary term-Source-Distribution-or-sdist495263 +Ref: 3d495263 +Ref: glossary term-System-Package495564 +Ref: 295495564 +Ref: glossary term-Version-Specifier495680 +Ref: 3b495680 +Ref: glossary term-Virtual-Environment496040 +Ref: 263496040 +Ref: glossary term-Wheel496311 +Ref: d496311 +Ref: glossary term-Working-Set496505 +Ref: 296496505 +Ref: Glossary-Footnote-1496789 +Ref: Glossary-Footnote-2496862 +Ref: Glossary-Footnote-3496921 +Ref: Glossary-Footnote-4496970 +Ref: Glossary-Footnote-5497009 +Ref: Glossary-Footnote-6497041 +Ref: Glossary-Footnote-7497076 +Ref: Glossary-Footnote-8497149 +Ref: Glossary-Footnote-9497196 +Ref: Glossary-Footnote-10497221 +Ref: Glossary-Footnote-11497247 +Ref: Glossary-Footnote-12497297 +Ref: Glossary-Footnote-13497365 +Ref: Glossary-Footnote-14497458 +Ref: Glossary-Footnote-15497528 +Ref: Glossary-Footnote-16497578 +Ref: Glossary-Footnote-17497647 +Ref: Glossary-Footnote-18497697 +Node: How to Get Support497758 +Ref: support doc497880 +Ref: 297497880 +Ref: support how-to-get-support497880 +Ref: 298497880 +Ref: How to Get Support-Footnote-1498187 +Ref: How to Get Support-Footnote-2498277 +Node: Contribute to this guide498328 +Ref: contribute doc498446 +Ref: 299498446 +Ref: contribute contribute-to-this-guide498446 +Ref: 29a498446 +Ref: Contribute to this guide-Footnote-1499318 +Ref: Contribute to this guide-Footnote-2499372 +Ref: Contribute to this guide-Footnote-3499432 +Ref: Contribute to this guide-Footnote-4499491 +Node: Documentation types499560 +Ref: contribute documentation-types499675 +Ref: 29c499675 +Ref: contribute id4499675 +Ref: 29d499675 +Node: Tutorials<2>500009 +Ref: contribute tutorials500109 +Ref: 29e500109 +Ref: Tutorials<2>-Footnote-1500399 +Node: Guides<2>500453 +Ref: contribute example-tutorial-style-document500576 +Ref: 29f500576 +Ref: contribute guides500576 +Ref: 2a0500576 +Node: Discussions<2>500959 +Ref: contribute discussions501084 +Ref: 2a1501084 +Node: Specifications501292 +Ref: contribute specifications501399 +Ref: 2a2501399 +Node: Translations501644 +Ref: contribute translations501794 +Ref: 2a3501794 +Ref: Translations-Footnote-1502267 +Ref: Translations-Footnote-2502296 +Ref: Translations-Footnote-3502367 +Ref: Translations-Footnote-4502427 +Node: Adding a language502508 +Ref: contribute adding-a-language502630 +Ref: 2a4502630 +Ref: contribute restructuredtext-syntax502630 +Ref: 2a5502630 +Ref: Adding a language-Footnote-1502893 +Node: Following reStructuredText syntax502964 +Ref: contribute following-restructuredtext-syntax503086 +Ref: 2a6503086 +Ref: Following reStructuredText syntax-Footnote-1503734 +Node: Building the guide locally503802 +Ref: contribute building-the-guide-locally503960 +Ref: 2a7503960 +Ref: contribute this-guide503960 +Ref: 2a8503960 +Ref: Building the guide locally-Footnote-1505036 +Ref: Building the guide locally-Footnote-2505088 +Node: Where the guide is deployed505149 +Ref: contribute where-the-guide-is-deployed505306 +Ref: 2a9505306 +Node: Style guide505570 +Ref: contribute contributing-style-guide505692 +Ref: 29b505692 +Ref: contribute style-guide505692 +Ref: 2aa505692 +Node: Purpose506119 +Ref: contribute purpose506202 +Ref: 2ab506202 +Node: Scope506392 +Ref: contribute scope506492 +Ref: 2ac506492 +Node: Audience506977 +Ref: contribute audience507084 +Ref: 2ad507084 +Node: Voice and tone507598 +Ref: contribute voice-and-tone507725 +Ref: 2ae507725 +Node: Conventions and mechanics508848 +Ref: contribute conventions-and-mechanics508958 +Ref: 2af508958 +Node: News511152 +Ref: news doc511263 +Ref: 2b0511263 +Ref: news news511263 +Ref: 2b1511263 +Node: September 2019511802 +Ref: news september-2019511891 +Ref: 2b2511891 +Ref: September 2019-Footnote-1512050 +Node: August 2019512112 +Ref: news august-2019512219 +Ref: 2b3512219 +Ref: August 2019-Footnote-1512364 +Node: July 2019512426 +Ref: news july-2019512528 +Ref: 2b4512528 +Ref: July 2019-Footnote-1512930 +Ref: July 2019-Footnote-2512992 +Ref: July 2019-Footnote-3513054 +Ref: July 2019-Footnote-4513116 +Ref: July 2019-Footnote-5513178 +Node: June 2019513240 +Ref: news june-2019513339 +Ref: 2b5513339 +Ref: June 2019-Footnote-1513444 +Node: May 2019513506 +Ref: news may-2019513606 +Ref: 2b6513606 +Ref: May 2019-Footnote-1513800 +Ref: May 2019-Footnote-2513862 +Node: April 2019513924 +Ref: news april-2019514025 +Ref: 2b7514025 +Ref: April 2019-Footnote-1514231 +Ref: April 2019-Footnote-2514293 +Node: March 2019514355 +Ref: news march-2019514461 +Ref: 2b8514461 +Ref: March 2019-Footnote-1514669 +Ref: March 2019-Footnote-2514731 +Node: February 2019514793 +Ref: news february-2019514901 +Ref: 2b9514901 +Ref: February 2019-Footnote-1515165 +Ref: February 2019-Footnote-2515227 +Node: January 2019515289 +Ref: news january-2019515400 +Ref: 2ba515400 +Ref: January 2019-Footnote-1515637 +Ref: January 2019-Footnote-2515699 +Ref: January 2019-Footnote-3515761 +Node: December 2018515823 +Ref: news december-2018515934 +Ref: 2bb515934 +Node: November 2018516011 +Ref: news november-2018516122 +Ref: 2bc516122 +Ref: November 2018-Footnote-1516456 +Ref: November 2018-Footnote-2516518 +Ref: November 2018-Footnote-3516580 +Ref: November 2018-Footnote-4516642 +Node: October 2018516704 +Ref: news october-2018516816 +Ref: 2bd516816 +Ref: October 2018-Footnote-1516996 +Ref: October 2018-Footnote-2517058 +Node: September 2018517120 +Ref: news september-2018517230 +Ref: 2be517230 +Ref: September 2018-Footnote-1517617 +Ref: September 2018-Footnote-2517679 +Ref: September 2018-Footnote-3517741 +Ref: September 2018-Footnote-4517803 +Ref: September 2018-Footnote-5517865 +Node: August 2018517927 +Ref: news august-2018518034 +Ref: 2bf518034 +Ref: August 2018-Footnote-1518418 +Ref: August 2018-Footnote-2518480 +Ref: August 2018-Footnote-3518542 +Ref: August 2018-Footnote-4518604 +Node: July 2018518666 +Ref: news july-2018518768 +Ref: 2c0518768 +Ref: July 2018-Footnote-1518945 +Ref: July 2018-Footnote-2519007 +Node: June 2018519069 +Ref: news june-2018519168 +Ref: 2c1519168 +Ref: June 2018-Footnote-1519365 +Ref: June 2018-Footnote-2519427 +Node: May 2018519489 +Ref: news may-2018519589 +Ref: 2c2519589 +Ref: May 2018-Footnote-1520174 +Ref: May 2018-Footnote-2520236 +Ref: May 2018-Footnote-3520298 +Ref: May 2018-Footnote-4520360 +Ref: May 2018-Footnote-5520422 +Ref: May 2018-Footnote-6520484 +Ref: May 2018-Footnote-7520546 +Node: April 2018520608 +Ref: news april-2018520709 +Ref: 2c3520709 +Ref: April 2018-Footnote-1521218 +Ref: April 2018-Footnote-2521280 +Ref: April 2018-Footnote-3521342 +Ref: April 2018-Footnote-4521404 +Ref: April 2018-Footnote-5521466 +Ref: April 2018-Footnote-6521528 +Ref: April 2018-Footnote-7521590 +Node: March 2018521652 +Ref: news march-2018521758 +Ref: 2c4521758 +Ref: March 2018-Footnote-1522119 +Ref: March 2018-Footnote-2522181 +Ref: March 2018-Footnote-3522243 +Ref: March 2018-Footnote-4522305 +Node: February 2018522367 +Ref: news february-2018522475 +Ref: 2c5522475 +Ref: February 2018-Footnote-1522940 +Ref: February 2018-Footnote-2523002 +Ref: February 2018-Footnote-3523064 +Ref: February 2018-Footnote-4523126 +Ref: February 2018-Footnote-5523188 +Node: January 2018523250 +Ref: news january-2018523361 +Ref: 2c6523361 +Ref: January 2018-Footnote-1523554 +Ref: January 2018-Footnote-2523616 +Node: December 2017523678 +Ref: news december-2017523789 +Ref: 2c7523789 +Ref: December 2017-Footnote-1524117 +Ref: December 2017-Footnote-2524179 +Ref: December 2017-Footnote-3524241 +Ref: December 2017-Footnote-4524303 +Node: November 2017524365 +Ref: news november-2017524476 +Ref: 2c8524476 +Ref: November 2017-Footnote-1524933 +Ref: November 2017-Footnote-2524995 +Ref: November 2017-Footnote-3525057 +Ref: November 2017-Footnote-4525119 +Node: October 2017525181 +Ref: news october-2017525293 +Ref: 2c9525293 +Ref: October 2017-Footnote-1525628 +Ref: October 2017-Footnote-2525690 +Ref: October 2017-Footnote-3525752 +Node: September 2017525814 +Ref: news september-2017525924 +Ref: 2ca525924 +Ref: September 2017-Footnote-1526165 +Ref: September 2017-Footnote-2526227 +Node: August 2017526289 +Ref: news august-2017526396 +Ref: 2cb526396 +Ref: August 2017-Footnote-1526692 +Ref: August 2017-Footnote-2526754 +Ref: August 2017-Footnote-3526816 +Node: July 2017526878 +Ref: news july-2017526980 +Ref: 2cc526980 +Ref: July 2017-Footnote-1527495 +Ref: July 2017-Footnote-2527557 +Ref: July 2017-Footnote-3527619 +Ref: July 2017-Footnote-4527681 +Ref: July 2017-Footnote-5527743 +Node: June 2017527805 +Ref: news june-2017527904 +Ref: 2cd527904 +Ref: June 2017-Footnote-1528688 +Ref: June 2017-Footnote-2528750 +Ref: June 2017-Footnote-3528812 +Ref: June 2017-Footnote-4528874 +Ref: June 2017-Footnote-5528936 +Ref: June 2017-Footnote-6528998 +Ref: June 2017-Footnote-7529060 +Ref: June 2017-Footnote-8529122 +Ref: June 2017-Footnote-9529184 +Ref: June 2017-Footnote-10529246 +Ref: June 2017-Footnote-11529309 +Ref: June 2017-Footnote-12529372 +Node: May 2017529435 +Ref: news may-2017529535 +Ref: 2ce529535 +Ref: May 2017-Footnote-1529858 +Ref: May 2017-Footnote-2529920 +Ref: May 2017-Footnote-3529982 +Node: April 2017530044 +Ref: news april-2017530145 +Ref: 2cf530145 +Ref: April 2017-Footnote-1531180 +Ref: April 2017-Footnote-2531242 +Ref: April 2017-Footnote-3531304 +Ref: April 2017-Footnote-4531366 +Ref: April 2017-Footnote-5531428 +Ref: April 2017-Footnote-6531490 +Ref: April 2017-Footnote-7531552 +Ref: April 2017-Footnote-8531614 +Ref: April 2017-Footnote-9531676 +Ref: April 2017-Footnote-10531738 +Ref: April 2017-Footnote-11531801 +Node: March 2017531864 +Ref: news march-2017531970 +Ref: 2d0531970 +Ref: March 2017-Footnote-1532108 +Node: February 2017532170 +Ref: news february-2017532257 +Ref: 2d1532257 +Ref: February 2017-Footnote-1532675 +Ref: February 2017-Footnote-2532724 +Ref: February 2017-Footnote-3532786 +Ref: February 2017-Footnote-4532839 +Node: Get started532878 +Ref: index get-started532975 +Ref: 2d2532975 +Ref: index github532975 +Ref: 2d3532975 +Node: Learn more533642 +Ref: index learn-more533740 +Ref: 2d4533740 +Node: Index534419 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: