@ -5,8 +5,11 @@ from __future__ import annotations
import os
import os
import subprocess
import subprocess
import sys
import sys
import typing as t
from configparser import ConfigParser
from configparser import ConfigParser
from contextlib import suppress
from importlib . metadata import import_module
from importlib . metadata import import_module
from io import StringIO
from pathlib import Path
from pathlib import Path
from setuptools . build_meta import (
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 ,
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
__all__ = ( # noqa: WPS317, WPS410
' build_sdist ' , ' get_requires_for_build_sdist ' ,
' 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 :
def _make_in_tree_ansible_importable ( ) - > None :
""" Add the library directory to module lookup paths. """
""" Add the library directory to module lookup paths. """
lib_path = str ( Path . cwd ( ) / ' lib/ ' )
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
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 ' )
cfg_version = setup_cfg . get ( ' metadata ' , ' version ' )
importable_version_str = cfg_version . removeprefix ( ' attr: ' )
importable_version_str = cfg_version . removeprefix ( ' attr: ' )
version_mod_str , version_var_str = importable_version_str . rsplit ( ' . ' , 1 )
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 )
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. """
""" Create ``*.1.rst.in`` files out of CLI Python modules. """
generate_man_cmd = (
generate_man_cmd = (
sys . executable ,
sys . executable ,
@ -53,41 +66,43 @@ def _generate_rst_in_templates() -> Path:
return Path ( ' docs/man/man1/ ' ) . glob ( ' *.1.rst.in ' )
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.
""" Render pre-made ``*.1.rst.in`` templates into manpages.
This includes pasting the hardcoded version into the resulting files .
This includes pasting the hardcoded version into the resulting files .
The resulting ` ` in ` ` - files are wiped in the process .
The resulting ` ` in ` ` - files are wiped in the process .
"""
"""
templated_rst_doc = rst_in . with_suffix ( ' ' )
templated_rst_doc = rst_doc_template . replace ( ' % VERSION % ' , version_number )
templated_rst_doc . write_text (
rst_in . read_text ( ) . replace ( ' % VERSION % ' , version_number ) )
rst_in . unlink ( )
with StringIO ( templated_rst_doc ) as in_mem_rst_doc :
publish_file (
rst2man_cmd = (
source = in_mem_rst_doc ,
sys . executable ,
destination_path = destination_path ,
Path ( sys . executable ) . parent / ' rst2man.py ' ,
writer = manpage . Writer ( ) ,
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
def build_sdist ( # noqa: WPS210, WPS430
sdist_directory : os . PathLike ,
sdist_directory : os . PathLike ,
config_settings : dict [ str , str ] | None = None ,
config_settings : dict [ str , str ] | None = None ,
) - > str :
) - > str :
build_manpages_requested = ' --build-manpages ' in (
build_manpages_requested = BUILD_MANPAGES_CONFIG_SETTING in (
config_settings or { }
config_settings or { }
)
)
if build_manpages_requested :
if build_manpages_requested :
Path ( ' docs/man/man1/ ' ) . mkdir ( exist_ok = True , parents = True )
Path ( ' docs/man/man1/ ' ) . mkdir ( exist_ok = True , parents = True )
_make_in_tree_ansible_importable ( )
version_number = _get_package_distribution_version ( )
version_number = _get_package_distribution_version ( )
for rst_in in _generate_rst_in_templates ( ) :
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 (
return _setuptools_build_sdist (
sdist_directory = sdist_directory ,
sdist_directory = sdist_directory ,
@ -98,10 +113,17 @@ def build_sdist( # noqa: WPS210, WPS430
def get_requires_for_build_sdist (
def get_requires_for_build_sdist (
config_settings : dict [ str , str ] | None = None ,
config_settings : dict [ str , str ] | None = None ,
) - > list [ str ] :
) - > list [ str ] :
return _setuptools_get_requires_for_build_sdist (
build_manpages_requested = BUILD_MANPAGES_CONFIG_SETTING in (
config_settings = config_settings ,
config_settings or { }
) + [
)
build_manpages_requested = True # FIXME: Once pypa/build#559 is addressed.
manpage_build_deps = [
' docutils ' , # provides `rst2man`
' docutils ' , # provides `rst2man`
' jinja2 ' , # used in `hacking/build-ansible.py generate-man`
' jinja2 ' , # used in `hacking/build-ansible.py generate-man`
' pyyaml ' , # needed for importing in-tree `ansible-core` from `lib/`
' 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