summaryrefslogtreecommitdiff
path: root/packaging
diff options
context:
space:
mode:
authorSviatoslav Sydorenko <webknjaz@redhat.com>2023-03-07 22:35:11 +0100
committerGitHub <noreply@github.com>2023-03-07 13:35:11 -0800
commitbfc26f55cc01c6be3bb77923424fef6f9778d9fd (patch)
tree5fb5dadfce03d3c4b19eb7a04b6126e8700e8ed1 /packaging
parent6be77608c6a73df9713ce37728a5505b2ae587e8 (diff)
downloadansible-bfc26f55cc01c6be3bb77923424fef6f9778d9fd.tar.gz
[backport-2.14] 📦 Integrate manpage builds into PEP 517 build backend (#80129)
This patch creates a thin wrapper around the `setuptools`' PEP 517 build backend in-tree. It features an ability to request generating the manpage files in the process of building a source distribution. This toggle is implemented using the `config_settings` mechanism of PEP 517. One must explicitly pass it a CLI option to the build front-end to trigger said behavior. The packagers are expected to use the following call: python -m build --config-setting=--build-manpages This option has no effect on building wheels. 🧪 The change includes integration tests This test runs building and re-building sdists and wheels with and without the `--build-manpages` config setting under the oldest-supported and new `setuptools` pinned. It is intended to preserve the interoperability of the packaging setup across Python runtimes. An extra smoke test also verifies that non PEP 517 interfaces remain functional. PR #79606 Co-authored-by: Matt Clay <matt@mystile.com> (cherry picked from commit 56036013cd09db0f1b20402a69be44345ddafb22)
Diffstat (limited to 'packaging')
-rw-r--r--packaging/pep517_backend/__init__.py1
-rw-r--r--packaging/pep517_backend/_backend.py108
-rw-r--r--packaging/pep517_backend/hooks.py9
3 files changed, 118 insertions, 0 deletions
diff --git a/packaging/pep517_backend/__init__.py b/packaging/pep517_backend/__init__.py
new file mode 100644
index 0000000000..1d3bc14c82
--- /dev/null
+++ b/packaging/pep517_backend/__init__.py
@@ -0,0 +1 @@
+"""PEP 517 build backend for optionally pre-building docs before setuptools."""
diff --git a/packaging/pep517_backend/_backend.py b/packaging/pep517_backend/_backend.py
new file mode 100644
index 0000000000..9adbc50f2f
--- /dev/null
+++ b/packaging/pep517_backend/_backend.py
@@ -0,0 +1,108 @@
+"""PEP 517 build backend wrapper for optionally pre-building docs for sdist."""
+
+from __future__ import annotations
+
+import os
+import subprocess
+import sys
+from configparser import ConfigParser
+from importlib.metadata import import_module
+from pathlib import Path
+
+from setuptools.build_meta import (
+ build_sdist as _setuptools_build_sdist,
+ get_requires_for_build_sdist as _setuptools_get_requires_for_build_sdist,
+)
+
+
+__all__ = ( # noqa: WPS317, WPS410
+ 'build_sdist', 'get_requires_for_build_sdist',
+)
+
+
+def _make_in_tree_ansible_importable() -> None:
+ """Add the library directory to module lookup paths."""
+ lib_path = str(Path.cwd() / 'lib/')
+ os.environ['PYTHONPATH'] = lib_path # NOTE: for subprocesses
+ sys.path.insert(0, lib_path) # NOTE: for the current runtime session
+
+
+def _get_package_distribution_version() -> str:
+ """Retrieve the current version number from setuptools config."""
+ setup_cfg_path = Path.cwd() / 'setup.cfg'
+ setup_cfg = ConfigParser()
+ setup_cfg.read_string(setup_cfg_path.read_text())
+ cfg_version = setup_cfg.get('metadata', 'version')
+ importable_version_str = cfg_version.removeprefix('attr: ')
+ version_mod_str, version_var_str = importable_version_str.rsplit('.', 1)
+ return getattr(import_module(version_mod_str), version_var_str)
+
+
+def _generate_rst_in_templates() -> Path:
+ """Create ``*.1.rst.in`` files out of CLI Python modules."""
+ generate_man_cmd = (
+ sys.executable,
+ 'hacking/build-ansible.py',
+ 'generate-man',
+ '--template-file=docs/templates/man.j2',
+ '--output-dir=docs/man/man1/',
+ '--output-format=man',
+ *Path('lib/ansible/cli/').glob('*.py'),
+ )
+ subprocess.check_call(tuple(map(str, generate_man_cmd)))
+ return Path('docs/man/man1/').glob('*.1.rst.in')
+
+
+def _convert_rst_in_template_to_manpage(rst_in, version_number) -> None:
+ """Render pre-made ``*.1.rst.in`` templates into manpages.
+
+ This includes pasting the hardcoded version into the resulting files.
+ The resulting ``in``-files are wiped in the process.
+ """
+ templated_rst_doc = rst_in.with_suffix('')
+ templated_rst_doc.write_text(
+ rst_in.read_text().replace('%VERSION%', version_number))
+
+ rst_in.unlink()
+
+ rst2man_cmd = (
+ sys.executable,
+ Path(sys.executable).parent / 'rst2man.py',
+ templated_rst_doc,
+ templated_rst_doc.with_suffix(''),
+ )
+ subprocess.check_call(tuple(map(str, rst2man_cmd)))
+ templated_rst_doc.unlink()
+
+
+def build_sdist( # noqa: WPS210, WPS430
+ sdist_directory: os.PathLike,
+ config_settings: dict[str, str] | None = None,
+) -> str:
+ build_manpages_requested = '--build-manpages' in (
+ config_settings or {}
+ )
+ if build_manpages_requested:
+ Path('docs/man/man1/').mkdir(exist_ok=True, parents=True)
+ _make_in_tree_ansible_importable()
+ version_number = _get_package_distribution_version()
+ for rst_in in _generate_rst_in_templates():
+ _convert_rst_in_template_to_manpage(rst_in, version_number)
+
+ return _setuptools_build_sdist(
+ sdist_directory=sdist_directory,
+ config_settings=config_settings,
+ )
+
+
+def get_requires_for_build_sdist(
+ config_settings: dict[str, str] | None = None,
+) -> list[str]:
+ return _setuptools_get_requires_for_build_sdist(
+ config_settings=config_settings,
+ ) + [
+ 'docutils', # provides `rst2man`
+ 'jinja2', # used in `hacking/build-ansible.py generate-man`
+ 'straight.plugin', # used in `hacking/build-ansible.py` for subcommand
+ 'pyyaml', # needed for importing in-tree `ansible-core` from `lib/`
+ ]
diff --git a/packaging/pep517_backend/hooks.py b/packaging/pep517_backend/hooks.py
new file mode 100644
index 0000000000..b834338a6d
--- /dev/null
+++ b/packaging/pep517_backend/hooks.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+"""PEP 517 build backend for optionally pre-building docs before setuptools."""
+
+from setuptools.build_meta import * # Re-exporting PEP 517 hooks # pylint: disable=unused-wildcard-import,wildcard-import
+
+from ._backend import ( # noqa: WPS436 # Re-exporting PEP 517 hooks
+ build_sdist, get_requires_for_build_sdist,
+)