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_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_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_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_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 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_interpreter_resolution_with_constraint_option(): with temporary_dir() as output_dir: pex_out_path = os.path.join(output_dir, 'pex1.pex') res = run_pex_command(['--disable-cache', '--interpreter-constraint=>=2.7', '--interpreter-constraint=<3', '-o', pex_out_path]) res.assert_success() pex_info = get_pex_info(pex_out_path) assert set(['>=2.7', '<3']) == set(pex_info.interpreter_constraints) assert pex_info.build_properties['version'][0] < 3
def test_interpreter_constraints_to_pex_info(): with temporary_dir() as output_dir: # target python 2 pex_out_path = os.path.join(output_dir, 'pex1.pex') res = run_pex_command(['--disable-cache', '--interpreter-constraint=>=2.7', '--interpreter-constraint=<3', '-o', pex_out_path]) res.assert_success() pex_info = get_pex_info(pex_out_path) assert set(['>=2.7', '<3']) == set(pex_info.interpreter_constraints) # target python 3 pex_out_path = os.path.join(output_dir, 'pex1.pex') res = run_pex_command(['--disable-cache', '--interpreter-constraint=>3', '-o', pex_out_path]) res.assert_success() pex_info = get_pex_info(pex_out_path) assert ['>3'] == pex_info.interpreter_constraints
def test_setup_interpreter_constraint(): interpreter = ensure_python_interpreter(PY27) with temporary_dir() as out: pex = os.path.join(out, 'pex.pex') results = run_pex_command(['jsonschema==2.6.0', '--disable-cache', '--interpreter-constraint=CPython=={}'.format(PY27), '-o', pex], env=make_env(PATH=os.path.dirname(interpreter))) results.assert_success() subprocess.check_call([pex, '-c', 'import jsonschema'])
def test_interpreter_constraints_to_pex_info_py2(): with temporary_dir() as output_dir: # target python 2 pex_out_path = os.path.join(output_dir, 'pex_py2.pex') res = run_pex_command(['--disable-cache', '--interpreter-constraint=>=2.7', '--interpreter-constraint=<3', '-o', pex_out_path]) res.assert_success() pex_info = get_pex_info(pex_out_path) assert set(['>=2.7', '<3']) == set(pex_info.interpreter_constraints)
def test_build_pex(): # type: () -> None with temporary_dir() as sandbox: pex_path = os.path.join(sandbox, "pex") results = run_pex_command(["ansicolors==1.1.8", "--output-file", pex_path]) results.assert_success() stdout, returncode = run_simple_pex( pex=pex_path, args=["-c", 'import colors; print(" ".join(colors.COLORS))'] ) assert 0 == returncode assert b"black red green yellow blue magenta cyan white" == stdout.strip()
def test_issues_661_devendoring_required(): # The cryptography distribution does not have a whl released for python3 on linux at version 2.5. # As a result, we're forced to build it under python3 and, prior to the fix for # https://github.com/pantsbuild/pex/issues/661, this would fail using the vendored setuptools # inside pex. with temporary_dir() as td: cryptography_pex = os.path.join(td, 'cryptography.pex') res = run_pex_command(['cryptography==2.5', '-o', cryptography_pex]) res.assert_success() subprocess.check_call([cryptography_pex, '-c', 'import cryptography'])
def test_platform_specific_egg_resolution_matching(): with temporary_dir() as td: pex_out_path = os.path.join(td, 'pex.pex') res = run_pex_command([ '--disable-cache', '--no-wheel', '--no-build', 'netifaces==0.10.6', # Only provides win32 eggs. '-o', pex_out_path ]) res.assert_failure()
def test_platform_specific_egg_resolution(): with temporary_dir() as td: pex_out_path = os.path.join(td, 'pex.pex') res = run_pex_command(['--disable-cache', '--no-wheel', '--no-build', '--no-pypi', '--platform=linux-x86_64', '--find-links=tests/example_packages/', 'M2Crypto==0.22.3', '-o', pex_out_path]) res.assert_success()
def test_build_pex(): with temporary_dir() as sandbox: pex_path = os.path.join(sandbox, 'pex') results = run_pex_command( ['ansicolors==1.1.8', '--output-file', pex_path]) results.assert_success() stdout, returncode = run_simple_pex( pex=pex_path, args=['-c', 'import colors; print(" ".join(colors.COLORS))']) assert 0 == returncode assert b'black red green yellow blue magenta cyan white' == stdout.strip( )
def assert_run_pex(python=None, pex_args=None): # type: (Optional[str], Optional[List[str]]) -> List[Text] pex_args = list(pex_args) if pex_args else [] results = run_pex_command( python=python, args=pex_args + ["ansicolors==1.1.8", "--", "-c", 'import colors; print(" ".join(colors.COLORS))'], quiet=True, ) results.assert_success() assert "black red green yellow blue magenta cyan white" == results.output.strip() return results.error.splitlines()
def test_interpreter_constraints_to_pex_info_py3(): py3_interpreter = ensure_python_interpreter('3.6.3') with environment_as(PATH=os.path.dirname(py3_interpreter)): with temporary_dir() as output_dir: # target python 3 pex_out_path = os.path.join(output_dir, 'pex_py3.pex') res = run_pex_command(['--disable-cache', '--interpreter-constraint=>3', '-o', pex_out_path]) res.assert_success() pex_info = get_pex_info(pex_out_path) assert ['>3'] == pex_info.interpreter_constraints
def assert_run_pex(python=None, pex_args=None): pex_args = list(pex_args) if pex_args else [] results = run_pex_command( python=python, args=pex_args + [ 'ansicolors==1.1.8', '--', '-c', 'import colors; print(" ".join(colors.COLORS))' ], quiet=True) results.assert_success() assert 'black red green yellow blue magenta cyan white' == results.output.strip( ) return results.error.splitlines()
def test_venv_entrypoint_function_exit_code_issue_1241(tmpdir): # type: (Any) -> None pex_file = os.path.join(str(tmpdir), "ep-function.pex") src = os.path.join(str(tmpdir), "src") with safe_open(os.path.join(src, "module.py"), "w") as fp: fp.write( dedent("""\ import sys def target(): args = sys.argv[1:] if args: exit = args[0] try: return int(exit) except ValueError: return exit """)) result = run_pex_command(args=[ "-D", src, "-e", "module:target", "--include-tools", "-o", pex_file ]) result.assert_success() venv = os.path.join(str(tmpdir), "ep-function.venv") subprocess.check_call(args=[pex_file, "venv", venv], env=make_env(PEX_TOOLS=1)) venv_pex = os.path.join(venv, "pex") assert 0 == subprocess.Popen(args=[venv_pex]).wait() def assert_venv_process( args, # type: List[str] expected_returncode, # type: int expected_stdout="", # type: str expected_stderr="", # type: str ): # type: (...) -> None process = subprocess.Popen(args=[venv_pex] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() assert expected_returncode == process.returncode assert expected_stdout == stdout.decode("utf-8") assert expected_stderr == stderr.decode("utf-8") assert_venv_process(args=["bob"], expected_returncode=1, expected_stderr="bob\n") assert_venv_process(args=["42"], expected_returncode=42)
def pex(): # type: () -> Iterator[str] with temporary_dir() as tmpdir: pex_path = os.path.join(tmpdir, "fabric.pex") src_dir = os.path.join(tmpdir, "src") touch(os.path.join(src_dir, "user/__init__.py")) touch(os.path.join(src_dir, "user/package/__init__.py")) # N.B.: --unzip just speeds up runs 2+ of the pex file and is otherwise not relevant to # these tests. run_pex_command(args=[ "fabric=={}".format(FABRIC_VERSION), "-c", "fab", "--sources-directory", src_dir, "-o", pex_path, "--unzip", "--include-tools", ]) yield os.path.realpath(pex_path)
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 test_extract(pex, pex_tools_env, tmpdir): # type: (str, Dict[str, str], Any) -> None dists_dir = os.path.join(str(tmpdir), "dists") pid_file = os.path.join(str(tmpdir), "pid") os.mkfifo(pid_file) find_links_server = subprocess.Popen( args=[ pex, "repository", "extract", "--serve", "--sources", "--dest-dir", dists_dir, "--pid-file", pid_file, ], env=pex_tools_env, stdout=subprocess.PIPE, ) with open(pid_file) as fp: _, port = fp.read().strip().split(":", 1) example_sdist_pex = os.path.join(str(tmpdir), "example-sdist.pex") find_links_url = "http://localhost:{}".format(port) result = run_pex_command( args=[ "--no-pypi", "--find-links", find_links_url, "example", "-c", "example", "-o", example_sdist_pex, ] ) result.assert_success() _, pip = ensure_python_venv(PY36) subprocess.check_call( args=[pip, "install", "--no-index", "--find-links", find_links_url, "example"] ) example_console_script = os.path.join(os.path.dirname(pip), "example") find_links_server.send_signal(signal.SIGQUIT) assert -1 * int(signal.SIGQUIT) == find_links_server.wait() expected_output = b"Fetching from https://example.com ...\n" assert expected_output == subprocess.check_output(args=[example_sdist_pex]) assert expected_output == subprocess.check_output(args=[example_console_script])
def test_cache_disable(): with nested(temporary_dir(), temporary_dir(), temporary_dir()) as (td, output_dir, tmp_home): output_path = os.path.join(output_dir, 'pex.pex') args = [ 'pex', '-o', output_path, '--not-zip-safe', '--disable-cache', '--pex-root={0}'.format(td), ] results = run_pex_command(args=args, env=make_env(HOME=tmp_home, PEX_INTERPRETER='1')) results.assert_success() assert ['pex.pex'] == os.listdir(output_dir), 'Expected built pex file.' assert [] == os.listdir(tmp_home), 'Expected empty temp home dir.'
def test_multiplatform_entrypoint(): with temporary_dir() as td: pex_out_path = os.path.join(td, 'p537.pex') interpreter = ensure_python_interpreter(PY36) res = run_pex_command([ 'p537==1.0.3', '--no-build', '--python={}'.format(interpreter), '--python-shebang=#!{}'.format(interpreter), '--platform=linux-x86_64', '--platform=macosx-10.13-x86_64', '-c', 'p537', '-o', pex_out_path, '--validate-entry-point' ]) res.assert_success() greeting = subprocess.check_output([pex_out_path]) assert b'Hello World!' == greeting.strip()
def test_pex_root(): with temporary_dir() as tmp_home: with environment_as(HOME=tmp_home): with temporary_dir() as td: with temporary_dir() as output_dir: env = os.environ.copy() env['PEX_INTERPRETER'] = '1' output_path = os.path.join(output_dir, 'pex.pex') args = ['pex', '-o', output_path, '--not-zip-safe', '--pex-root={0}'.format(td)] results = run_pex_command(args=args, env=env) results.assert_success() assert ['pex.pex'] == os.listdir(output_dir), 'Expected built pex file.' assert [] == os.listdir(tmp_home), 'Expected empty temp home dir.' assert 'build' in os.listdir(td), 'Expected build directory in tmp pex root.'
def test_setup_python_direct_markers(): py36_interpreter = ensure_python_interpreter(PY36) with temporary_dir() as out: pex = os.path.join(out, 'pex.pex') results = run_pex_command(['subprocess32==3.2.7; python_version<"3"', '--disable-cache', '--python-shebang=#!/usr/bin/env python', '--python={}'.format(py36_interpreter), '-o', pex]) results.assert_success() py2_only_program = [pex, '-c', 'import subprocess32'] with pytest.raises(subprocess.CalledProcessError): subprocess.check_call(py2_only_program, env=make_env(PATH=os.path.dirname(py36_interpreter)))
def test_pex_exit_code_propagation(): """Tests exit code propagation.""" test_stub = dedent(""" def test_fail(): assert False """) with temporary_content({'tester.py': test_stub}) as output_dir: pex_path = os.path.join(output_dir, 'test.pex') tester_path = os.path.join(output_dir, 'tester.py') results = run_pex_command( ['pytest==3.9.1', '-e', 'pytest:main', '-o', pex_path]) results.assert_success() assert subprocess.call([pex_path, os.path.realpath(tester_path)]) == 1
def test_pex_multi_resolve(): """Tests multi-interpreter + multi-platform resolution.""" with temporary_dir() as output_dir: pex_path = os.path.join(output_dir, 'pex.pex') results = run_pex_command([ '--disable-cache', 'lxml==3.8.0', '--no-build', '--platform=linux-x86_64', '--platform=macosx-10.6-x86_64', '--python=python2.7', '--python=python3.6', '-o', pex_path ]) results.assert_success() included_dists = get_dep_dist_names_from_pex(pex_path, 'lxml') assert len(included_dists) == 4 for dist_substr in ('-cp27-', '-cp36-', '-manylinux1_x86_64', '-macosx_'): assert any(dist_substr in f for f in included_dists)
def test_pex_multi_resolve(): """Tests multi-interpreter + multi-platform resolution.""" with temporary_dir() as output_dir: pex_path = os.path.join(output_dir, 'pex.pex') results = run_pex_command(['--disable-cache', 'lxml==3.8.0', '--platform=manylinux1-x86_64', '--platform=macosx-10.6-x86_64', '--python=python2.7', '--python=python3.6', '-o', pex_path]) results.assert_success() included_dists = get_dep_dist_names_from_pex(pex_path, 'lxml') assert len(included_dists) == 4 for dist_substr in ('-cp27-', '-cp36-', '-manylinux1_x86_64', '-macosx_'): assert any(dist_substr in f for f in included_dists)
def test_venv_multiprocessing_issues_1236( tmpdir, # type: Any start_method, # type: Optional[str] ): # type: (...) -> None src = os.path.join(str(tmpdir), "src") with safe_open(os.path.join(src, "foo.py"), "w") as fp: fp.write( dedent( """\ def bar(): print('hello') """ ) ) with safe_open(os.path.join(src, "main.py"), "w") as fp: fp.write( dedent( """\ import multiprocessing from foo import bar if __name__ == '__main__': if {start_method!r}: multiprocessing.set_start_method({start_method!r}) p = multiprocessing.Process(target=bar) p.start() """.format( start_method=start_method ) ) ) pex_file = os.path.join(str(tmpdir), "mp.pex") result = run_pex_command(args=["-D", src, "-m", "main", "-o", pex_file, "--include-tools"]) result.assert_success() # Confirm multiprocessing works via normal PEX file execution. output = subprocess.check_output(args=[pex_file]) assert "hello" == output.decode("utf-8").strip() # Confirm multiprocessing works via the `pex` venv script. venv = os.path.join(str(tmpdir), "venv") subprocess.check_call(args=[pex_file, "venv", venv], env=make_env(PEX_TOOLS=True)) output = subprocess.check_output(args=[os.path.join(venv, "pex")]) assert "hello" == output.decode("utf-8").strip()
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(PY36) 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_manylinux_runtime(): """Tests resolver manylinux support and runtime resolution (and --platform=current).""" test_stub = dedent(""" import msgpack print(msgpack.unpackb(msgpack.packb([1, 2, 3]))) """) with temporary_content({'tester.py': test_stub}) as output_dir: pex_path = os.path.join(output_dir, 'test.pex') tester_path = os.path.join(output_dir, 'tester.py') results = run_pex_command([ '--disable-cache', '--no-build', 'msgpack-python==0.4.7', '--platform=current'.format(platform), '-o', pex_path ]) results.assert_success() out = subprocess.check_output([pex_path, tester_path]) assert out.strip() == '[1, 2, 3]'
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_relocatable_venv(tmpdir): # type: (Any) -> None pex_file = os.path.join(str(tmpdir), "relocatable.pex") src = os.path.join(str(tmpdir), "src") with safe_open(os.path.join(src, "main.py"), "w") as fp: fp.write( dedent( """\ import sys from colors import blue print(blue(sys.executable)) """ ) ) result = run_pex_command( args=["-D", src, "ansicolors==1.1.8", "-m", "main", "--include-tools", "-o", pex_file] ) result.assert_success() venv = os.path.join(str(tmpdir), "relocatable.venv") subprocess.check_call(args=[pex_file, "venv", venv], env=make_env(PEX_TOOLS=1)) subprocess.check_call(args=[os.path.join(venv, "pex")]) relocated_relpath = "relocated.venv" relocated_venv = os.path.join(str(tmpdir), relocated_relpath) # Since the venv pex script contains a shebang with an absolute path to the venv python # interpreter, a move of the venv makes the script un-runnable directly. shutil.move(venv, relocated_venv) with pytest.raises(OSError) as exec_info: subprocess.check_call(args=[os.path.join(relocated_venv, "pex")]) assert errno.ENOENT == exec_info.value.errno # But we should be able to run the script using the moved venv's interpreter. subprocess.check_call( args=[ os.path.join(relocated_relpath, "bin", "python"), os.path.join(relocated_relpath, "pex"), ], cwd=str(tmpdir), )
def pex(): # type: () -> Iterator[str] with temporary_dir() as tmpdir: pex_path = os.path.join(tmpdir, "example.pex") src = os.path.join(tmpdir, "src") with safe_open(os.path.join(src, "data", "url.txt"), "w") as fp: fp.write("https://example.com") with safe_open(os.path.join(src, "main.py"), "w") as fp: fp.write( dedent( """\ from __future__ import print_function import os import sys import requests def do(): with open(os.path.join(os.path.dirname(__file__), "data", "url.txt")) as fp: url = fp.read().strip() print("Fetching from {} ...".format(url)) print(requests.get(url).text, file=sys.stderr) """ ) ) result = run_pex_command( args=[ "-D", src, "requests==2.25.1", "-e", "main:do", "--interpreter-constraint", "CPython>=2.7,<4", "-o", pex_path, "--include-tools", ], ) result.assert_success() yield os.path.realpath(pex_path)
def test_pex_multi_resolve_2(): """Tests multi-interpreter + multi-platform resolution using extended platform notation.""" with temporary_dir() as output_dir: pex_path = os.path.join(output_dir, 'pex.pex') results = run_pex_command([ '--disable-cache', 'lxml==3.8.0', '--no-build', '--platform=linux-x86_64-cp-36-m', '--platform=linux-x86_64-cp-27-m', '--platform=macosx-10.6-x86_64-cp-36-m', '--platform=macosx-10.6-x86_64-cp-27-m', '-o', pex_path ]) results.assert_success() included_dists = get_dep_dist_names_from_pex(pex_path, 'lxml') assert len(included_dists) == 4 for dist_substr in ('-cp27-', '-cp36-', '-manylinux1_x86_64', '-macosx_'): assert any(dist_substr in f for f in included_dists), ( '{} was not found in wheel'.format(dist_substr))
def pex_with_entrypoints(entry_point): setup_py = dedent(""" from setuptools import setup setup( name='my_app', version='0.0.0', zip_safe=True, packages=[''], install_requires=['setuptools==36.2.7'], entry_points={'console_scripts': ['my_app_function = my_app:do_something', 'my_app_module = my_app']}, ) """) my_app = dedent(""" import sys def do_something(): try: from setuptools.sandbox import run_setup return 0 except: return 1 if __name__ == '__main__': sys.exit(do_something()) """) with temporary_content({ 'setup.py': setup_py, 'my_app.py': my_app }) as project_dir: with temporary_dir() as out: pex = os.path.join(out, 'pex.pex') pex_command = [ '--validate-entry-point', '-c', entry_point, project_dir, '-o', pex ] results = run_pex_command(pex_command) results.assert_success() yield pex
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 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_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