17757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch"""Execute files of Python code.""" 27757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 37757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochimport imp, os, sys 47757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 57757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochfrom coverage.backward import exec_code_object, open_source 67757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochfrom coverage.misc import NoSource, ExceptionDuringRun 77757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 87757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 97757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochtry: 107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # In Py 2.x, the builtins were in __builtin__ 117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch BUILTINS = sys.modules['__builtin__'] 127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochexcept KeyError: 137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # In Py 3.x, they're in builtins 147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch BUILTINS = sys.modules['builtins'] 157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochdef rsplit1(s, sep): 187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch """The same as s.rsplit(sep, 1), but works in 2.3""" 197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch parts = s.split(sep) 207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return sep.join(parts[:-1]), parts[-1] 217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochdef run_python_module(modulename, args): 247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch """Run a python module, as though with ``python -m name args...``. 257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch `modulename` is the name of the module, possibly a dot-separated name. 277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch `args` is the argument array to present as sys.argv, including the first 287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch element naming the module being executed. 297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch """ 317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch openfile = None 327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch glo, loc = globals(), locals() 337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch try: 347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch try: 357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Search for the module - inside its parent package, if any - using 367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # standard import mechanics. 377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if '.' in modulename: 387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch packagename, name = rsplit1(modulename, '.') 397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch package = __import__(packagename, glo, loc, ['__path__']) 407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch searchpath = package.__path__ 417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch else: 427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch packagename, name = None, modulename 437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch searchpath = None # "top-level search" in imp.find_module() 447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch openfile, pathname, _ = imp.find_module(name, searchpath) 457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Complain if this is a magic non-file module. 477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if openfile is None and pathname is None: 487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch raise NoSource( 497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch "module does not live in a file: %r" % modulename 507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch ) 517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # If `modulename` is actually a package, not a mere module, then we 537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # pretend to be Python 2.7 and try running its __main__.py script. 547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if openfile is None: 557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch packagename = modulename 567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch name = '__main__' 577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch package = __import__(packagename, glo, loc, ['__path__']) 587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch searchpath = package.__path__ 597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch openfile, pathname, _ = imp.find_module(name, searchpath) 607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch except ImportError: 617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch _, err, _ = sys.exc_info() 627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch raise NoSource(str(err)) 637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch finally: 647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if openfile: 657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch openfile.close() 667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Finally, hand the file off to run_python_file for execution. 687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch run_python_file(pathname, args, package=packagename) 697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochdef run_python_file(filename, args, package=None): 727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch """Run a python file as if it were the main program on the command line. 737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch `filename` is the path to the file to execute, it need not be a .py file. 757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch `args` is the argument array to present as sys.argv, including the first 767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch element naming the file being executed. `package` is the name of the 777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch enclosing package, if any. 787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch """ 807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Create a module to serve as __main__ 817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch old_main_mod = sys.modules['__main__'] 827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch main_mod = imp.new_module('__main__') 837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch sys.modules['__main__'] = main_mod 847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch main_mod.__file__ = filename 857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch main_mod.__package__ = package 867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch main_mod.__builtins__ = BUILTINS 877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Set sys.argv and the first path element properly. 897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch old_argv = sys.argv 907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch old_path0 = sys.path[0] 917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch sys.argv = args 927757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch sys.path[0] = os.path.abspath(os.path.dirname(filename)) 937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch try: 957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Open the source file. 967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch try: 977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch source_file = open_source(filename) 987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch except IOError: 997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch raise NoSource("No file to run: %r" % filename) 1007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch try: 1027757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch source = source_file.read() 1037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch finally: 1047757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch source_file.close() 1057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # We have the source. `compile` still needs the last line to be clean, 1077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # so make sure it is, then compile a code object from it. 1087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if source[-1] != '\n': 1097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch source += '\n' 1107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch code = compile(source, filename, "exec") 1117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Execute the source file. 1137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch try: 1147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch exec_code_object(code, main_mod.__dict__) 1157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch except SystemExit: 1167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # The user called sys.exit(). Just pass it along to the upper 1177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # layers, where it will be handled. 1187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch raise 1197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch except: 1207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Something went wrong while executing the user code. 1217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Get the exc_info, and pack them into an exception that we can 1227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # throw up to the outer loop. We peel two layers off the traceback 1237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # so that the coverage.py code doesn't appear in the final printed 1247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # traceback. 1257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch typ, err, tb = sys.exc_info() 1267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch raise ExceptionDuringRun(typ, err, tb.tb_next.tb_next) 1277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch finally: 1287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Restore the old __main__ 1297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch sys.modules['__main__'] = old_main_mod 1307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 1317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch # Restore the old argv and path 1327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch sys.argv = old_argv 1337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch sys.path[0] = old_path0 134