Repository: pex-tool/pex

Issue:
pex 1.2.14 breaks entrypoint targeting when PEX_PYTHON is present
with 1.2.13, targeting an entrypoint with `-e` et al results in an attempt to load that entrypoint at runtime:

```
[omerta ~]$ pip install pex==1.2.13 2>&1 >/dev/null
[omerta ~]$ pex --version
pex 1.2.13
[omerta ~]$ pex -e 'pants.bin.pants_loader:main' pantsbuild.pants -o /tmp/pants.pex
[omerta ~]$ /tmp/pants.pex
Traceback (most recent call last):
  File ".bootstrap/_pex/pex.py", line 365, in execute
  File ".bootstrap/_pex/pex.py", line 293, in _wrap_coverage
  File ".bootstrap/_pex/pex.py", line 325, in _wrap_profiling
  File ".bootstrap/_pex/pex.py", line 408, in _execute
  File ".bootstrap/_pex/pex.py", line 466, in execute_entry
  File ".bootstrap/_pex/pex.py", line 480, in execute_pkg_resources
  File ".bootstrap/pkg_resources/__init__.py", line 2297, in resolve
ImportError: No module named pants_loader
```

with 1.2.14, it seems to be re-execing against the `PEX_PYTHON` interpreter sans args which results in a bare repl when the pex is run:

```
[omerta ~]$ pip install pex==1.2.14 2>&1 >/dev/null
[omerta ~]$ pex --version
pex 1.2.14
[omerta ~]$ pex -e 'pants.bin.pants_loader:main' pantsbuild.pants -o /tmp/pants.pex
[omerta ~]$ PEX_VERBOSE=9 /tmp/pants.pex
pex: Please build pex with the subprocess32 module for more reliable requirement installation and interpreter execution.
pex: Selecting runtime interpreter based on pexrc: 0.1ms
pex: Re-executing: cmdline="['/opt/ee/python/2.7/bin/python2.7']", sys.executable="/Users/kwilson/Python/CPython-2.7.13/bin/python2.7", PEX_PYTHON="None", PEX_PYTHON_PATH="None", COMPATIBILITY_CONSTRAINTS="[]"
Python 2.7.10 (default, Dec 16 2015, 14:09:45) 
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 
```

cc @CMLivingston since this appears related to #427 


Discussion:

Resolving patch:
diff --git a/pex/pex_bootstrapper.py b/pex/pex_bootstrapper.py
--- a/pex/pex_bootstrapper.py
+++ b/pex/pex_bootstrapper.py
@@ -1,6 +1,7 @@
 # Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
 # Licensed under the Apache License, Version 2.0 (see LICENSE).
 from __future__ import print_function
+
 import os
 import sys
 
@@ -147,14 +148,14 @@ def maybe_reexec_pex(compatibility_constraints):
       selected_interpreter = _select_interpreter(ENV.PEX_PYTHON_PATH, compatibility_constraints)
 
   if selected_interpreter:
-    ENV.delete('PEX_PYTHON')
-    ENV.delete('PEX_PYTHON_PATH')
-    ENV.SHOULD_EXIT_BOOTSTRAP_REEXEC = True
-    cmdline = [selected_interpreter] + sys.argv[1:]
+    cmdline = [selected_interpreter] + sys.argv
     TRACER.log('Re-executing: cmdline="%s", sys.executable="%s", PEX_PYTHON="%s", '
                'PEX_PYTHON_PATH="%s", COMPATIBILITY_CONSTRAINTS="%s"'
                % (cmdline, sys.executable, ENV.PEX_PYTHON, ENV.PEX_PYTHON_PATH,
                   compatibility_constraints))
+    ENV.delete('PEX_PYTHON')
+    ENV.delete('PEX_PYTHON_PATH')
+    ENV.SHOULD_EXIT_BOOTSTRAP_REEXEC = True
     os.execve(selected_interpreter, cmdline, ENV.copy())
 
 


Test patch:
diff --git a/tests/test_integration.py b/tests/test_integration.py
--- a/tests/test_integration.py
+++ b/tests/test_integration.py
@@ -547,3 +547,23 @@ def test_pex_python():
     assert rc == 0
     correct_interpreter_path = pex_python.encode()
     assert correct_interpreter_path in stdout
+
+
+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