diff options
Diffstat (limited to 'packaging/pep517_backend/_backend.py')
-rw-r--r-- | packaging/pep517_backend/_backend.py | 108 |
1 files changed, 108 insertions, 0 deletions
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/` + ] |