Skip to content

Commit 8d8b310

Browse files
Merge branch 'conda_notes' of https://github.com/ChrisBarker-NOAA/python-packaging-user-guide into conda_notes
2 parents 78be284 + 0f301ce commit 8d8b310

19 files changed

+480
-228
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.6.0
3+
rev: v5.0.0
44
hooks:
55
- id: check-added-large-files
66
- id: check-case-conflict
@@ -34,7 +34,7 @@ repos:
3434
- id: rst-inline-touching-normal
3535

3636
- repo: https://github.com/astral-sh/ruff-pre-commit
37-
rev: v0.4.10
37+
rev: v0.7.1
3838
hooks:
3939
- id: ruff
4040
- id: ruff-format

source/contribute.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Tutorials are focused on teaching the reader new concepts by accomplishing a
4545
goal. They are opinionated step-by-step guides. They do not include extraneous
4646
warnings or information. `example tutorial-style document`_.
4747

48-
.. _example tutorial-style document: https://docs.djangoproject.com/en/1.11/intro/
48+
.. _example tutorial-style document: https://docs.djangoproject.com/en/dev/intro/
4949

5050
Guides
5151
------

source/discussions/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ specific topic. If you're just trying to get stuff done, see
1616
package-formats
1717
src-layout-vs-flat-layout
1818
setup-py-deprecated
19+
single-source-version

source/discussions/setup-py-deprecated.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ This guide does not make suggestions of replacement solutions for those commands
141141
* ``easy_install``
142142
* ``editable_wheel``
143143
* ``egg_info``
144-
* ``install``
145144
* ``install_data``
146145
* ``install_egg_info``
147146
* ``install_headers``
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
.. _single-source-version:
2+
3+
===================================
4+
Single-sourcing the Project Version
5+
===================================
6+
7+
:Page Status: Complete
8+
:Last Reviewed: 2024-10-07
9+
10+
Many Python :term:`distribution packages <Distribution Package>` publish a single
11+
Python :term:`import package <Import Package>` where it is desired that the runtime
12+
``__version__`` attribute on the import package report the same version specifier
13+
as :func:`importlib.metadata.version` reports for the distribution package
14+
(as described in :ref:`runtime-version-access`).
15+
16+
It is also frequently desired that this version information be derived from a version
17+
control system *tag* (such as ``v1.2.3``) rather than being manually updated in the
18+
source code.
19+
20+
Some projects may choose to simply live with the data entry duplication, and rely
21+
on automated testing to ensure the different values do not diverge.
22+
23+
Alternatively, a project's chosen build system may offer a way to define a single
24+
source of truth for the version number.
25+
26+
In general, the options are:
27+
28+
1) If the code is in a version control system (VCS), such as Git, then the version can be extracted from the VCS.
29+
30+
2) The version can be hard-coded into the :file:`pyproject.toml` file -- and the build system can copy it
31+
into other locations it may be required.
32+
33+
3) The version string can be hard-coded into the source code -- either in a special purpose file,
34+
such as :file:`_version.txt` (which must then be shipped as part of the project's source distribution
35+
package), or as an attribute in a particular module, such as :file:`__init__.py`. The build
36+
system can then extract it from the runtime location at build time.
37+
38+
Consult your build system's documentation for their recommended method.
39+
40+
When the intention is that a distribution package and its associated import package
41+
share the same version, it is recommended that the project include an automated test
42+
case that ensures ``import_name.__version__`` and ``importlib.metadata.version("dist-name")``
43+
report the same value (note: for many projects, ``import_name`` and ``dist-name`` will
44+
be the same name).
45+
46+
47+
.. _Build system version handling:
48+
49+
Build System Version Handling
50+
-----------------------------
51+
52+
The following are links to some build system's documentation for handling version strings.
53+
54+
* `Flit <https://flit.pypa.io/en/stable/>`_
55+
56+
* `Hatchling <https://hatch.pypa.io/1.9/version/>`_
57+
58+
* `PDM <https://pdm-project.org/en/latest/reference/pep621/#__tabbed_1_2>`_
59+
60+
* `Setuptools <https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html#dynamic-metadata>`_
61+
62+
- `setuptools_scm <https://setuptools-scm.readthedocs.io/en/latest/>`_

source/discussions/versioning.rst

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ numbering scheme that readily conveys the approximate age of a release, but
153153
doesn't otherwise commit to a particular release cadence within the year.
154154

155155

156-
157156
Local version identifiers
158157
=========================
159158

@@ -172,6 +171,54 @@ since the latest release, setuptools-scm generates a version like
172171
"0.5.dev1+gd00980f", or if the repository has untracked changes, like
173172
"0.5.dev1+gd00980f.d20231217".
174173

174+
.. _runtime-version-access:
175+
176+
Accessing version information at runtime
177+
========================================
178+
179+
Version information for all :term:`distribution packages <Distribution Package>`
180+
that are locally available in the current environment can be obtained at runtime
181+
using the standard library's :func:`importlib.metadata.version` function::
182+
183+
>>> importlib.metadata.version("cryptography")
184+
'41.0.7'
185+
186+
Many projects also choose to version their top level
187+
:term:`import packages <Import Package>` by providing a package level
188+
``__version__`` attribute::
189+
190+
>>> import cryptography
191+
>>> cryptography.__version__
192+
'41.0.7'
193+
194+
This technique can be particularly valuable for CLI applications which want
195+
to ensure that version query invocations (such as ``pip -V``) run as quickly
196+
as possible.
197+
198+
Package publishers wishing to ensure their reported distribution package and
199+
import package versions are consistent with each other can review the
200+
:ref:`single-source-version` discussion for potential approaches to doing so.
201+
202+
As import packages and modules are not *required* to publish runtime
203+
version information in this way (see the withdrawn proposal in
204+
:pep:`PEP 396 <396>`), the ``__version__`` attribute should either only be
205+
queried with interfaces that are known to provide it (such as a project
206+
querying its own version or the version of one of its direct dependencies),
207+
or else the querying code should be designed to handle the case where the
208+
attribute is missing [#fallback-to-dist-version]_.
209+
210+
Some projects may need to publish version information for external APIs
211+
that aren't the version of the module itself. Such projects should
212+
define their own project-specific ways of obtaining the relevant information
213+
at runtime. For example, the standard library's :mod:`ssl` module offers
214+
multiple ways to access the underlying OpenSSL library version::
215+
216+
>>> ssl.OPENSSL_VERSION
217+
'OpenSSL 3.2.2 4 Jun 2024'
218+
>>> ssl.OPENSSL_VERSION_INFO
219+
(3, 2, 0, 2, 0)
220+
>>> hex(ssl.OPENSSL_VERSION_NUMBER)
221+
'0x30200020'
175222

176223
--------------------------------------------------------------------------------
177224

@@ -184,6 +231,15 @@ since the latest release, setuptools-scm generates a version like
184231
Brett Cannon <semver-brett-cannon_>`_. For a humoristic take, read about
185232
ZeroVer_.
186233
234+
.. [#fallback-to-dist-version] A full list mapping the top level names available
235+
for import to the distribution packages that provide those import packages and
236+
modules may be obtained through the standard library's
237+
:func:`importlib.metadata.packages_distributions` function. This means that
238+
even code that is attempting to infer a version to report for all importable
239+
top-level names has a means to fall back to reporting the distribution
240+
version information if no ``__version__`` attribute is defined. Only standard
241+
library modules, and modules added via means other than Python package
242+
installation would fail to have version information reported in that case.
187243
188244
189245
.. _zerover: https://0ver.org

source/guides/creating-command-line-tools.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ in :file:`cli.py`:
7878
7979
import typer
8080
81-
from .hello import greet
81+
from .greet import greet
8282
8383
8484
app = typer.Typer()

source/guides/github-actions-ci-cd-sample/publish-to-test-pypi.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
- name: Build a binary wheel and a source tarball
2323
run: python3 -m build
2424
- name: Store the distribution packages
25-
uses: actions/upload-artifact@v3
25+
uses: actions/upload-artifact@v4
2626
with:
2727
name: python-package-distributions
2828
path: dist/
@@ -42,7 +42,7 @@ jobs:
4242

4343
steps:
4444
- name: Download all the dists
45-
uses: actions/download-artifact@v3
45+
uses: actions/download-artifact@v4
4646
with:
4747
name: python-package-distributions
4848
path: dist/
@@ -63,12 +63,12 @@ jobs:
6363

6464
steps:
6565
- name: Download all the dists
66-
uses: actions/download-artifact@v3
66+
uses: actions/download-artifact@v4
6767
with:
6868
name: python-package-distributions
6969
path: dist/
7070
- name: Sign the dists with Sigstore
71-
uses: sigstore/gh-action-sigstore-python@v2.1.1
71+
uses: sigstore/gh-action-sigstore-python@v3.0.0
7272
with:
7373
inputs: >-
7474
./dist/*.tar.gz
@@ -107,7 +107,7 @@ jobs:
107107

108108
steps:
109109
- name: Download all the dists
110-
uses: actions/download-artifact@v3
110+
uses: actions/download-artifact@v4
111111
with:
112112
name: python-package-distributions
113113
path: dist/

source/guides/packaging-binary-extensions.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,3 +403,15 @@ a Debian system, see the following articles:
403403
* `What are (c)python extension modules? <https://thomasnyberg.com/what_are_extension_modules.html>`_
404404
* `Releasing the gil <https://thomasnyberg.com/releasing_the_gil.html>`_
405405
* `Writing cpython extension modules using C++ <https://thomasnyberg.com/cpp_extension_modules.html>`_
406+
407+
Additional considerations for binary wheels
408+
-------------------------------------------
409+
410+
The `pypackaging-native <https://pypackaging-native.github.io/>`_ website has
411+
additional coverage of packaging Python packages with native code. It aims to
412+
provide an overview of the most important packaging issues for such projects,
413+
with in-depth explanations and references.
414+
415+
Examples of topics covered are non-Python compiled dependencies ("native
416+
dependencies"), the importance of the ABI (Application Binary Interface) of
417+
native code, dependency on SIMD code and cross compilation.

source/guides/section-build-and-publish.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ Building and Publishing
77

88
writing-pyproject-toml
99
distributing-packages-using-setuptools
10-
single-sourcing-package-version
1110
dropping-older-python-versions
1211
packaging-binary-extensions
1312
packaging-namespace-packages

0 commit comments

Comments
 (0)