mirror of
https://github.com/zebrajr/ansible.git
synced 2025-12-06 00:19:48 +01:00
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>
109 lines
3.6 KiB
Python
109 lines
3.6 KiB
Python
"""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/`
|
|
]
|