diff --git a/source/discussions/index.rst b/source/discussions/index.rst index d262bcff2..1f5ff1f2b 100644 --- a/source/discussions/index.rst +++ b/source/discussions/index.rst @@ -16,3 +16,4 @@ specific topic. If you're just trying to get stuff done, see package-formats src-layout-vs-flat-layout setup-py-deprecated + single-source-version diff --git a/source/discussions/single-source-version.rst b/source/discussions/single-source-version.rst new file mode 100644 index 000000000..9bcab6291 --- /dev/null +++ b/source/discussions/single-source-version.rst @@ -0,0 +1,47 @@ +.. _`Single sourcing the version discussion`: + +=================================== +Single-sourcing the Project Version +=================================== + +:Page Status: Complete +:Last Reviewed: 2024-08-24 + +One of the challenges in building packages is that the version string can be required in multiple places. + +* It needs to be specified when building the package (e.g. in :file:`pyproject.toml`) + This will make it available in the installed package’s metadata, from where it will be accessible at runtime using ``importlib.metadata.version("distribution_name")``. + +* A package may set a module attribute (e.g., ``__version__``) to provide an alternative means of runtime access to the version of the imported package. If this is done, the value of the attribute and that used by the build system to set the distribution's version should be kept in sync in :ref:`the build systems's recommended way `. + +* If the code is in in a version control system (VCS), e.g. Git, the version may appear in a *tag* such as ``v1.2.3``. + +To ensure that version numbers do not get out of sync, it is recommended that there is a single source of truth for the version number. + +In general, the options are: + +1) If the code is in a version control system (VCS), e.g. Git, then the version can be extracted from the VCS. + +2) The version can be hard-coded into the :file:`pyproject.toml` file -- and the build system can copy it into other locations it may be required. + +3) The version string can be hard-coded into the source code -- either in a special purpose file, such as :file:`_version.txt`, or as a attribute in a module, such as :file:`__init__.py`, and the build system can extract it at build time. + + +Consult your build system's documentation for their recommended method. + +.. _Build system version handling: + +Build System Version Handling +----------------------------- + +The following are links to some build system's documentation for handling version strings. + +* `Flit `_ + +* `Hatchling `_ + +* `PDM `_ + +* `Setuptools `_ + + - `setuptools_scm `_ diff --git a/source/guides/creating-command-line-tools.rst b/source/guides/creating-command-line-tools.rst index 9f040ce7d..49ce0c9ed 100644 --- a/source/guides/creating-command-line-tools.rst +++ b/source/guides/creating-command-line-tools.rst @@ -78,7 +78,7 @@ in :file:`cli.py`: import typer - from .hello import greet + from .greet import greet app = typer.Typer() diff --git a/source/guides/github-actions-ci-cd-sample/publish-to-test-pypi.yml b/source/guides/github-actions-ci-cd-sample/publish-to-test-pypi.yml index 3bd06cccc..3c0192b53 100644 --- a/source/guides/github-actions-ci-cd-sample/publish-to-test-pypi.yml +++ b/source/guides/github-actions-ci-cd-sample/publish-to-test-pypi.yml @@ -22,7 +22,7 @@ jobs: - name: Build a binary wheel and a source tarball run: python3 -m build - name: Store the distribution packages - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: python-package-distributions path: dist/ @@ -42,7 +42,7 @@ jobs: steps: - name: Download all the dists - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: python-package-distributions path: dist/ @@ -63,7 +63,7 @@ jobs: steps: - name: Download all the dists - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: python-package-distributions path: dist/ @@ -107,7 +107,7 @@ jobs: steps: - name: Download all the dists - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: python-package-distributions path: dist/ diff --git a/source/guides/packaging-binary-extensions.rst b/source/guides/packaging-binary-extensions.rst index 589ed89c8..de8a9d2d6 100644 --- a/source/guides/packaging-binary-extensions.rst +++ b/source/guides/packaging-binary-extensions.rst @@ -403,3 +403,15 @@ a Debian system, see the following articles: * `What are (c)python extension modules? `_ * `Releasing the gil `_ * `Writing cpython extension modules using C++ `_ + +Additional considerations for binary wheels +------------------------------------------- + +The `pypackaging-native `_ website has +additional coverage of packaging Python packages with native code. It aims to +provide an overview of the most important packaging issues for such projects, +with in-depth explanations and references. + +Examples of topics covered are non-Python compiled dependencies ("native +dependencies"), the importance of the ABI (Application Binary Interface) of +native code, dependency on SIMD code and cross compilation. diff --git a/source/guides/writing-pyproject-toml.rst b/source/guides/writing-pyproject-toml.rst index e82bd893d..d11b8a87c 100644 --- a/source/guides/writing-pyproject-toml.rst +++ b/source/guides/writing-pyproject-toml.rst @@ -22,19 +22,19 @@ three possible TOML tables in this file. .. note:: - There is a significant difference between the ``[build-system]`` and - ``[project]`` tables. The former should always be present, regardless of - which build backend you use (since it *defines* the tool you use). The latter - is understood by *most* build backends, but some build backends use a - different format. + The ``[build-system]`` table should always be present, + regardless of which build backend you use (``[build-system]`` *defines* the + build tool you use). - At the time of writing this (November 2023), Poetry_ is a notable build - backend that does not use the ``[project]`` table (it uses the - ``[tool.poetry]`` table instead). + On the other hand, the ``[project]`` table is understood by *most* build + backends, but some build backends use a different format. + As of August 2024, Poetry_ is a notable build backend that does not use + the ``[project]`` table, it uses the ``[tool.poetry]`` table instead. Also, the setuptools_ build backend supports both the ``[project]`` table, - and the older format in ``setup.cfg`` or ``setup.py``. For new projects, it - is recommended to use the ``[project]`` table, and keep ``setup.py`` only if + and the older format in ``setup.cfg`` or ``setup.py``. + + For new projects, use the ``[project]`` table, and keep ``setup.py`` only if some programmatic configuration is needed (such as building C extensions), but the ``setup.cfg`` and ``setup.py`` formats are still valid. See :ref:`setup-py-deprecated`. @@ -130,7 +130,7 @@ only field that cannot be marked as dynamic. [project] name = "spam-eggs" -The project name must consists of ASCII letters, digits, underscores "``_``", +The project name must consist of ASCII letters, digits, underscores "``_``", hyphens "``-``" and periods "``.``". It must not start or end with an underscore, hyphen or period. diff --git a/source/specifications/core-metadata.rst b/source/specifications/core-metadata.rst index 90793c791..97686c543 100644 --- a/source/specifications/core-metadata.rst +++ b/source/specifications/core-metadata.rst @@ -48,7 +48,7 @@ Metadata-Version .. versionadded:: 1.0 Version of the file format; legal values are "1.0", "1.1", "1.2", "2.1", -"2.2", and "2.3". +"2.2", "2.3", and "2.4". Automated tools consuming metadata SHOULD warn if ``metadata_version`` is greater than the highest version they support, and MUST fail if @@ -63,7 +63,7 @@ all of the needed fields. Example:: - Metadata-Version: 2.3 + Metadata-Version: 2.4 .. _core-metadata-name: @@ -460,6 +460,14 @@ License ======= .. versionadded:: 1.0 +.. deprecated:: 2.4 + in favour of ``License-Expression``. + +.. warning:: + As of Metadata 2.4, ``License`` and ``License-Expression`` are mutually + exclusive. If both are specified, tools which parse metadata will disregard + ``License`` and PyPI will reject uploads. + See `PEP 639 `__. Text indicating the license covering the distribution where the license is not a selection from the "License" Trove classifiers. See @@ -477,6 +485,50 @@ Examples:: License: GPL version 3, excluding DRM provisions +.. _license-expression-optional: +.. _core-metadata-license-expression: + +License-Expression +================== + +.. versionadded:: 2.4 + +Text string that is a valid SPDX +`license expression `__ +as `defined in PEP 639 `__. + +Examples:: + + License-Expression: MIT + License-Expression: BSD-3-Clause + License-Expression: MIT AND (Apache-2.0 OR BSD-2-Clause) + License-Expression: MIT OR GPL-2.0-or-later OR (FSFUL AND BSD-2-Clause) + License-Expression: GPL-3.0-only WITH Classpath-Exception-2.0 OR BSD-3-Clause + License-Expression: LicenseRef-Special-License OR CC0-1.0 OR Unlicense + License-Expression: LicenseRef-Proprietary + + +.. _license-file-optional: +.. _core-metadata-license-file: + +License-File (multiple use) +=========================== + +.. versionadded:: 2.4 + +Each entry is a string representation of the path of a license-related file. +The path is located within the project source tree, relative to the project +root directory. For details see :pep:`639`. + +Examples:: + + License-File: LICENSE + License-File: AUTHORS + License-File: LICENSE.txt + License-File: licenses/LICENSE.MIT + License-File: licenses/LICENSE.CC0 + + .. _metadata-classifier: .. _core-metadata-classifier: @@ -490,6 +542,11 @@ for the distribution. Classifiers are described in :pep:`301`, and the Python Package Index publishes a dynamic list of `currently defined classifiers `__. +.. note:: + The use of ``License ::`` classifiers is deprecated as of Metadata 2.4, + use ``License-Expression`` instead. See + `PEP 639 `_. + This field may be followed by an environment marker after a semicolon. Examples:: @@ -725,7 +782,7 @@ This field may be followed by an environment marker after a semicolon. Examples:: Provides-Dist: OtherProject - Provides-Dist: AnotherProject (3.4) + Provides-Dist: AnotherProject==3.4 Provides-Dist: virtual_package; python_version >= "3.4" .. _core-metadata-obsoletes-dist: @@ -864,6 +921,11 @@ History - Restricted extra names to be normalized. +- August 2024: Core metadata 2.4 was approved through :pep:`639`. + + - Added the ``License-Expression`` field. + - Added the ``License-File`` field. + ---- .. [1] reStructuredText markup: diff --git a/source/specifications/platform-compatibility-tags.rst b/source/specifications/platform-compatibility-tags.rst index 381b84ca9..3679cf4ad 100644 --- a/source/specifications/platform-compatibility-tags.rst +++ b/source/specifications/platform-compatibility-tags.rst @@ -256,7 +256,7 @@ The full list of simple tags is:: for x in pytag.split('.'): for y in abitag.split('.'): - for z in archtag.split('.'): + for z in platformtag.split('.'): yield '-'.join((x, y, z)) A bdist format that implements this scheme should include the expanded @@ -343,5 +343,5 @@ History .. _musl: https://musl.libc.org -.. _ldd: https://www.unix.com/man-page/posix/1/ldd/ +.. _ldd: https://www.man7.org/linux/man-pages/man1/ldd.1.html .. _elf: https://refspecs.linuxfoundation.org/elf/elf.pdf