Python Packaging Best Practices

Slightly opinionated, but nevertheless informed (imho) list of Python Packaging Best Practices, based on copious amounts of experience with many diverse Python projects, as a user and a packager.

This list seeks to be “tool” (solution) agnostic where possible, and describe things in terms of needs and outcomes, with the driving motivations being:

  • PEP20 relevant (obvious, explicit, etc)
  • Reducing friction, saving (everyone) time.
  • Making your software easy to consume
  • Encouraging contributions to your software
  • Transcending the “downstream vs upstream divide”

We'll flesh out the motivations and caveats later.

Note: setup.py means setup.py or setup.cfg or other equivalent one place that has your package metadata.

  • Have a clear LICENSE
    • Pick a well-defined existing LICENSE.
    • Have a LICENSE file in your repository
    • Include LICENSE file to the source distribution (sdist). Use MANIFEST.in or setup.py:data_files
    • Define LICENSE in setup.py:license
  • Clearly declare exact Python version support. setup.py:python_requires. This should at least match your CI coverage.
  • Declare all dependencies in one place, in one way. This includes optional (setup.py:extras_require) and test dependencies (setup.py:tests_require)
  • Put development dependencies in extras_require[dev], not tests_require. They are not compulsory.
    • Understand the distinctions between development and user testing (eg: the latter doesn't want/need coverage, pylint, pep8 etc).
  • Use >= version specs for distribution dependencies.
    • Understand the distinctions between packaging and deployment (pinned) dependencies.
    • Use these for development testing too. This makes sure issues are picked up in development early, and before releases/users.
    • Use the lowest supported version of a dependency that your code requires.
  • Have a HOW TO RUN TESTS section in your README in the repository root. Noone should need to go looking.
  • Have one entry point, and ideally one command to run tests.
  • Include tests, test data files, and test related files in the source distribution. Use MANIFEST.in and/or setup.py:packages
  • Tests that need some external thing (package, file, environment) SKIP not FAIL if that test requirement is not fulfilled.
  • Run tests using the the source distribution. This gets you coverage of the user test scenario and tests the complete packaging pipeline.
  • kubilaykocak/pythonpackagingbcp.txt
  • Last modified: 2020/05/02 05:05
  • by KubilayKocak