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