def test_pex_python(): with temporary_dir() as td: pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: pex_python = ensure_python_interpreter('3.6.3') pexrc.write("PEX_PYTHON=%s" % pex_python) # test PEX_PYTHON with valid constraints pex_out_path = os.path.join(td, 'pex.pex') res = run_pex_command(['--disable-cache', '--rcfile=%s' % pexrc_path, '--interpreter-constraint=>3', '--interpreter-constraint=<3.8', '-o', pex_out_path]) res.assert_success() stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload) assert rc == 0 correct_interpreter_path = pex_python.encode() assert correct_interpreter_path in stdout # test PEX_PYTHON with incompatible constraints pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: pex_python = ensure_python_interpreter('2.7.10') pexrc.write("PEX_PYTHON=%s" % pex_python) pex_out_path = os.path.join(td, 'pex2.pex') res = run_pex_command(['--disable-cache', '--rcfile=%s' % pexrc_path, '--interpreter-constraint=>3', '--interpreter-constraint=<3.8', '-o', pex_out_path]) res.assert_success() stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload) assert rc == 1 fail_str = 'not compatible with specified interpreter constraints'.encode() assert fail_str in stdout # test PEX_PYTHON with no constraints pex_out_path = os.path.join(td, 'pex3.pex') res = run_pex_command(['--disable-cache', '--rcfile=%s' % pexrc_path, '-o', pex_out_path]) res.assert_success() stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload) assert rc == 0 correct_interpreter_path = pex_python.encode() assert correct_interpreter_path in stdout
def test_interpreter_resolution_pex_python_path_precedence_over_pex_python(): with temporary_dir() as td: pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: # set both PPP and PP pex_python_path = ':'.join([ ensure_python_interpreter('2.7.10'), ensure_python_interpreter('3.6.3') ]) pexrc.write("PEX_PYTHON_PATH=%s\n" % pex_python_path) pex_python = '/path/to/some/python' pexrc.write("PEX_PYTHON=%s" % pex_python) pex_out_path = os.path.join(td, 'pex.pex') res = run_pex_command(['--disable-cache', '--rcfile=%s' % pexrc_path, '--interpreter-constraint=>3', '--interpreter-constraint=<3.8', '-o', pex_out_path]) res.assert_success() stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload) assert rc == 0 correct_interpreter_path = pex_python_path.split(':')[1].encode() assert correct_interpreter_path in stdout
def test_interpreter_resolution_with_pex_python_path(): with temporary_dir() as td: pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: # set pex python path pex_python_path = ':'.join([ ensure_python_interpreter('2.7.10'), ensure_python_interpreter('3.6.3') ]) pexrc.write("PEX_PYTHON_PATH=%s" % pex_python_path) # constraints to build pex cleanly; PPP + pex_bootstrapper.py # will use these constraints to override sys.executable on pex re-exec interpreter_constraint1 = '>3' if sys.version_info[0] == 3 else '<3' interpreter_constraint2 = '<3.8' if sys.version_info[0] == 3 else '>=2.7' pex_out_path = os.path.join(td, 'pex.pex') res = run_pex_command(['--disable-cache', '--rcfile=%s' % pexrc_path, '--interpreter-constraint=%s' % interpreter_constraint1, '--interpreter-constraint=%s' % interpreter_constraint2, '-o', pex_out_path]) res.assert_success() stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload) assert rc == 0 if sys.version_info[0] == 3: assert str(pex_python_path.split(':')[1]).encode() in stdout else: assert str(pex_python_path.split(':')[0]).encode() in stdout
def test_pex_exec_with_pex_python_path_and_pex_python_but_no_constraints(): with temporary_dir() as td: pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: # set both PPP and PP pex_python_path = ':'.join([ ensure_python_interpreter('2.7.10'), ensure_python_interpreter('3.6.3') ]) pexrc.write("PEX_PYTHON_PATH=%s\n" % pex_python_path) pex_python = '/path/to/some/python' pexrc.write("PEX_PYTHON=%s" % pex_python) pex_out_path = os.path.join(td, 'pex.pex') res = run_pex_command(['--disable-cache', '--rcfile=%s' % pexrc_path, '-o', pex_out_path]) res.assert_success() # test that pex bootstrapper selects lowest version interpreter # in pex python path (python2.7) stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload) assert rc == 0 assert str(pex_python_path.split(':')[0]).encode() in stdout
def test_access_zipped_assets_integration(): test_executable = dedent(''' import os from _pex.util import DistributionHelper temp_dir = DistributionHelper.access_zipped_assets('my_package', 'submodule') with open(os.path.join(temp_dir, 'mod.py'), 'r') as fp: for line in fp: print(line) ''') with nested(temporary_dir(), temporary_dir()) as (td1, td2): pb = PEXBuilder(path=td1) with open(os.path.join(td1, 'exe.py'), 'w') as fp: fp.write(test_executable) pb.set_executable(fp.name) submodule = os.path.join(td1, 'my_package', 'submodule') safe_mkdir(submodule) mod_path = os.path.join(submodule, 'mod.py') with open(mod_path, 'w') as fp: fp.write('accessed') pb.add_source(fp.name, 'my_package/submodule/mod.py') pex = os.path.join(td2, 'app.pex') pb.build(pex) output, returncode = run_simple_pex(pex) try: output = output.decode('UTF-8') except ValueError: pass assert output == 'accessed\n' assert returncode == 0
def test_plain_pex_exec_no_ppp_no_pp_no_constraints(): with temporary_dir() as td: pex_out_path = os.path.join(td, 'pex.pex') res = run_pex_command(['--disable-cache', '-o', pex_out_path]) res.assert_success() stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload) assert rc == 0 assert str(sys.executable).encode() in stdout
def test_pex_repl_built(): """Tests the REPL in the context of a built pex.""" stdin_payload = b'import requests; import sys; sys.exit(3)' with temporary_dir() as output_dir: # Create a temporary pex containing just `requests` with no entrypoint. pex_path = os.path.join(output_dir, 'requests.pex') results = run_pex_command(['--disable-cache', 'requests', '-o', pex_path]) results.assert_success() # Test that the REPL is functional. stdout, rc = run_simple_pex(pex_path, stdin=stdin_payload) assert rc == 3 assert b'>>>' in stdout
def write_and_run_simple_pex(inheriting=False): """Write a pex file that contains an executable entry point :param inheriting: whether this pex should inherit site-packages paths :type inheriting: bool """ with temporary_dir() as td: pex_path = os.path.join(td, 'show_path.pex') with open(os.path.join(td, 'exe.py'), 'w') as fp: fp.write('') # No contents, we just want the startup messages pb = PEXBuilder(path=td, preamble=None) pb.info.inherit_path = inheriting pb.set_executable(os.path.join(td, 'exe.py')) pb.freeze() pb.build(pex_path) yield run_simple_pex(pex_path, env={'PEX_VERBOSE': '1'})[0]
def test_pex_path_in_pex_info_and_env(): with temporary_dir() as output_dir: # create 2 pex files for PEX-INFO pex_path pex1_path = os.path.join(output_dir, 'pex1.pex') res1 = run_pex_command(['--disable-cache', 'requests', '-o', pex1_path]) res1.assert_success() pex2_path = os.path.join(output_dir, 'pex2.pex') res2 = run_pex_command(['--disable-cache', 'flask', '-o', pex2_path]) res2.assert_success() pex_path = ':'.join(os.path.join(output_dir, name) for name in ('pex1.pex', 'pex2.pex')) # create a pex for environment PEX_PATH pex3_path = os.path.join(output_dir, 'pex3.pex') res3 = run_pex_command(['--disable-cache', 'wheel', '-o', pex3_path]) res3.assert_success() env_pex_path = os.path.join(output_dir, 'pex3.pex') # parameterize the pex arg for test.py pex_out_path = os.path.join(output_dir, 'out.pex') # create test file test.py that attempts to import modules from pex1/pex2 test_file_path = os.path.join(output_dir, 'test.py') with open(test_file_path, 'w') as fh: fh.write(dedent(''' import requests import flask import wheel import sys import os import subprocess print('Success!') ''')) # build out.pex composed from pex1/pex1 run_pex_command(['--disable-cache', '--pex-path={}'.format(pex_path), '-o', pex_out_path]) # load secondary PEX_PATH env = os.environ.copy() env['PEX_PATH'] = env_pex_path # run test.py with composite env stdout, rc = run_simple_pex(pex_out_path, [test_file_path], env=env) assert rc == 0 assert stdout == b'Success!\n'
def test_pex_re_exec_failure(): with temporary_dir() as output_dir: # create 2 pex files for PEX_PATH pex1_path = os.path.join(output_dir, 'pex1.pex') res1 = run_pex_command(['--disable-cache', 'requests', '-o', pex1_path]) res1.assert_success() pex2_path = os.path.join(output_dir, 'pex2.pex') res2 = run_pex_command(['--disable-cache', 'flask', '-o', pex2_path]) res2.assert_success() pex_path = ':'.join(os.path.join(output_dir, name) for name in ('pex1.pex', 'pex2.pex')) # create test file test.py that attmepts to import modules from pex1/pex2 test_file_path = os.path.join(output_dir, 'test.py') with open(test_file_path, 'w') as fh: fh.write(dedent(''' import requests import flask import sys import os import subprocess if 'RAN_ONCE' in os.environ:: print('Hello world') else: env = os.environ.copy() env['RAN_ONCE'] = '1' subprocess.call([sys.executable] + sys.argv, env=env) sys.exit() ''')) # set up env for pex build with PEX_PATH in the environment env = os.environ.copy() env['PEX_PATH'] = pex_path # build composite pex of pex1/pex1 pex_out_path = os.path.join(output_dir, 'out.pex') run_pex_command(['--disable-cache', 'wheel', '-o', pex_out_path]) # run test.py with composite env stdout, rc = run_simple_pex(pex_out_path, [test_file_path], env=env) assert rc == 0 assert stdout == b'Hello world\n'
def test_entry_point_targeting(): """Test bugfix for https://github.com/pantsbuild/pex/issues/434""" with temporary_dir() as td: pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: pex_python = ensure_python_interpreter('3.6.3') pexrc.write("PEX_PYTHON=%s" % pex_python) # test pex with entry point pex_out_path = os.path.join(td, 'pex.pex') res = run_pex_command(['--disable-cache', 'autopep8', '-e', 'autopep8', '-o', pex_out_path]) res.assert_success() stdout, rc = run_simple_pex(pex_out_path) assert 'usage: autopep8'.encode() in stdout
def test_pex_path_arg(): with temporary_dir() as output_dir: # create 2 pex files for PEX_PATH pex1_path = os.path.join(output_dir, 'pex1.pex') res1 = run_pex_command(['--disable-cache', 'requests', '-o', pex1_path]) res1.assert_success() pex2_path = os.path.join(output_dir, 'pex2.pex') res2 = run_pex_command(['--disable-cache', 'flask', '-o', pex2_path]) res2.assert_success() pex_path = ':'.join(os.path.join(output_dir, name) for name in ('pex1.pex', 'pex2.pex')) # parameterize the pex arg for test.py pex_out_path = os.path.join(output_dir, 'out.pex') # create test file test.py that attempts to import modules from pex1/pex2 test_file_path = os.path.join(output_dir, 'test.py') with open(test_file_path, 'w') as fh: fh.write(dedent(''' import requests import flask import sys import os import subprocess if 'RAN_ONCE' in os.environ: print('Success!') else: env = os.environ.copy() env['RAN_ONCE'] = '1' subprocess.call([sys.executable] + ['%s'] + sys.argv, env=env) sys.exit() ''' % pex_out_path)) # build out.pex composed from pex1/pex1 run_pex_command(['--disable-cache', '--pex-path={}'.format(pex_path), 'wheel', '-o', pex_out_path]) # run test.py with composite env stdout, rc = run_simple_pex(pex_out_path, [test_file_path]) assert rc == 0 assert stdout == b'Success!\n'
def inherit_path(inherit_path): with temporary_dir() as output_dir: exe = os.path.join(output_dir, 'exe.py') body = "import sys ; print('\\n'.join(sys.path))" with open(exe, 'w') as f: f.write(body) pex_path = os.path.join(output_dir, 'pex.pex') results = run_pex_command([ '--disable-cache', 'msgpack_python', '--inherit-path{}'.format(inherit_path), '-o', pex_path, ]) results.assert_success() env = os.environ.copy() env["PYTHONPATH"] = "/doesnotexist" stdout, rc = run_simple_pex( pex_path, args=(exe, ), env=env, ) assert rc == 0 stdout_lines = stdout.decode().split('\n') requests_paths = tuple(i for i, l in enumerate(stdout_lines) if 'msgpack_python' in l) sys_paths = tuple(i for i, l in enumerate(stdout_lines) if 'doesnotexist' in l) assert len(requests_paths) == 1 assert len(sys_paths) == 1 if inherit_path == "=fallback": assert requests_paths[0] < sys_paths[0] else: assert requests_paths[0] > sys_paths[0]
def test_pex_source_bundling(): with temporary_dir() as output_dir: with temporary_dir() as input_dir: with open(os.path.join(input_dir, 'exe.py'), 'w') as fh: fh.write(dedent(''' print('hello') ''')) pex_path = os.path.join(output_dir, 'pex1.pex') res = run_pex_command([ '-o', pex_path, '-D', input_dir, '-e', 'exe', ]) res.assert_success() stdout, rc = run_simple_pex(pex_path) assert rc == 0 assert stdout == b'hello\n'
def test_pex_exec_with_pex_python_path_only(): with temporary_dir() as td: pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: # set pex python path pex_python_path = ':'.join([ ensure_python_interpreter('2.7.10'), ensure_python_interpreter('3.6.3') ]) pexrc.write("PEX_PYTHON_PATH=%s" % pex_python_path) pex_out_path = os.path.join(td, 'pex.pex') res = run_pex_command(['--disable-cache', '--rcfile=%s' % pexrc_path, '-o', pex_out_path]) res.assert_success() # test that pex bootstrapper selects lowest version interpreter # in pex python path (python2.7) stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload) assert rc == 0 assert str(pex_python_path.split(':')[0]).encode() in stdout
def inherit_path(inherit_path): with temporary_dir() as output_dir: exe = os.path.join(output_dir, 'exe.py') body = "import sys ; print('\\n'.join(sys.path))" with open(exe, 'w') as f: f.write(body) pex_path = os.path.join(output_dir, 'pex.pex') results = run_pex_command([ '--disable-cache', 'requests', '--inherit-path{}'.format(inherit_path), '-o', pex_path, ]) results.assert_success() env = os.environ.copy() env["PYTHONPATH"] = "/doesnotexist" stdout, rc = run_simple_pex( pex_path, args=(exe,), env=env, ) assert rc == 0 stdout_lines = stdout.split('\n') requests_paths = tuple(i for i, l in enumerate(stdout_lines) if 'requests' in l) sys_paths = tuple(i for i, l in enumerate(stdout_lines) if 'doesnotexist' in l) assert len(requests_paths) == 1 assert len(sys_paths) == 1 if inherit_path == "=fallback": assert requests_paths[0] < sys_paths[0] else: assert requests_paths[0] > sys_paths[0]
def test_pex_run_strip_env(): with temporary_dir() as pex_root: pex_env = dict(PEX_MODULE='does_not_exist_in_sub_pex', PEX_ROOT=pex_root) with environment_as(**pex_env), temporary_dir() as pex_chroot: pex_builder = PEXBuilder(path=pex_chroot) with tempfile.NamedTemporaryFile(mode="w") as fp: fp.write(dedent(""" import json import os print(json.dumps({k: v for k, v in os.environ.items() if k.startswith("PEX_")})) """)) fp.flush() pex_builder.set_executable(fp.name, 'print_pex_env.py') pex_builder.freeze() stdout, returncode = run_simple_pex(pex_chroot) assert 0 == returncode assert {} == json.loads(stdout.decode('utf-8')), ( 'Expected the entrypoint environment to be stripped of PEX_ environment variables.' ) assert pex_env == {k: v for k, v in os.environ.items() if k.startswith("PEX_")}, ( 'Expected the parent environment to be left un-stripped.' )
def test_interpreter_selection_using_os_environ_for_bootstrap_reexec(): """ This is a test for verifying the proper function of the pex bootstrapper's interpreter selection logic and validate a corresponding bugfix. More details on the nature of the bug can be found at: https://github.com/pantsbuild/pex/pull/441 """ with temporary_dir() as td: pexrc_path = os.path.join(td, '.pexrc') # Select pexrc interpreter versions based on test environment. # The parent interpreter is the interpreter we expect the parent pex to # execute with. The child interpreter is the interpreter we expect the # child pex to execute with. if (sys.version_info[0], sys.version_info[1]) == (3, 6): child_pex_interpreter_version = PY36 else: child_pex_interpreter_version = PY27 # Write parent pex's pexrc. with open(pexrc_path, 'w') as pexrc: pexrc.write("PEX_PYTHON=%s" % sys.executable) test_setup_path = os.path.join(td, 'setup.py') with open(test_setup_path, 'w') as fh: fh.write( dedent(''' from setuptools import setup setup( name='tester', version='1.0', description='tests', author='tester', author_email='*****@*****.**', packages=['testing'] ) ''')) os.mkdir(os.path.join(td, 'testing')) test_init_path = os.path.join(td, 'testing/__init__.py') with open(test_init_path, 'w') as fh: fh.write( dedent(''' def tester(): from pex.testing import ( run_pex_command, run_simple_pex, temporary_dir ) import os from textwrap import dedent with temporary_dir() as td: pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: pexrc.write("PEX_PYTHON={}") test_file_path = os.path.join(td, 'build_and_run_child_pex.py') with open(test_file_path, 'w') as fh: fh.write(dedent(""" import sys print(sys.executable) """)) pex_out_path = os.path.join(td, 'child.pex') res = run_pex_command(['--disable-cache', '-o', pex_out_path]) stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload) print(stdout) '''.format(ensure_python_interpreter(child_pex_interpreter_version)))) pex_out_path = os.path.join(td, 'parent.pex') res = run_pex_command([ '--disable-cache', 'pex', '{}'.format(td), '-e', 'testing:tester', '-o', pex_out_path ]) res.assert_success() stdout, rc = run_simple_pex(pex_out_path) assert rc == 0 # Ensure that child pex used the proper interpreter as specified by its pexrc. correct_interpreter_path = ensure_python_interpreter( child_pex_interpreter_version) correct_interpreter_path = correct_interpreter_path.encode( ) # Py 2/3 compatibility assert correct_interpreter_path in stdout
def test_pex_python(): py2_path_interpreter = ensure_python_interpreter(PY27) py3_path_interpreter = ensure_python_interpreter(PY36) path = ':'.join([ os.path.dirname(py2_path_interpreter), os.path.dirname(py3_path_interpreter) ]) env = make_env(PATH=path) with temporary_dir() as td: pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: pex_python = ensure_python_interpreter(PY36) pexrc.write("PEX_PYTHON=%s" % pex_python) # test PEX_PYTHON with valid constraints pex_out_path = os.path.join(td, 'pex.pex') res = run_pex_command([ '--disable-cache', '--rcfile=%s' % pexrc_path, '--interpreter-constraint=>3', '--interpreter-constraint=<3.8', '-o', pex_out_path ], env=env) res.assert_success() stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload, env=env) assert rc == 0 correct_interpreter_path = pex_python.encode() assert correct_interpreter_path in stdout # test PEX_PYTHON with incompatible constraints pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: pex_python = ensure_python_interpreter(PY27) pexrc.write("PEX_PYTHON=%s" % pex_python) pex_out_path = os.path.join(td, 'pex2.pex') res = run_pex_command([ '--disable-cache', '--rcfile=%s' % pexrc_path, '--interpreter-constraint=>3', '--interpreter-constraint=<3.8', '-o', pex_out_path ], env=env) res.assert_success() stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload, env=env) assert rc == 1 fail_str = 'not compatible with specified interpreter constraints'.encode( ) assert fail_str in stdout # test PEX_PYTHON with no constraints pex_out_path = os.path.join(td, 'pex3.pex') res = run_pex_command([ '--disable-cache', '--rcfile=%s' % pexrc_path, '-o', pex_out_path ], env=env) res.assert_success() stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload, env=env) assert rc == 0 correct_interpreter_path = pex_python.encode() assert correct_interpreter_path in stdout
def test_pex_interpreter_interact_custom_setuptools_useable(): with pex_with_no_entrypoints() as (pex, test_script, _): stdout, rc = run_simple_pex(pex, env=make_env(PEX_VERBOSE=1), stdin=test_script) assert rc == 0, stdout
def test_pex_script_function_custom_setuptools_useable(): with pex_with_entrypoints('my_app_function') as pex: stdout, rc = run_simple_pex(pex, env=make_env(PEX_VERBOSE=1)) assert rc == 0, stdout
def test_pex_script_module_custom_setuptools_useable(): with pex_with_entrypoints('my_app_module') as pex: stdout, rc = run_simple_pex(pex, env={'PEX_VERBOSE': '1'}) assert rc == 0, stdout
def test_interpreter_selection_using_os_environ_for_bootstrap_reexec(): """ This is a test for verifying the proper function of the pex bootstrapper's interpreter selection logic and validate a corresponding bugfix. More details on the nature of the bug can be found at: https://github.com/pantsbuild/pex/pull/441 """ with temporary_dir() as td: pexrc_path = os.path.join(td, '.pexrc') # Select pexrc interpreter versions based on test environemnt. # The parent interpreter is the interpreter we expect the parent pex to # execute with. The child interpreter is the interpreter we expect the # child pex to execute with. if (sys.version_info[0], sys.version_info[1]) == (3, 6): child_pex_interpreter_version = '3.6.3' else: child_pex_interpreter_version = '2.7.10' # Write parent pex's pexrc. with open(pexrc_path, 'w') as pexrc: pexrc.write("PEX_PYTHON=%s" % sys.executable) test_setup_path = os.path.join(td, 'setup.py') with open(test_setup_path, 'w') as fh: fh.write(dedent(''' from setuptools import setup setup( name='tester', version='1.0', description='tests', author='tester', author_email='*****@*****.**', packages=['testing'] ) ''')) os.mkdir(os.path.join(td, 'testing')) test_init_path = os.path.join(td, 'testing/__init__.py') with open(test_init_path, 'w') as fh: fh.write(dedent(''' def tester(): from pex.testing import ( run_pex_command, run_simple_pex ) import os import tempfile import shutil from textwrap import dedent td = tempfile.mkdtemp() try: pexrc_path = os.path.join(td, '.pexrc') with open(pexrc_path, 'w') as pexrc: pexrc.write("PEX_PYTHON={}") test_file_path = os.path.join(td, 'build_and_run_child_pex.py') with open(test_file_path, 'w') as fh: fh.write(dedent(""" import sys print(sys.executable) """)) pex_out_path = os.path.join(td, 'child.pex') res = run_pex_command(['--disable-cache', '-o', pex_out_path]) stdin_payload = b'import sys; print(sys.executable); sys.exit(0)' stdout, rc = run_simple_pex(pex_out_path, stdin=stdin_payload) print(stdout) finally: shutil.rmtree(td) '''.format(ensure_python_interpreter(child_pex_interpreter_version)))) pex_out_path = os.path.join(td, 'parent.pex') res = run_pex_command(['--disable-cache', 'pex', '{}'.format(td), '-e', 'testing:tester', '-o', pex_out_path]) res.assert_success() stdout, rc = run_simple_pex(pex_out_path) assert rc == 0 # Ensure that child pex used the proper interpreter as specified by its pexrc. correct_interpreter_path = ensure_python_interpreter(child_pex_interpreter_version) correct_interpreter_path = correct_interpreter_path.encode() # Py 2/3 compatibility assert correct_interpreter_path in stdout