1 """Execute files of Python code."""
3 import imp
, marshal
, os
, sys
5 from coverage
.backward
import exec_code_object
, open_source
6 from coverage
.misc
import ExceptionDuringRun
, NoCode
, NoSource
10 # In Py 2.x, the builtins were in __builtin__
11 BUILTINS
= sys
.modules
['__builtin__']
13 # In Py 3.x, they're in builtins
14 BUILTINS
= sys
.modules
['builtins']
18 """The same as s.rsplit(sep, 1), but works in 2.3"""
20 return sep
.join(parts
[:-1]), parts
[-1]
23 def run_python_module(modulename
, args
):
24 """Run a python module, as though with ``python -m name args...``.
26 `modulename` is the name of the module, possibly a dot-separated name.
27 `args` is the argument array to present as sys.argv, including the first
28 element naming the module being executed.
32 glo
, loc
= globals(), locals()
35 # Search for the module - inside its parent package, if any - using
36 # standard import mechanics.
38 packagename
, name
= rsplit1(modulename
, '.')
39 package
= __import__(packagename
, glo
, loc
, ['__path__'])
40 searchpath
= package
.__path
__
42 packagename
, name
= None, modulename
43 searchpath
= None # "top-level search" in imp.find_module()
44 openfile
, pathname
, _
= imp
.find_module(name
, searchpath
)
46 # Complain if this is a magic non-file module.
47 if openfile
is None and pathname
is None:
49 "module does not live in a file: %r" % modulename
52 # If `modulename` is actually a package, not a mere module, then we
53 # pretend to be Python 2.7 and try running its __main__.py script.
55 packagename
= modulename
57 package
= __import__(packagename
, glo
, loc
, ['__path__'])
58 searchpath
= package
.__path
__
59 openfile
, pathname
, _
= imp
.find_module(name
, searchpath
)
61 _
, err
, _
= sys
.exc_info()
62 raise NoSource(str(err
))
67 # Finally, hand the file off to run_python_file for execution.
68 pathname
= os
.path
.abspath(pathname
)
70 run_python_file(pathname
, args
, package
=packagename
)
73 def run_python_file(filename
, args
, package
=None):
74 """Run a python file as if it were the main program on the command line.
76 `filename` is the path to the file to execute, it need not be a .py file.
77 `args` is the argument array to present as sys.argv, including the first
78 element naming the file being executed. `package` is the name of the
79 enclosing package, if any.
82 # Create a module to serve as __main__
83 old_main_mod
= sys
.modules
['__main__']
84 main_mod
= imp
.new_module('__main__')
85 sys
.modules
['__main__'] = main_mod
86 main_mod
.__file
__ = filename
88 main_mod
.__package
__ = package
89 main_mod
.__builtins
__ = BUILTINS
91 # Set sys.argv properly.
96 # Make a code object somehow.
97 if filename
.endswith(".pyc") or filename
.endswith(".pyo"):
98 code
= make_code_from_pyc(filename
)
100 code
= make_code_from_py(filename
)
102 # Execute the code object.
104 exec_code_object(code
, main_mod
.__dict
__)
106 # The user called sys.exit(). Just pass it along to the upper
107 # layers, where it will be handled.
110 # Something went wrong while executing the user code.
111 # Get the exc_info, and pack them into an exception that we can
112 # throw up to the outer loop. We peel two layers off the traceback
113 # so that the coverage.py code doesn't appear in the final printed
115 typ
, err
, tb
= sys
.exc_info()
116 raise ExceptionDuringRun(typ
, err
, tb
.tb_next
.tb_next
)
118 # Restore the old __main__
119 sys
.modules
['__main__'] = old_main_mod
121 # Restore the old argv and path
124 def make_code_from_py(filename
):
125 """Get source from `filename` and make a code object of it."""
126 # Open the source file.
128 source_file
= open_source(filename
)
130 raise NoSource("No file to run: %r" % filename
)
133 source
= source_file
.read()
137 # We have the source. `compile` still needs the last line to be clean,
138 # so make sure it is, then compile a code object from it.
139 if not source
or source
[-1] != '\n':
141 code
= compile(source
, filename
, "exec")
146 def make_code_from_pyc(filename
):
147 """Get a code object from a .pyc file."""
149 fpyc
= open(filename
, "rb")
151 raise NoCode("No file to run: %r" % filename
)
154 # First four bytes are a version-specific magic number. It has to
155 # match or we won't run the file.
157 if magic
!= imp
.get_magic():
158 raise NoCode("Bad magic number in .pyc file")
160 # Skip the junk in the header that we don't need.
161 fpyc
.read(4) # Skip the moddate.
162 if sys
.version_info
>= (3, 3):
163 # 3.3 added another long to the header (size), skip it.
166 # The rest of the file is the code object we want.
167 code
= marshal
.load(fpyc
)