diff options
author | Sviatoslav Sydorenko <wk@sydorenko.org.ua> | 2023-02-28 16:13:41 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-28 16:13:41 +0100 |
commit | 67bafafbc0d61751d2ec10b0aeccb6b01482a074 (patch) | |
tree | fe0b10e8493e6994da9d9daf1a6184293ceda063 /packaging | |
parent | Add Ansible community 7.3.0 porting guide (#80106) (diff) | |
download | ansible-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.py | 68 |
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 |