1#!/usr/bin/env '%interpreter%' 2 3import os 4import re 5import tempfile 6import shutil 7import sys 8import subprocess 9import zipfile 10 11PYTHON_BINARY = '%interpreter%' 12MAIN_FILE = '%main%' 13PYTHON_PATH = 'PYTHONPATH' 14 15# Don't imply 'import site' on initialization 16PYTHON_ARG = '-S' 17 18def SearchPathEnv(name): 19 search_path = os.getenv('PATH', os.defpath).split(os.pathsep) 20 for directory in search_path: 21 if directory == '': continue 22 path = os.path.join(directory, name) 23 # Check if path is actual executable file. 24 if os.path.isfile(path) and os.access(path, os.X_OK): 25 return path 26 return None 27 28def FindPythonBinary(): 29 if PYTHON_BINARY.startswith('/'): 30 # Case 1: Python interpreter is directly provided with absolute path. 31 return PYTHON_BINARY 32 else: 33 # Case 2: Find Python interpreter through environment variable: PATH. 34 return SearchPathEnv(PYTHON_BINARY) 35 36# Create the runfiles tree by extracting the zip file 37def ExtractRunfiles(): 38 temp_dir = tempfile.mkdtemp("", "Soong.python_") 39 zf = zipfile.ZipFile(os.path.dirname(__file__)) 40 zf.extractall(temp_dir) 41 return temp_dir 42 43def Main(): 44 args = sys.argv[1:] 45 46 new_env = {} 47 runfiles_path = None 48 49 try: 50 runfiles_path = ExtractRunfiles() 51 52 # Add runfiles path to PYTHONPATH. 53 python_path_entries = [runfiles_path] 54 55 # Add top dirs within runfiles path to PYTHONPATH. 56 top_entries = [os.path.join(runfiles_path, i) for i in os.listdir(runfiles_path)] 57 top_pkg_dirs = [i for i in top_entries if os.path.isdir(i)] 58 python_path_entries += top_pkg_dirs 59 60 old_python_path = os.environ.get(PYTHON_PATH) 61 separator = ':' 62 new_python_path = separator.join(python_path_entries) 63 64 # Copy old PYTHONPATH. 65 if old_python_path: 66 new_python_path += separator + old_python_path 67 new_env[PYTHON_PATH] = new_python_path 68 69 # Now look for main python source file. 70 main_filepath = os.path.join(runfiles_path, MAIN_FILE) 71 assert os.path.exists(main_filepath), \ 72 'Cannot exec() %r: file not found.' % main_filepath 73 assert os.access(main_filepath, os.R_OK), \ 74 'Cannot exec() %r: file not readable.' % main_filepath 75 76 python_program = FindPythonBinary() 77 if python_program is None: 78 raise AssertionError('Could not find python binary: ' + PYTHON_BINARY) 79 args = [python_program, PYTHON_ARG, main_filepath] + args 80 81 os.environ.update(new_env) 82 83 sys.stdout.flush() 84 retCode = subprocess.call(args) 85 sys.exit(retCode) 86 except: 87 raise 88 finally: 89 if runfiles_path is not None: 90 shutil.rmtree(runfiles_path, True) 91 92if __name__ == '__main__': 93 Main() 94