def iter_pth_paths(filename): """Given a .pth file, extract and yield all inner paths without honoring imports. This shadows Python's site.py behavior, which is invoked at interpreter startup. """ try: f = open(filename, "rU" if PY2 else "r") # noqa except IOError: return dirname = os.path.dirname(filename) known_paths = set() with f: for i, line in enumerate(f, start=1): line = line.rstrip() if not line or line.startswith("#"): continue elif line.startswith(("import ", "import\t")): # One important side effect of executing import lines can be alteration of the # sys.path directly or indirectly as a programmatic way to add sys.path entries # in contrast to the standard .pth mechanism of including fixed paths as # individual lines in the file. Here we capture all such programmatic attempts # to expand the sys.path and report the additions. original_sys_path = sys.path[:] try: # N.B.: Setting sys.path to empty is ok since all the .pth files we find and # execute have already been found and executed by our ambient sys.executable # when it started up before running this PEX file. As such, all symbols imported # by the .pth files then will still be available now as cached in sys.modules. sys.path = [] exec_function(line, globals_map={}) for path in sys.path: yield path except Exception as e: # NB: import lines are routinely abused with extra code appended using `;` so # the class of exceptions that might be raised in broader than ImportError. As # such we catch broadly here. TRACER.log( "Error executing line {linenumber} of {pth_file} with content:\n" "{content}\n" "Error was:\n" "{error}".format(linenumber=i, pth_file=filename, content=line, error=e), V=9, ) # Defer error handling to the higher level site.py logic invoked at startup. return finally: sys.path = original_sys_path else: extras_dir, extras_dir_case_insensitive = makepath( dirname, line) if extras_dir_case_insensitive not in known_paths and os.path.exists( extras_dir): yield extras_dir known_paths.add(extras_dir_case_insensitive)
def iter_pth_paths(filename): """Given a .pth file, extract and yield all inner paths without honoring imports. This shadows python's site.py behavior, which is invoked at interpreter startup.""" try: f = open(filename, 'rU') # noqa except IOError: return dirname = os.path.dirname(filename) known_paths = set() with f: for line in f: line = line.rstrip() if not line or line.startswith('#'): continue elif line.startswith(('import ', 'import\t')): try: exec_function(line, globals_map={}) continue except Exception: # NB: import lines are routinely abused with extra code appended using `;` so the class of # exceptions that might be raised in broader than ImportError. As such we cacth broadly # here. # Defer error handling to the higher level site.py logic invoked at startup. return else: extras_dir, extras_dir_case_insensitive = makepath( dirname, line) if extras_dir_case_insensitive not in known_paths and os.path.exists( extras_dir): yield extras_dir known_paths.add(extras_dir_case_insensitive)
def execute_content( cls, name, # type: str content, # type: str argv0=None, # type: Optional[str] ): # type: (...) -> Optional[str] argv0 = argv0 or name try: ast = compile(content, name, "exec", flags=0, dont_inherit=1) except SyntaxError: return "Unable to parse {}. PEX script support only supports Python scripts.".format( name ) cls.demote_bootstrap() from pex.compatibility import exec_function sys.argv[0] = argv0 globals_map = globals().copy() globals_map["__name__"] = "__main__" globals_map["__file__"] = name exec_function(ast, globals_map) return None
def iter_pth_paths(filename): """Given a .pth file, extract and yield all inner paths without honoring imports. This shadows python's site.py behavior, which is invoked at interpreter startup.""" try: f = open(filename, 'rU') # noqa except IOError: return dirname = os.path.dirname(filename) known_paths = set() with f: for line in f: line = line.rstrip() if not line or line.startswith('#'): continue elif line.startswith(('import ', 'import\t')): try: exec_function(line, globals_map={}) continue except Exception: # NB: import lines are routinely abused with extra code appended using `;` so the class of # exceptions that might be raised in broader than ImportError. As such we cacth broadly # here. # Defer error handling to the higher level site.py logic invoked at startup. return else: extras_dir, extras_dir_case_insensitive = makepath(dirname, line) if extras_dir_case_insensitive not in known_paths and os.path.exists(extras_dir): yield extras_dir known_paths.add(extras_dir_case_insensitive)
def execute_content(cls, name, content, argv0=None): argv0 = argv0 or name try: ast = compile(content, name, 'exec', flags=0, dont_inherit=1) except SyntaxError: die('Unable to parse %s. PEX script support only supports Python scripts.' % name) cls.demote_bootstrap() from pex.compatibility import exec_function sys.argv[0] = argv0 globals_map = globals().copy() globals_map['__name__'] = '__main__' globals_map['__file__'] = name exec_function(ast, globals_map)