PyProject

The future of Python builds, distribution, and packaging lies in pyproject.toml. The protocol has been incrementally built through PEPs 517, 518, PEP 621, PEP 631, and PEP 660.


Build System

This is the focus of PEP 517. A minimal example of the Build System section is:

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

From here, different backends will have different requirements.

Setuptools

To use the setuptools.build_meta backend, an additional setup.cfg file is needed.

A minimal example would be:

[metadata]
name = my-project
version = 1.0.2
description = This is the short description
long_description = file: path/to/my/long/description
license = GPL
author = John Doe
author_email = [email protected]
url = example.com/my-project

[options]
packages = my-project
python_requires = >= 3.6
install_requires =
    toml >= 0.10.2

[options.entry_points]
console_scripts =
    my-project-cli = my-project:main

You will note that this is highly duplicative of the below Project section.

Setuptools (Legacy)

With all of the above in place, it's possible to use a simple shim setup.py. This will enable setup.py install to continue to work.

import setuptools
if __name__ == "__main__":
    setuptools.setup()


Project

This is the focus of PEP 621. It is more-or-less a direct mapping of a boilerplate setup.py file into the TOML format.

[project]                           
name = "my-project"    
description = "This is the short description"
readme = "path/to/my/long/description"                     
version = "1.0.2"                                                     
authors = [ { name = "John Doe", email = "[email protected]" } ] 
urls = { homepage = "example.com/my-project" }                   
license = { file = "path/to/my/license" }          
requires-python = ">=3.6"                
dependencies = [                         
    "toml >= 0.10.1",                    
]

[project.scripts]
my-project-cli = "my-project:main"

Some notable changes from setup.py:

Dependencies

PEP 631 furthered the design of dependencies and introduced optional-dependencies. This is the pyproject.toml of docker-compose:

[project]
dependencies = [
  'cached-property >= 1.2.0, < 2',
  'distro >= 1.5.0, < 2',
  'docker[ssh] >= 4.2.2, < 5',
  'dockerpty >= 0.4.1, < 1',
  'docopt >= 0.6.1, < 1',
  'jsonschema >= 2.5.1, < 4',
  'PyYAML >= 3.10, < 6',
  'python-dotenv >= 0.13.0, < 1',
  'requests >= 2.20.0, < 3',
  'texttable >= 0.9.0, < 2',
  'websocket-client >= 0.32.0, < 1',

  # Conditional
  'backports.shutil_get_terminal_size == 1.0.0; python_version < "3.3"',
  'backports.ssl_match_hostname >= 3.5, < 4; python_version < "3.5"',
  'colorama >= 0.4, < 1; sys_platform == "win32"',
  'enum34 >= 1.0.4, < 2; python_version < "3.4"',
  'ipaddress >= 1.0.16, < 2; python_version < "3.3"',
  'subprocess32 >= 3.5.4, < 4; python_version < "3.2"',
]

[project.optional-dependencies]
socks = [ 'PySocks >= 1.5.6, != 1.5.7, < 2' ]
tests = [
  'ddt >= 1.2.2, < 2',
  'pytest < 6',
  'mock >= 1.0.1, < 4; python_version < "3.4"',
]


CategoryRicottone