@ -134,6 +134,14 @@ def install(pip, options): # type: (str, t.Dict[str, t.Any]) -> None
options . extend ( packages )
for path , content in requirements :
if path . split ( os . sep ) [ 0 ] in ( ' test ' , ' requirements ' ) :
# Support for pre-build is currently limited to requirements embedded in ansible-test and those used by ansible-core.
# Requirements from ansible-core can be found in the 'test' and 'requirements' directories.
# This feature will probably be extended to support collections after further testing.
# Requirements from collections can be found in the 'tests' directory.
for pre_build in parse_pre_build_instructions ( content ) :
pre_build . execute ( pip )
write_text_file ( os . path . join ( tempdir , path ) , content , True )
options . extend ( [ ' -r ' , path ] )
@ -150,6 +158,61 @@ def install(pip, options): # type: (str, t.Dict[str, t.Any]) -> None
remove_tree ( tempdir )
class PreBuild :
""" Parsed pre-build instructions. """
def __init__ ( self , requirement ) : # type: (str) -> None
self . requirement = requirement
self . constraints = [ ] # type: list[str]
def execute ( self , pip ) : # type: (str) -> None
""" Execute these pre-build instructions. """
tempdir = tempfile . mkdtemp ( prefix = ' ansible-test- ' , suffix = ' -pre-build ' )
try :
options = common_pip_options ( )
options . append ( self . requirement )
constraints = ' \n ' . join ( self . constraints ) + ' \n '
constraints_path = os . path . join ( tempdir , ' constraints.txt ' )
write_text_file ( constraints_path , constraints , True )
env = common_pip_environment ( )
env . update ( PIP_CONSTRAINT = constraints_path )
command = [ sys . executable , pip , ' wheel ' ] + options
execute_command ( command , env = env , cwd = tempdir )
finally :
remove_tree ( tempdir )
def parse_pre_build_instructions ( requirements ) : # type: (str) -> list[PreBuild]
""" Parse the given pip requirements and return a list of extracted pre-build instructions. """
# CAUTION: This code must be kept in sync with the sanity test hashing code in:
# test/lib/ansible_test/_internal/commands/sanity/__init__.py
pre_build_prefix = ' # pre-build '
pre_build_requirement_prefix = pre_build_prefix + ' requirement: '
pre_build_constraint_prefix = pre_build_prefix + ' constraint: '
lines = requirements . splitlines ( )
pre_build_lines = [ line for line in lines if line . startswith ( pre_build_prefix ) ]
instructions = [ ] # type: list[PreBuild]
for line in pre_build_lines :
if line . startswith ( pre_build_requirement_prefix ) :
instructions . append ( PreBuild ( line [ len ( pre_build_requirement_prefix ) : ] ) )
elif line . startswith ( pre_build_constraint_prefix ) :
instructions [ - 1 ] . constraints . append ( line [ len ( pre_build_constraint_prefix ) : ] )
else :
raise RuntimeError ( ' Unsupported pre-build comment: ' + line )
return instructions
def uninstall ( pip , options ) : # type: (str, t.Dict[str, t.Any]) -> None
""" Perform a pip uninstall. """
packages = options [ ' packages ' ]