====== 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%%%%. ===== Cheatsheet ===== ==== General ==== * 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. ==== Dependencies ==== * 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**. ==== Tests ==== * 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.