Skip to content

Commit 9546a39

Browse files
authored
Merge branch 'main' into patch-1
2 parents f65fa6d + 8b854a4 commit 9546a39

21 files changed

+191
-161
lines changed

.github/CODEOWNERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
source/guides/github-actions-ci-cd-sample/* @webknjaz
22
source/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows.rst @webknjaz
33

4+
# Sphinx extension
5+
pug_sphinx_extensions/ @FFY00
6+
47
# build-details.json
58
source/specifications/build-details/ @FFY00
69
source/specifications/specs/build-details-*.json @FFY00

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ repos:
3737
- id: rst-inline-touching-normal
3838

3939
- repo: https://github.com/astral-sh/ruff-pre-commit
40-
rev: v0.13.3
40+
rev: v0.14.10
4141
hooks:
4242
- id: ruff
4343
- id: ruff-format

pug_sphinx_extensions/__init__.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import os
2+
import pathlib
3+
import urllib
4+
5+
import sphinx.application
6+
import sphinx.util.logging
7+
8+
9+
DOMAIN = "packaging.python.org"
10+
11+
12+
logger = sphinx.util.logging.getLogger(__name__)
13+
14+
15+
def resolve_local_html_link(app: sphinx.application.Sphinx, url_path: str) -> str:
16+
"""Takes path of a link pointing an HTML render of the current project,
17+
and returns local path of the referenced document.
18+
19+
Support links to renders from both the `html` and `dirhtml` builders.
20+
21+
Example:
22+
23+
.. code-block:: python
24+
25+
>>> resolve_local_html_link('https://packaging.python.org/en/latest/flow/')
26+
'{srcdir}/flow.rst'
27+
>>> resolve_local_html_link('https://packaging.python.org/en/latest/flow.html')
28+
'{srcdir}/flow.rst'
29+
>>> resolve_local_html_link('https://packaging.python.org/en/latest/specifications/schemas/')
30+
'{srcdir}/specifications/schemas/index.rst'
31+
>>> resolve_local_html_link('https://packaging.python.org/en/latest/specifications/schemas/build-details-v1.0.schema.json')
32+
'{html_extra_path0}/specifications/schemas/build-details-v1.0.schema.json'
33+
34+
"""
35+
# Search for document in html_extra_path
36+
for entry in app.config.html_extra_path:
37+
candidate = (app.confdir / entry / url_path).resolve()
38+
if candidate.is_dir():
39+
candidate = candidate / "index.html"
40+
if candidate.exists():
41+
return os.fspath(candidate)
42+
# Convert html path to source path
43+
url_path = url_path.removesuffix("/") # Normalize
44+
if url_path.endswith(".html"):
45+
document = url_path.removesuffix(".html")
46+
elif (candidate := f"{url_path}/index") in app.project.docnames:
47+
document = candidate
48+
else:
49+
document = url_path
50+
return app.env.doc2path(document)
51+
52+
53+
def rewrite_local_uri(app: sphinx.application.Sphinx, uri: str) -> str:
54+
"""Replace remote URIs targeting https://packaging.python.org/en/latest/...
55+
with local ones, so that local changes are taken into account by linkcheck.
56+
57+
Additionally, resolve local relative links to html_extra_path.
58+
"""
59+
local_uri = uri
60+
parsed = urllib.parse.urlparse(uri)
61+
# Links to https://packaging.python.org/en/latest/...
62+
if parsed.hostname == DOMAIN and parsed.path.startswith("/en/latest/"):
63+
document = parsed.path.removeprefix("/en/latest/")
64+
local_uri = resolve_local_html_link(app, document)
65+
logger.verbose(
66+
f"{uri!s} is a remote URL that points to local sources, "
67+
"replacing it with a local URL in linkcheck to take new changes "
68+
"into account (pass -vv for more info)"
69+
)
70+
logger.debug(f"Replacing linkcheck URL {uri!r} with {local_uri!r}")
71+
# Local relative links
72+
if not parsed.scheme and not parsed.netloc and parsed.path:
73+
full_path = pathlib.Path(app.env.docname).parent / parsed.path
74+
local_uri = resolve_local_html_link(app, os.fspath(full_path))
75+
if local_uri != uri:
76+
logger.verbose(f"Local linkcheck URL {uri!r} resolved as {local_uri!r}")
77+
return local_uri
78+
79+
80+
def setup(app: sphinx.application.Sphinx) -> dict[str, bool]:
81+
app.connect("linkcheck-process-uri", rewrite_local_uri)
82+
83+
return {
84+
"parallel_read_safe": True,
85+
"parallel_write_safe": True,
86+
}

source/conf.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
33

44
import os
5+
import pathlib
6+
import sys
7+
8+
_ROOT = pathlib.Path(__file__).resolve().parent.parent
9+
sys.path.append(os.fspath(_ROOT))
510

611
# Some options are only enabled for the main packaging.python.org deployment builds
712
RTD_BUILD = bool(os.getenv("READTHEDOCS"))
@@ -22,6 +27,7 @@
2227
root_doc = "index"
2328

2429
extensions = [
30+
"pug_sphinx_extensions",
2531
"sphinx.ext.extlinks",
2632
"sphinx.ext.intersphinx",
2733
"sphinx.ext.todo",
@@ -133,7 +139,6 @@
133139

134140
linkcheck_ignore = [
135141
r"http://localhost:\d+",
136-
r"https://packaging\.python\.org/en/latest/specifications/schemas/.*",
137142
r"https://test\.pypi\.org/project/example-package-YOUR-USERNAME-HERE",
138143
r"https://pypi\.org/manage/.*",
139144
r"https://test\.pypi\.org/manage/.*",
@@ -151,6 +156,10 @@
151156
r"https://click\.palletsprojects\.com/.*",
152157
r"https://typer\.tiangolo\.com/.*",
153158
r"https://www.npmjs.com/.*",
159+
r"https://docutils\.sourceforge\.io/.*",
160+
# Temporarily ignored due to expired TLS cert.
161+
# Ref: https://github.com/pypa/packaging.python.org/issues/1998
162+
r"https://blog\.ganssle\.io/.*",
154163
]
155164
linkcheck_retries = 5
156165
# Ignore anchors for common targets when we know they likely won't be found
@@ -162,9 +171,6 @@
162171
# https://github.com/pypa/packaging.python.org/issues/1744
163172
r"https://pypi\.org/",
164173
]
165-
linkcheck_exclude_documents = [
166-
"specifications/schemas/index",
167-
]
168174

169175
# -- Options for extlinks ----------------------------------------------------------
170176
# https://www.sphinx-doc.org/en/master/usage/extensions/extlinks.html#configuration

source/glossary.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ Glossary
160160

161161
A string with valid SPDX license expression syntax,
162162
including one or more SPDX :term:`License Identifier`\(s),
163-
which describes a :term:`Project`'s license(s)
163+
which describes a :term:`Distribution Archive`'s license(s)
164164
and how they inter-relate.
165165
Examples:
166166
``GPL-3.0-or-later``,
@@ -287,8 +287,7 @@ Glossary
287287
PyPA is a working group that maintains many of the relevant
288288
projects in Python packaging. They maintain a site at
289289
:doc:`pypa.io <pypa:index>`, host projects on `GitHub
290-
<https://github.com/pypa>`_ and `Bitbucket
291-
<https://bitbucket.org/pypa>`_, and discuss issues on the
290+
<https://github.com/pypa>`_, and discuss issues on the
292291
`distutils-sig mailing list
293292
<https://mail.python.org/mailman3/lists/distutils-sig.python.org/>`_
294293
and `the Python Discourse forum <https://discuss.python.org/c/packaging>`__.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ To just run the program without installing it permanently, use ``pipx run``, whi
154154
$ pipx run --spec . greet --doctor
155155
156156
This syntax is a bit impractical, however; as the name of the entry point we defined above does not match the package name,
157-
we need to state explicitly which executable script to run (even though there is only on in existence).
157+
we need to state explicitly which executable script to run (even though there is only one in existence).
158158

159159
There is, however, a more practical solution to this problem, in the form of an entry point specific to ``pipx run``.
160160
The same can be defined as follows in :file:`pyproject.toml`:

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ jobs:
88
runs-on: ubuntu-latest
99

1010
steps:
11-
- uses: actions/checkout@v4
11+
- uses: actions/checkout@v6
1212
with:
1313
persist-credentials: false
1414
- name: Set up Python
15-
uses: actions/setup-python@v5
15+
uses: actions/setup-python@v6
1616
with:
1717
python-version: "3.x"
1818
- name: Install pypa/build
@@ -24,7 +24,7 @@ jobs:
2424
- name: Build a binary wheel and a source tarball
2525
run: python3 -m build
2626
- name: Store the distribution packages
27-
uses: actions/upload-artifact@v4
27+
uses: actions/upload-artifact@v5
2828
with:
2929
name: python-package-distributions
3030
path: dist/
@@ -44,7 +44,7 @@ jobs:
4444

4545
steps:
4646
- name: Download all the dists
47-
uses: actions/download-artifact@v4
47+
uses: actions/download-artifact@v6
4848
with:
4949
name: python-package-distributions
5050
path: dist/
@@ -66,7 +66,7 @@ jobs:
6666

6767
steps:
6868
- name: Download all the dists
69-
uses: actions/download-artifact@v4
69+
uses: actions/download-artifact@v6
7070
with:
7171
name: python-package-distributions
7272
path: dist/

source/guides/licensing-examples-and-user-scenarios.rst

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ Licensing examples and user scenarios
66
=====================================
77

88

9-
:pep:`639` has specified the way to declare a project's license and paths to
10-
license files and other legally required information.
9+
:pep:`639` has specified the way to declare a :term:`Distribution Archive`'s
10+
license and paths to license files and other legally required information.
1111
This document aims to provide clear guidance how to migrate from the legacy
1212
to the standardized way of declaring licenses.
1313
Make sure your preferred build backend supports :pep:`639` before
@@ -53,7 +53,7 @@ Or, if the project used :file:`setup.cfg`, in its ``[metadata]`` table:
5353
[metadata]
5454
license = MIT
5555
56-
The output Core Metadata for the distribution packages would then be:
56+
The output Core Metadata for the :term:`Distribution Package` would then be:
5757

5858
.. code-block:: email
5959
@@ -63,8 +63,9 @@ The output Core Metadata for the distribution packages would then be:
6363
The :file:`LICENSE` file would be stored at :file:`/setuptools-{VERSION}/LICENSE`
6464
in the sdist and :file:`/setuptools-{VERSION}.dist-info/licenses/LICENSE`
6565
in the wheel, and unpacked from there into the site directory (e.g.
66-
:file:`site-packages/`) on installation; :file:`/` is the root of the respective archive
67-
and ``{VERSION}`` the version of the Setuptools release in the Core Metadata.
66+
:file:`site-packages/`) on installation; :file:`/` is the root of the respective
67+
archive and ``{VERSION}`` the version of the Setuptools release in the Core
68+
Metadata.
6869

6970

7071
.. _licensing-example-advanced:
@@ -83,7 +84,7 @@ directories; specifically:
8384
ordered-set==3.1.1
8485
more_itertools==8.8.0
8586
86-
The license expressions for these projects are:
87+
The appropriate license expressions are:
8788

8889
.. code-block:: text
8990
@@ -287,7 +288,7 @@ and make sure to remove any legacy ``license`` table subkeys or
287288
``License ::`` classifiers. Your existing ``license`` value may already
288289
be valid as one (e.g. ``MIT``, ``Apache-2.0 OR BSD-2-Clause``, etc);
289290
otherwise, check the `SPDX license list <spdxlist_>`__ for the identifier
290-
that matches the license used in your project.
291+
that matches the license used.
291292

292293
Make sure to list your license files under ``license-files``
293294
under ``[project]`` in :file:`pyproject.toml`
@@ -312,12 +313,11 @@ to describe the licenses involved and the relationship
312313
between them.
313314

314315
In short, ``License-1 AND License-2`` mean that *both* licenses apply
315-
to your project, or parts of it (for example, you included a file
316-
under another license), and ``License-1 OR License-2`` means that
317-
*either* of the licenses can be used, at the user's option (for example,
318-
you want to allow users a choice of multiple licenses). You can use
319-
parenthesis (``()``) for grouping to form expressions that cover even the most
320-
complex situations.
316+
(for example, you included a file under another license), and
317+
``License-1 OR License-2`` means that *either* of the licenses can be used, at
318+
the user's option (for example, you want to allow users a choice of multiple
319+
licenses). You can use parenthesis (``()``) for grouping to form expressions
320+
that cover even the most complex situations.
321321

322322
In your project config file, enter your license expression under
323323
``license`` (``[project]`` table of :file:`pyproject.toml`),

source/guides/multi-version-installs.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,3 @@ time, but that approach does mean that standard command line invocations of
3737
the affected tools can't be used - it's necessary to write a custom
3838
wrapper script or use ``python3 -c '<command>'`` to invoke the application's
3939
main entry point directly.
40-
41-
Refer to the `pkg_resources documentation
42-
<https://setuptools.readthedocs.io/en/latest/pkg_resources.html#workingset-objects>`__
43-
for more details.

source/guides/packaging-namespace-packages.rst

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,7 @@ Legacy namespace packages
159159

160160
These two methods, that were used to create namespace packages prior to :pep:`420`,
161161
are now considered to be obsolete and should not be used unless you need compatibility
162-
with packages already using this method. Also, :doc:`pkg_resources <setuptools:pkg_resources>`
163-
has been deprecated.
162+
with packages already using one of these methods.
164163

165164
To migrate an existing package, all packages sharing the namespace must be migrated simultaneously.
166165

@@ -176,7 +175,7 @@ pkgutil-style namespace packages
176175
Python 2.3 introduced the :doc:`pkgutil <python:library/pkgutil>` module and the
177176
:py:func:`python:pkgutil.extend_path` function. This can be used to declare namespace
178177
packages that need to be compatible with both Python 2.3+ and Python 3. This
179-
is the recommended approach for the highest level of compatibility.
178+
was the recommended approach for the highest level of compatibility.
180179

181180
To create a pkgutil-style namespace package, you need to provide an
182181
:file:`__init__.py` file for the namespace package:
@@ -216,10 +215,18 @@ in the `pkgutil namespace example project`_.
216215
pkg_resources-style namespace packages
217216
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
218217

219-
:doc:`Setuptools <setuptools:index>` provides the `pkg_resources.declare_namespace`_ function and
218+
.. warning::
219+
220+
The information in this section is obsolete and is no longer functional
221+
(as of Setuptools 82.0.0). It is only retained for historical reference.
222+
223+
``pkg_resources`` has been deprecated and was fully removed in Setuptools 82.0.0.
224+
225+
:doc:`Setuptools <setuptools:index>` previously provided the ``pkg_resources.declare_namespace`` function and
220226
the ``namespace_packages`` argument to :func:`~setuptools.setup`. Together
221-
these can be used to declare namespace packages. While this approach is no
222-
longer recommended, it is widely present in most existing namespace packages.
227+
these could be used to declare namespace packages. While this approach is no
228+
longer supported, it may still be encountered in environments using older
229+
``setuptools`` versions.
223230
If you are creating a new distribution within an existing namespace package that
224231
uses this method then it's recommended to continue using this as the different
225232
methods are not cross-compatible and it's not advisable to try to migrate an
@@ -281,11 +288,3 @@ to :func:`~setuptools.setup` in :file:`setup.py`. For example:
281288
packages=find_packages()
282289
namespace_packages=['mynamespace']
283290
)
284-
285-
A complete working example of two pkg_resources-style namespace packages can be found
286-
in the `pkg_resources namespace example project`_.
287-
288-
.. _pkg_resources.declare_namespace:
289-
https://setuptools.readthedocs.io/en/latest/pkg_resources.html#namespace-package-support
290-
.. _pkg_resources namespace example project:
291-
https://github.com/pypa/sample-namespace-packages/tree/master/pkg_resources

0 commit comments

Comments
 (0)