You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ansible/packaging/pep517_backend/_backend.py

108 lines
3.5 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`
'pyyaml', # needed for importing in-tree `ansible-core` from `lib/`
]