We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
If sys.executable is not on PATH a pex will re-exec itself forever.
This can happen via:
```
/not/on/PATH/python a.pex
```

If `a.pex` in this example has compatibility constraints that rule out all other interpreters on `PATH` (or there are no intepreters on `PATH`!, c.f.: #53), then, even if sys.executable would be compatible to execute `a.pex` with, it is not considered useable:
https://github.com/pantsbuild/pex/blob/442ce7952674cb8a367ecded7d138661194d4f12/pex/pex_bootstrapper.py#L45-L50
https://github.com/pantsbuild/pex/blob/442ce7952674cb8a367ecded7d138661194d4f12/pex/interpreter.py#L283-L287

And so the pex_bootstrapper re-execs the pex ad infinitum:
https://github.com/pantsbuild/pex/blob/442ce7952674cb8a367ecded7d138661194d4f12/pex/pex_bootstrapper.py#L122-L137

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pex/pex_bootstrapper.py`
Content:
```
1 # Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
2 # Licensed under the Apache License, Version 2.0 (see LICENSE).
3 
4 from __future__ import absolute_import, print_function
5 
6 import os
7 import sys
8 
9 from pex import pex_warnings
10 from pex.common import die
11 from pex.executor import Executor
12 from pex.interpreter import PythonInterpreter
13 from pex.interpreter_constraints import matched_interpreters
14 from pex.tracer import TRACER
15 from pex.variables import ENV
16 
17 __all__ = ('bootstrap_pex',)
18 
19 
20 def find_in_path(target_interpreter):
21   if os.path.exists(target_interpreter):
22     return target_interpreter
23 
24   for directory in os.getenv('PATH', '').split(os.pathsep):
25     try_path = os.path.join(directory, target_interpreter)
26     if os.path.exists(try_path):
27       return try_path
28 
29 
30 def find_compatible_interpreters(pex_python_path, compatibility_constraints):
31   """Find all compatible interpreters on the system within the supplied constraints and use
32      PEX_PYTHON_PATH if it is set. If not, fall back to interpreters on $PATH.
33   """
34   if pex_python_path:
35     interpreters = []
36     for binary in pex_python_path.split(os.pathsep):
37       try:
38         interpreters.append(PythonInterpreter.from_binary(binary))
39       except Executor.ExecutionError:
40         print("Python interpreter %s in PEX_PYTHON_PATH failed to load properly." % binary,
41           file=sys.stderr)
42     if not interpreters:
43       die('PEX_PYTHON_PATH was defined, but no valid interpreters could be identified. Exiting.')
44   else:
45     if not os.getenv('PATH', ''):
46       # no $PATH, use sys.executable
47       interpreters = [PythonInterpreter.get()]
48     else:
49       # get all qualifying interpreters found in $PATH
50       interpreters = PythonInterpreter.all()
51 
52   return list(
53     matched_interpreters(interpreters, compatibility_constraints)
54     if compatibility_constraints
55     else interpreters
56   )
57 
58 
59 def _select_pex_python_interpreter(target_python, compatibility_constraints):
60   target = find_in_path(target_python)
61 
62   if not target:
63     die('Failed to find interpreter specified by PEX_PYTHON: %s' % target)
64   if compatibility_constraints:
65     pi = PythonInterpreter.from_binary(target)
66     if not list(matched_interpreters([pi], compatibility_constraints)):
67       die('Interpreter specified by PEX_PYTHON (%s) is not compatible with specified '
68           'interpreter constraints: %s' % (target, str(compatibility_constraints)))
69   if not os.path.exists(target):
70     die('Target interpreter specified by PEX_PYTHON %s does not exist. Exiting.' % target)
71   return target
72 
73 
74 def _select_interpreter(pex_python_path, compatibility_constraints):
75   compatible_interpreters = find_compatible_interpreters(
76     pex_python_path, compatibility_constraints)
77 
78   if not compatible_interpreters:
79     die('Failed to find compatible interpreter for constraints: %s'
80         % str(compatibility_constraints))
81   # TODO: https://github.com/pantsbuild/pex/issues/430
82   target = min(compatible_interpreters).binary
83 
84   if os.path.exists(target):
85     return target
86 
87 
88 def maybe_reexec_pex(compatibility_constraints):
89   """
90   Handle environment overrides for the Python interpreter to use when executing this pex.
91 
92   This function supports interpreter filtering based on interpreter constraints stored in PEX-INFO
93   metadata. If PEX_PYTHON is set in a pexrc, it attempts to obtain the binary location of the
94   interpreter specified by PEX_PYTHON. If PEX_PYTHON_PATH is set, it attempts to search the path for
95   a matching interpreter in accordance with the interpreter constraints. If both variables are
96   present in a pexrc, this function gives precedence to PEX_PYTHON_PATH and errors out if no
97   compatible interpreters can be found on said path.
98 
99   If neither variable is set, we fall back to plain PEX execution using PATH searching or the
100   currently executing interpreter. If compatibility constraints are used, we match those constraints
101   against these interpreters.
102 
103   :param compatibility_constraints: list of requirements-style strings that constrain the
104   Python interpreter to re-exec this pex with.
105   """
106   if os.environ.pop('SHOULD_EXIT_BOOTSTRAP_REEXEC', None):
107     # We've already been here and selected an interpreter. Continue to execution.
108     return
109 
110   target = None
111   with TRACER.timed('Selecting runtime interpreter based on pexrc', V=3):
112     if ENV.PEX_PYTHON and not ENV.PEX_PYTHON_PATH:
113       # preserve PEX_PYTHON re-exec for backwards compatibility
114       # TODO: Kill this off completely in favor of PEX_PYTHON_PATH
115       # https://github.com/pantsbuild/pex/issues/431
116       target = _select_pex_python_interpreter(ENV.PEX_PYTHON,
117                                               compatibility_constraints)
118     elif ENV.PEX_PYTHON_PATH:
119       target = _select_interpreter(ENV.PEX_PYTHON_PATH, compatibility_constraints)
120 
121     elif compatibility_constraints:
122       # Apply constraints to target using regular PATH
123       target = _select_interpreter(
124         pex_python_path=None,
125         compatibility_constraints=compatibility_constraints
126       )
127 
128   if target and os.path.realpath(target) != os.path.realpath(sys.executable):
129     cmdline = [target] + sys.argv
130     TRACER.log('Re-executing: cmdline="%s", sys.executable="%s", PEX_PYTHON="%s", '
131                'PEX_PYTHON_PATH="%s", COMPATIBILITY_CONSTRAINTS="%s"'
132                % (cmdline, sys.executable, ENV.PEX_PYTHON, ENV.PEX_PYTHON_PATH,
133                   compatibility_constraints))
134     ENV.delete('PEX_PYTHON')
135     ENV.delete('PEX_PYTHON_PATH')
136     os.environ['SHOULD_EXIT_BOOTSTRAP_REEXEC'] = '1'
137     os.execve(target, cmdline, ENV.copy())
138 
139 
140 def _bootstrap(entry_point):
141   from .pex_info import PexInfo
142   pex_info = PexInfo.from_pex(entry_point)
143   pex_warnings.configure_warnings(pex_info)
144 
145   from .finders import register_finders
146   register_finders()
147 
148   return pex_info
149 
150 
151 def bootstrap_pex(entry_point):
152   pex_info = _bootstrap(entry_point)
153   maybe_reexec_pex(pex_info.interpreter_constraints)
154 
155   from . import pex
156   pex.PEX(entry_point).execute()
157 
158 
159 # NB: This helper is used by third party libs - namely https://github.com/wickman/lambdex.
160 # TODO(John Sirois): Kill once https://github.com/wickman/lambdex/issues/5 is resolved.
161 def is_compressed(entry_point):
162   from .pex_info import PexInfo
163   return os.path.exists(entry_point) and not os.path.exists(os.path.join(entry_point, PexInfo.PATH))
164 
165 
166 def bootstrap_pex_env(entry_point):
167   """Bootstrap the current runtime environment using a given pex."""
168   pex_info = _bootstrap(entry_point)
169 
170   from .environment import PEXEnvironment
171   PEXEnvironment(entry_point, pex_info).activate()
172
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pex/pex_bootstrapper.py b/pex/pex_bootstrapper.py
--- a/pex/pex_bootstrapper.py
+++ b/pex/pex_bootstrapper.py
@@ -11,6 +11,7 @@
 from pex.executor import Executor
 from pex.interpreter import PythonInterpreter
 from pex.interpreter_constraints import matched_interpreters
+from pex.orderedset import OrderedSet
 from pex.tracer import TRACER
 from pex.variables import ENV
 
@@ -27,7 +28,7 @@
       return try_path
 
 
-def find_compatible_interpreters(pex_python_path, compatibility_constraints):
+def find_compatible_interpreters(pex_python_path=None, compatibility_constraints=None):
   """Find all compatible interpreters on the system within the supplied constraints and use
      PEX_PYTHON_PATH if it is set. If not, fall back to interpreters on $PATH.
   """
@@ -42,12 +43,12 @@
     if not interpreters:
       die('PEX_PYTHON_PATH was defined, but no valid interpreters could be identified. Exiting.')
   else:
-    if not os.getenv('PATH', ''):
-      # no $PATH, use sys.executable
-      interpreters = [PythonInterpreter.get()]
-    else:
-      # get all qualifying interpreters found in $PATH
-      interpreters = PythonInterpreter.all()
+    # We may have been invoked with a specific interpreter not on the $PATH, make sure our
+    # sys.executable is included as a candidate in this case.
+    interpreters = OrderedSet([PythonInterpreter.get()])
+
+    # Add all qualifying interpreters found in $PATH.
+    interpreters.update(PythonInterpreter.all())
 
   return list(
     matched_interpreters(interpreters, compatibility_constraints)
@@ -56,7 +57,7 @@
   )
 
 
-def _select_pex_python_interpreter(target_python, compatibility_constraints):
+def _select_pex_python_interpreter(target_python, compatibility_constraints=None):
   target = find_in_path(target_python)
 
   if not target:
@@ -71,9 +72,9 @@
   return target
 
 
-def _select_interpreter(pex_python_path, compatibility_constraints):
+def _select_interpreter(pex_python_path=None, compatibility_constraints=None):
   compatible_interpreters = find_compatible_interpreters(
-    pex_python_path, compatibility_constraints)
+    pex_python_path=pex_python_path, compatibility_constraints=compatibility_constraints)
 
   if not compatible_interpreters:
     die('Failed to find compatible interpreter for constraints: %s'
@@ -114,16 +115,14 @@
       # TODO: Kill this off completely in favor of PEX_PYTHON_PATH
       # https://github.com/pantsbuild/pex/issues/431
       target = _select_pex_python_interpreter(ENV.PEX_PYTHON,
-                                              compatibility_constraints)
+                                              compatibility_constraints=compatibility_constraints)
     elif ENV.PEX_PYTHON_PATH:
-      target = _select_interpreter(ENV.PEX_PYTHON_PATH, compatibility_constraints)
+      target = _select_interpreter(pex_python_path=ENV.PEX_PYTHON_PATH,
+                                   compatibility_constraints=compatibility_constraints)
 
     elif compatibility_constraints:
       # Apply constraints to target using regular PATH
-      target = _select_interpreter(
-        pex_python_path=None,
-        compatibility_constraints=compatibility_constraints
-      )
+      target = _select_interpreter(compatibility_constraints=compatibility_constraints)
 
   if target and os.path.realpath(target) != os.path.realpath(sys.executable):
     cmdline = [target] + sys.argv

{"golden_diff": "diff --git a/pex/pex_bootstrapper.py b/pex/pex_bootstrapper.py\n--- a/pex/pex_bootstrapper.py\n+++ b/pex/pex_bootstrapper.py\n@@ -11,6 +11,7 @@\n from pex.executor import Executor\n from pex.interpreter import PythonInterpreter\n from pex.interpreter_constraints import matched_interpreters\n+from pex.orderedset import OrderedSet\n from pex.tracer import TRACER\n from pex.variables import ENV\n \n@@ -27,7 +28,7 @@\n       return try_path\n \n \n-def find_compatible_interpreters(pex_python_path, compatibility_constraints):\n+def find_compatible_interpreters(pex_python_path=None, compatibility_constraints=None):\n   \"\"\"Find all compatible interpreters on the system within the supplied constraints and use\n      PEX_PYTHON_PATH if it is set. If not, fall back to interpreters on $PATH.\n   \"\"\"\n@@ -42,12 +43,12 @@\n     if not interpreters:\n       die('PEX_PYTHON_PATH was defined, but no valid interpreters could be identified. Exiting.')\n   else:\n-    if not os.getenv('PATH', ''):\n-      # no $PATH, use sys.executable\n-      interpreters = [PythonInterpreter.get()]\n-    else:\n-      # get all qualifying interpreters found in $PATH\n-      interpreters = PythonInterpreter.all()\n+    # We may have been invoked with a specific interpreter not on the $PATH, make sure our\n+    # sys.executable is included as a candidate in this case.\n+    interpreters = OrderedSet([PythonInterpreter.get()])\n+\n+    # Add all qualifying interpreters found in $PATH.\n+    interpreters.update(PythonInterpreter.all())\n \n   return list(\n     matched_interpreters(interpreters, compatibility_constraints)\n@@ -56,7 +57,7 @@\n   )\n \n \n-def _select_pex_python_interpreter(target_python, compatibility_constraints):\n+def _select_pex_python_interpreter(target_python, compatibility_constraints=None):\n   target = find_in_path(target_python)\n \n   if not target:\n@@ -71,9 +72,9 @@\n   return target\n \n \n-def _select_interpreter(pex_python_path, compatibility_constraints):\n+def _select_interpreter(pex_python_path=None, compatibility_constraints=None):\n   compatible_interpreters = find_compatible_interpreters(\n-    pex_python_path, compatibility_constraints)\n+    pex_python_path=pex_python_path, compatibility_constraints=compatibility_constraints)\n \n   if not compatible_interpreters:\n     die('Failed to find compatible interpreter for constraints: %s'\n@@ -114,16 +115,14 @@\n       # TODO: Kill this off completely in favor of PEX_PYTHON_PATH\n       # https://github.com/pantsbuild/pex/issues/431\n       target = _select_pex_python_interpreter(ENV.PEX_PYTHON,\n-                                              compatibility_constraints)\n+                                              compatibility_constraints=compatibility_constraints)\n     elif ENV.PEX_PYTHON_PATH:\n-      target = _select_interpreter(ENV.PEX_PYTHON_PATH, compatibility_constraints)\n+      target = _select_interpreter(pex_python_path=ENV.PEX_PYTHON_PATH,\n+                                   compatibility_constraints=compatibility_constraints)\n \n     elif compatibility_constraints:\n       # Apply constraints to target using regular PATH\n-      target = _select_interpreter(\n-        pex_python_path=None,\n-        compatibility_constraints=compatibility_constraints\n-      )\n+      target = _select_interpreter(compatibility_constraints=compatibility_constraints)\n \n   if target and os.path.realpath(target) != os.path.realpath(sys.executable):\n     cmdline = [target] + sys.argv\n", "issue": "If sys.executable is not on PATH a pex will re-exec itself forever.\nThis can happen via:\r\n```\r\n/not/on/PATH/python a.pex\r\n```\r\n\r\nIf `a.pex` in this example has compatibility constraints that rule out all other interpreters on `PATH` (or there are no intepreters on `PATH`!, c.f.: #53), then, even if sys.executable would be compatible to execute `a.pex` with, it is not considered useable:\r\nhttps://github.com/pantsbuild/pex/blob/442ce7952674cb8a367ecded7d138661194d4f12/pex/pex_bootstrapper.py#L45-L50\r\nhttps://github.com/pantsbuild/pex/blob/442ce7952674cb8a367ecded7d138661194d4f12/pex/interpreter.py#L283-L287\r\n\r\nAnd so the pex_bootstrapper re-execs the pex ad infinitum:\r\nhttps://github.com/pantsbuild/pex/blob/442ce7952674cb8a367ecded7d138661194d4f12/pex/pex_bootstrapper.py#L122-L137\n", "before_files": [{"content": "# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import absolute_import, print_function\n\nimport os\nimport sys\n\nfrom pex import pex_warnings\nfrom pex.common import die\nfrom pex.executor import Executor\nfrom pex.interpreter import PythonInterpreter\nfrom pex.interpreter_constraints import matched_interpreters\nfrom pex.tracer import TRACER\nfrom pex.variables import ENV\n\n__all__ = ('bootstrap_pex',)\n\n\ndef find_in_path(target_interpreter):\n  if os.path.exists(target_interpreter):\n    return target_interpreter\n\n  for directory in os.getenv('PATH', '').split(os.pathsep):\n    try_path = os.path.join(directory, target_interpreter)\n    if os.path.exists(try_path):\n      return try_path\n\n\ndef find_compatible_interpreters(pex_python_path, compatibility_constraints):\n  \"\"\"Find all compatible interpreters on the system within the supplied constraints and use\n     PEX_PYTHON_PATH if it is set. If not, fall back to interpreters on $PATH.\n  \"\"\"\n  if pex_python_path:\n    interpreters = []\n    for binary in pex_python_path.split(os.pathsep):\n      try:\n        interpreters.append(PythonInterpreter.from_binary(binary))\n      except Executor.ExecutionError:\n        print(\"Python interpreter %s in PEX_PYTHON_PATH failed to load properly.\" % binary,\n          file=sys.stderr)\n    if not interpreters:\n      die('PEX_PYTHON_PATH was defined, but no valid interpreters could be identified. Exiting.')\n  else:\n    if not os.getenv('PATH', ''):\n      # no $PATH, use sys.executable\n      interpreters = [PythonInterpreter.get()]\n    else:\n      # get all qualifying interpreters found in $PATH\n      interpreters = PythonInterpreter.all()\n\n  return list(\n    matched_interpreters(interpreters, compatibility_constraints)\n    if compatibility_constraints\n    else interpreters\n  )\n\n\ndef _select_pex_python_interpreter(target_python, compatibility_constraints):\n  target = find_in_path(target_python)\n\n  if not target:\n    die('Failed to find interpreter specified by PEX_PYTHON: %s' % target)\n  if compatibility_constraints:\n    pi = PythonInterpreter.from_binary(target)\n    if not list(matched_interpreters([pi], compatibility_constraints)):\n      die('Interpreter specified by PEX_PYTHON (%s) is not compatible with specified '\n          'interpreter constraints: %s' % (target, str(compatibility_constraints)))\n  if not os.path.exists(target):\n    die('Target interpreter specified by PEX_PYTHON %s does not exist. Exiting.' % target)\n  return target\n\n\ndef _select_interpreter(pex_python_path, compatibility_constraints):\n  compatible_interpreters = find_compatible_interpreters(\n    pex_python_path, compatibility_constraints)\n\n  if not compatible_interpreters:\n    die('Failed to find compatible interpreter for constraints: %s'\n        % str(compatibility_constraints))\n  # TODO: https://github.com/pantsbuild/pex/issues/430\n  target = min(compatible_interpreters).binary\n\n  if os.path.exists(target):\n    return target\n\n\ndef maybe_reexec_pex(compatibility_constraints):\n  \"\"\"\n  Handle environment overrides for the Python interpreter to use when executing this pex.\n\n  This function supports interpreter filtering based on interpreter constraints stored in PEX-INFO\n  metadata. If PEX_PYTHON is set in a pexrc, it attempts to obtain the binary location of the\n  interpreter specified by PEX_PYTHON. If PEX_PYTHON_PATH is set, it attempts to search the path for\n  a matching interpreter in accordance with the interpreter constraints. If both variables are\n  present in a pexrc, this function gives precedence to PEX_PYTHON_PATH and errors out if no\n  compatible interpreters can be found on said path.\n\n  If neither variable is set, we fall back to plain PEX execution using PATH searching or the\n  currently executing interpreter. If compatibility constraints are used, we match those constraints\n  against these interpreters.\n\n  :param compatibility_constraints: list of requirements-style strings that constrain the\n  Python interpreter to re-exec this pex with.\n  \"\"\"\n  if os.environ.pop('SHOULD_EXIT_BOOTSTRAP_REEXEC', None):\n    # We've already been here and selected an interpreter. Continue to execution.\n    return\n\n  target = None\n  with TRACER.timed('Selecting runtime interpreter based on pexrc', V=3):\n    if ENV.PEX_PYTHON and not ENV.PEX_PYTHON_PATH:\n      # preserve PEX_PYTHON re-exec for backwards compatibility\n      # TODO: Kill this off completely in favor of PEX_PYTHON_PATH\n      # https://github.com/pantsbuild/pex/issues/431\n      target = _select_pex_python_interpreter(ENV.PEX_PYTHON,\n                                              compatibility_constraints)\n    elif ENV.PEX_PYTHON_PATH:\n      target = _select_interpreter(ENV.PEX_PYTHON_PATH, compatibility_constraints)\n\n    elif compatibility_constraints:\n      # Apply constraints to target using regular PATH\n      target = _select_interpreter(\n        pex_python_path=None,\n        compatibility_constraints=compatibility_constraints\n      )\n\n  if target and os.path.realpath(target) != os.path.realpath(sys.executable):\n    cmdline = [target] + sys.argv\n    TRACER.log('Re-executing: cmdline=\"%s\", sys.executable=\"%s\", PEX_PYTHON=\"%s\", '\n               'PEX_PYTHON_PATH=\"%s\", COMPATIBILITY_CONSTRAINTS=\"%s\"'\n               % (cmdline, sys.executable, ENV.PEX_PYTHON, ENV.PEX_PYTHON_PATH,\n                  compatibility_constraints))\n    ENV.delete('PEX_PYTHON')\n    ENV.delete('PEX_PYTHON_PATH')\n    os.environ['SHOULD_EXIT_BOOTSTRAP_REEXEC'] = '1'\n    os.execve(target, cmdline, ENV.copy())\n\n\ndef _bootstrap(entry_point):\n  from .pex_info import PexInfo\n  pex_info = PexInfo.from_pex(entry_point)\n  pex_warnings.configure_warnings(pex_info)\n\n  from .finders import register_finders\n  register_finders()\n\n  return pex_info\n\n\ndef bootstrap_pex(entry_point):\n  pex_info = _bootstrap(entry_point)\n  maybe_reexec_pex(pex_info.interpreter_constraints)\n\n  from . import pex\n  pex.PEX(entry_point).execute()\n\n\n# NB: This helper is used by third party libs - namely https://github.com/wickman/lambdex.\n# TODO(John Sirois): Kill once https://github.com/wickman/lambdex/issues/5 is resolved.\ndef is_compressed(entry_point):\n  from .pex_info import PexInfo\n  return os.path.exists(entry_point) and not os.path.exists(os.path.join(entry_point, PexInfo.PATH))\n\n\ndef bootstrap_pex_env(entry_point):\n  \"\"\"Bootstrap the current runtime environment using a given pex.\"\"\"\n  pex_info = _bootstrap(entry_point)\n\n  from .environment import PEXEnvironment\n  PEXEnvironment(entry_point, pex_info).activate()\n", "path": "pex/pex_bootstrapper.py"}], "after_files": [{"content": "# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import absolute_import, print_function\n\nimport os\nimport sys\n\nfrom pex import pex_warnings\nfrom pex.common import die\nfrom pex.executor import Executor\nfrom pex.interpreter import PythonInterpreter\nfrom pex.interpreter_constraints import matched_interpreters\nfrom pex.orderedset import OrderedSet\nfrom pex.tracer import TRACER\nfrom pex.variables import ENV\n\n__all__ = ('bootstrap_pex',)\n\n\ndef find_in_path(target_interpreter):\n  if os.path.exists(target_interpreter):\n    return target_interpreter\n\n  for directory in os.getenv('PATH', '').split(os.pathsep):\n    try_path = os.path.join(directory, target_interpreter)\n    if os.path.exists(try_path):\n      return try_path\n\n\ndef find_compatible_interpreters(pex_python_path=None, compatibility_constraints=None):\n  \"\"\"Find all compatible interpreters on the system within the supplied constraints and use\n     PEX_PYTHON_PATH if it is set. If not, fall back to interpreters on $PATH.\n  \"\"\"\n  if pex_python_path:\n    interpreters = []\n    for binary in pex_python_path.split(os.pathsep):\n      try:\n        interpreters.append(PythonInterpreter.from_binary(binary))\n      except Executor.ExecutionError:\n        print(\"Python interpreter %s in PEX_PYTHON_PATH failed to load properly.\" % binary,\n          file=sys.stderr)\n    if not interpreters:\n      die('PEX_PYTHON_PATH was defined, but no valid interpreters could be identified. Exiting.')\n  else:\n    # We may have been invoked with a specific interpreter not on the $PATH, make sure our\n    # sys.executable is included as a candidate in this case.\n    interpreters = OrderedSet([PythonInterpreter.get()])\n\n    # Add all qualifying interpreters found in $PATH.\n    interpreters.update(PythonInterpreter.all())\n\n  return list(\n    matched_interpreters(interpreters, compatibility_constraints)\n    if compatibility_constraints\n    else interpreters\n  )\n\n\ndef _select_pex_python_interpreter(target_python, compatibility_constraints=None):\n  target = find_in_path(target_python)\n\n  if not target:\n    die('Failed to find interpreter specified by PEX_PYTHON: %s' % target)\n  if compatibility_constraints:\n    pi = PythonInterpreter.from_binary(target)\n    if not list(matched_interpreters([pi], compatibility_constraints)):\n      die('Interpreter specified by PEX_PYTHON (%s) is not compatible with specified '\n          'interpreter constraints: %s' % (target, str(compatibility_constraints)))\n  if not os.path.exists(target):\n    die('Target interpreter specified by PEX_PYTHON %s does not exist. Exiting.' % target)\n  return target\n\n\ndef _select_interpreter(pex_python_path=None, compatibility_constraints=None):\n  compatible_interpreters = find_compatible_interpreters(\n    pex_python_path=pex_python_path, compatibility_constraints=compatibility_constraints)\n\n  if not compatible_interpreters:\n    die('Failed to find compatible interpreter for constraints: %s'\n        % str(compatibility_constraints))\n  # TODO: https://github.com/pantsbuild/pex/issues/430\n  target = min(compatible_interpreters).binary\n\n  if os.path.exists(target):\n    return target\n\n\ndef maybe_reexec_pex(compatibility_constraints):\n  \"\"\"\n  Handle environment overrides for the Python interpreter to use when executing this pex.\n\n  This function supports interpreter filtering based on interpreter constraints stored in PEX-INFO\n  metadata. If PEX_PYTHON is set in a pexrc, it attempts to obtain the binary location of the\n  interpreter specified by PEX_PYTHON. If PEX_PYTHON_PATH is set, it attempts to search the path for\n  a matching interpreter in accordance with the interpreter constraints. If both variables are\n  present in a pexrc, this function gives precedence to PEX_PYTHON_PATH and errors out if no\n  compatible interpreters can be found on said path.\n\n  If neither variable is set, we fall back to plain PEX execution using PATH searching or the\n  currently executing interpreter. If compatibility constraints are used, we match those constraints\n  against these interpreters.\n\n  :param compatibility_constraints: list of requirements-style strings that constrain the\n  Python interpreter to re-exec this pex with.\n  \"\"\"\n  if os.environ.pop('SHOULD_EXIT_BOOTSTRAP_REEXEC', None):\n    # We've already been here and selected an interpreter. Continue to execution.\n    return\n\n  target = None\n  with TRACER.timed('Selecting runtime interpreter based on pexrc', V=3):\n    if ENV.PEX_PYTHON and not ENV.PEX_PYTHON_PATH:\n      # preserve PEX_PYTHON re-exec for backwards compatibility\n      # TODO: Kill this off completely in favor of PEX_PYTHON_PATH\n      # https://github.com/pantsbuild/pex/issues/431\n      target = _select_pex_python_interpreter(ENV.PEX_PYTHON,\n                                              compatibility_constraints=compatibility_constraints)\n    elif ENV.PEX_PYTHON_PATH:\n      target = _select_interpreter(pex_python_path=ENV.PEX_PYTHON_PATH,\n                                   compatibility_constraints=compatibility_constraints)\n\n    elif compatibility_constraints:\n      # Apply constraints to target using regular PATH\n      target = _select_interpreter(compatibility_constraints=compatibility_constraints)\n\n  if target and os.path.realpath(target) != os.path.realpath(sys.executable):\n    cmdline = [target] + sys.argv\n    TRACER.log('Re-executing: cmdline=\"%s\", sys.executable=\"%s\", PEX_PYTHON=\"%s\", '\n               'PEX_PYTHON_PATH=\"%s\", COMPATIBILITY_CONSTRAINTS=\"%s\"'\n               % (cmdline, sys.executable, ENV.PEX_PYTHON, ENV.PEX_PYTHON_PATH,\n                  compatibility_constraints))\n    ENV.delete('PEX_PYTHON')\n    ENV.delete('PEX_PYTHON_PATH')\n    os.environ['SHOULD_EXIT_BOOTSTRAP_REEXEC'] = '1'\n    os.execve(target, cmdline, ENV.copy())\n\n\ndef _bootstrap(entry_point):\n  from .pex_info import PexInfo\n  pex_info = PexInfo.from_pex(entry_point)\n  pex_warnings.configure_warnings(pex_info)\n\n  from .finders import register_finders\n  register_finders()\n\n  return pex_info\n\n\ndef bootstrap_pex(entry_point):\n  pex_info = _bootstrap(entry_point)\n  maybe_reexec_pex(pex_info.interpreter_constraints)\n\n  from . import pex\n  pex.PEX(entry_point).execute()\n\n\n# NB: This helper is used by third party libs - namely https://github.com/wickman/lambdex.\n# TODO(John Sirois): Kill once https://github.com/wickman/lambdex/issues/5 is resolved.\ndef is_compressed(entry_point):\n  from .pex_info import PexInfo\n  return os.path.exists(entry_point) and not os.path.exists(os.path.join(entry_point, PexInfo.PATH))\n\n\ndef bootstrap_pex_env(entry_point):\n  \"\"\"Bootstrap the current runtime environment using a given pex.\"\"\"\n  pex_info = _bootstrap(entry_point)\n\n  from .environment import PEXEnvironment\n  PEXEnvironment(entry_point, pex_info).activate()\n", "path": "pex/pex_bootstrapper.py"}]}