Add a Notification Settings Button to all web notifications behind the web platform...
[chromium-blink-merge.git] / third_party / pycoverage / coverage / execfile.py
blobf6ebdf79bb9e8a1fb9268af492cdbea4a09ab522
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
9 try:
10 # In Py 2.x, the builtins were in __builtin__
11 BUILTINS = sys.modules['__builtin__']
12 except KeyError:
13 # In Py 3.x, they're in builtins
14 BUILTINS = sys.modules['builtins']
17 def rsplit1(s, sep):
18 """The same as s.rsplit(sep, 1), but works in 2.3"""
19 parts = s.split(sep)
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.
30 """
31 openfile = None
32 glo, loc = globals(), locals()
33 try:
34 try:
35 # Search for the module - inside its parent package, if any - using
36 # standard import mechanics.
37 if '.' in modulename:
38 packagename, name = rsplit1(modulename, '.')
39 package = __import__(packagename, glo, loc, ['__path__'])
40 searchpath = package.__path__
41 else:
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:
48 raise NoSource(
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.
54 if openfile is None:
55 packagename = modulename
56 name = '__main__'
57 package = __import__(packagename, glo, loc, ['__path__'])
58 searchpath = package.__path__
59 openfile, pathname, _ = imp.find_module(name, searchpath)
60 except ImportError:
61 _, err, _ = sys.exc_info()
62 raise NoSource(str(err))
63 finally:
64 if openfile:
65 openfile.close()
67 # Finally, hand the file off to run_python_file for execution.
68 pathname = os.path.abspath(pathname)
69 args[0] = 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.
81 """
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
87 if package:
88 main_mod.__package__ = package
89 main_mod.__builtins__ = BUILTINS
91 # Set sys.argv properly.
92 old_argv = sys.argv
93 sys.argv = args
95 try:
96 # Make a code object somehow.
97 if filename.endswith(".pyc") or filename.endswith(".pyo"):
98 code = make_code_from_pyc(filename)
99 else:
100 code = make_code_from_py(filename)
102 # Execute the code object.
103 try:
104 exec_code_object(code, main_mod.__dict__)
105 except SystemExit:
106 # The user called sys.exit(). Just pass it along to the upper
107 # layers, where it will be handled.
108 raise
109 except:
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
114 # traceback.
115 typ, err, tb = sys.exc_info()
116 raise ExceptionDuringRun(typ, err, tb.tb_next.tb_next)
117 finally:
118 # Restore the old __main__
119 sys.modules['__main__'] = old_main_mod
121 # Restore the old argv and path
122 sys.argv = old_argv
124 def make_code_from_py(filename):
125 """Get source from `filename` and make a code object of it."""
126 # Open the source file.
127 try:
128 source_file = open_source(filename)
129 except IOError:
130 raise NoSource("No file to run: %r" % filename)
132 try:
133 source = source_file.read()
134 finally:
135 source_file.close()
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':
140 source += '\n'
141 code = compile(source, filename, "exec")
143 return code
146 def make_code_from_pyc(filename):
147 """Get a code object from a .pyc file."""
148 try:
149 fpyc = open(filename, "rb")
150 except IOError:
151 raise NoCode("No file to run: %r" % filename)
153 try:
154 # First four bytes are a version-specific magic number. It has to
155 # match or we won't run the file.
156 magic = fpyc.read(4)
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.
164 fpyc.read(4)
166 # The rest of the file is the code object we want.
167 code = marshal.load(fpyc)
168 finally:
169 fpyc.close()
171 return code