summaryrefslogtreecommitdiffstats
path: root/packaging
diff options
context:
space:
mode:
authorSviatoslav Sydorenko <wk@sydorenko.org.ua>2023-02-28 16:13:41 +0100
committerGitHub <noreply@github.com>2023-02-28 16:13:41 +0100
commit67bafafbc0d61751d2ec10b0aeccb6b01482a074 (patch)
treefe0b10e8493e6994da9d9daf1a6184293ceda063 /packaging
parentAdd Ansible community 7.3.0 porting guide (#80106) (diff)
downloadansible-67bafafbc0d61751d2ec10b0aeccb6b01482a074.tar.xz
ansible-67bafafbc0d61751d2ec10b0aeccb6b01482a074.zip
🎨 Convert RST to manpage in-memory @ PEP 517 (#80098)
* Add _convert_rst_in_template_to_manpage arg types * 📦 Make manpage build dependencies conditional Previously, said dependencies were declared as unconditionally required even when manpages not needed to be built. This patch Makes it so they are only required when needed. * Correct _generate_rst_in_templates returned type It was marked as Path before this patch but in fact, it's iterable of paths. * 🎨 Convert RST to manpage in-memory @ PEP 517 Previously, the automation was writing a temporary templated RST on disk and calling a helper CLI script on that. But with this change, it happens with less unnecessary I/O. Co-Authored-By: Matt Davis <6775756+nitzmahone@users.noreply.github.com> * 📦Expose sdist manpage build deps unconditionally Due to a bug in pypa/build, the `get_requires_for_build_sdist()` hook is always invoked with `config_settings=None`. This means that we cannot conditionally extend build requirements in said hook. As a workaround, this patch makes hook pretend that `--built-manpages` is always passed. Ref: https://github.com/pypa/build/issues/559. --------- Co-authored-by: Matt Davis <6775756+nitzmahone@users.noreply.github.com>
Diffstat (limited to 'packaging')
-rw-r--r--packaging/pep517_backend/_backend.py68
1 files changed, 45 insertions, 23 deletions
diff --git a/packaging/pep517_backend/_backend.py b/packaging/pep517_backend/_backend.py
index 14bc911aaa..d4451ac14e 100644
--- a/packaging/pep517_backend/_backend.py
+++ b/packaging/pep517_backend/_backend.py
@@ -5,8 +5,11 @@ from __future__ import annotations
import os
import subprocess
import sys
+import typing as t
from configparser import ConfigParser
+from contextlib import suppress
from importlib.metadata import import_module
+from io import StringIO
from pathlib import Path
from setuptools.build_meta import (
@@ -14,16 +17,25 @@ from setuptools.build_meta import (
get_requires_for_build_sdist as _setuptools_get_requires_for_build_sdist,
)
+with suppress(ImportError):
+ # NOTE: Only available for sdist builds that bundle manpages. Declared by
+ # NOTE: `get_requires_for_build_sdist()` when `--build-manpages` is passed.
+ from docutils.core import publish_file
+ from docutils.writers import manpage
+
__all__ = ( # noqa: WPS317, WPS410
'build_sdist', 'get_requires_for_build_sdist',
)
+BUILD_MANPAGES_CONFIG_SETTING = '--build-manpages'
+"""Config setting name toggle that is used to request manpage in sdists."""
+
+
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
@@ -35,10 +47,11 @@ def _get_package_distribution_version() -> str:
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)
+ _make_in_tree_ansible_importable()
return getattr(import_module(version_mod_str), version_var_str)
-def _generate_rst_in_templates() -> Path:
+def _generate_rst_in_templates() -> t.Iterable[Path]:
"""Create ``*.1.rst.in`` files out of CLI Python modules."""
generate_man_cmd = (
sys.executable,
@@ -53,41 +66,43 @@ def _generate_rst_in_templates() -> Path:
return Path('docs/man/man1/').glob('*.1.rst.in')
-def _convert_rst_in_template_to_manpage(rst_in, version_number) -> None:
+def _convert_rst_in_template_to_manpage(
+ rst_doc_template: str,
+ destination_path: os.PathLike,
+ version_number: str,
+) -> 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))
+ templated_rst_doc = rst_doc_template.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()
+ with StringIO(templated_rst_doc) as in_mem_rst_doc:
+ publish_file(
+ source=in_mem_rst_doc,
+ destination_path=destination_path,
+ writer=manpage.Writer(),
+ )
def build_sdist( # noqa: WPS210, WPS430
sdist_directory: os.PathLike,
config_settings: dict[str, str] | None = None,
) -> str:
- build_manpages_requested = '--build-manpages' in (
+ build_manpages_requested = BUILD_MANPAGES_CONFIG_SETTING 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)
+ _convert_rst_in_template_to_manpage(
+ rst_doc_template=rst_in.read_text(),
+ destination_path=rst_in.with_suffix('').with_suffix(''),
+ version_number=version_number,
+ )
+ rst_in.unlink()
return _setuptools_build_sdist(
sdist_directory=sdist_directory,
@@ -98,10 +113,17 @@ def build_sdist( # noqa: WPS210, WPS430
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,
- ) + [
+ build_manpages_requested = BUILD_MANPAGES_CONFIG_SETTING in (
+ config_settings or {}
+ )
+ build_manpages_requested = True # FIXME: Once pypa/build#559 is addressed.
+
+ manpage_build_deps = [
'docutils', # provides `rst2man`
'jinja2', # used in `hacking/build-ansible.py generate-man`
'pyyaml', # needed for importing in-tree `ansible-core` from `lib/`
- ]
+ ] if build_manpages_requested else []
+
+ return _setuptools_get_requires_for_build_sdist(
+ config_settings=config_settings,
+ ) + manpage_build_deps