blob: 96d2bebbc44b8f2e971855e4eafa170d6e0aaa0c [file] [log] [blame]
Thomas Woutersa9773292006-04-21 09:43:23 +00001# Test the runpy module
2import unittest
3import os
4import os.path
5import sys
Nick Coghlan16eb0fb2009-11-18 11:35:25 +00006import re
Thomas Woutersa9773292006-04-21 09:43:23 +00007import tempfile
Barry Warsaw28a691b2010-04-17 00:19:56 +00008import py_compile
Brett Cannon61b14252010-07-03 21:48:25 +00009from test.support import forget, make_legacy_pyc, run_unittest, unload, verbose
Barry Warsaw28a691b2010-04-17 00:19:56 +000010from test.script_helper import (
11 make_pkg, make_script, make_zip_pkg, make_zip_script, temp_dir)
Christian Heimescbf3b5c2007-12-03 21:02:03 +000012
Nick Coghlan761bb112012-07-14 23:59:22 +100013import runpy
Nick Coghlan260bd3e2009-11-16 06:49:25 +000014from runpy import _run_code, _run_module_code, run_module, run_path
Christian Heimescbf3b5c2007-12-03 21:02:03 +000015# Note: This module can't safely test _run_module_as_main as it
16# runs its tests in the current process, which would mess with the
17# real __main__ module (usually test.regrtest)
18# See test_cmd_line_script for a test that executes that code path
Thomas Woutersa9773292006-04-21 09:43:23 +000019
Thomas Woutersa9773292006-04-21 09:43:23 +000020
Nick Coghlan761bb112012-07-14 23:59:22 +100021# Set up the test code and expected results
22example_source = """\
23# Check basic code execution
24result = ['Top level assignment']
25def f():
26 result.append('Lower level reference')
27f()
28del f
29# Check the sys module
30import sys
31run_argv0 = sys.argv[0]
32run_name_in_sys_modules = __name__ in sys.modules
33module_in_sys_modules = (run_name_in_sys_modules and
34 globals() is sys.modules[__name__].__dict__)
35# Check nested operation
36import runpy
37nested = runpy._run_module_code('x=1\\n', mod_name='<run>')
38"""
39
40implicit_namespace = {
41 "__name__": None,
42 "__file__": None,
43 "__cached__": None,
44 "__package__": None,
45 "__doc__": None,
46}
47example_namespace = {
48 "sys": sys,
49 "runpy": runpy,
50 "result": ["Top level assignment", "Lower level reference"],
51 "run_argv0": sys.argv[0],
52 "run_name_in_sys_modules": False,
53 "module_in_sys_modules": False,
54 "nested": dict(implicit_namespace,
55 x=1, __name__="<run>", __loader__=None),
56}
57example_namespace.update(implicit_namespace)
58
59class CodeExecutionMixin:
60 # Issue #15230 (run_path not handling run_name correctly) highlighted a
61 # problem with the way arguments were being passed from higher level APIs
62 # down to lower level code. This mixin makes it easier to ensure full
63 # testing occurs at those upper layers as well, not just at the utility
64 # layer
65
66 def assertNamespaceMatches(self, result_ns, expected_ns):
67 """Check two namespaces match.
68
69 Ignores any unspecified interpreter created names
70 """
71 # Impls are permitted to add extra names, so filter them out
72 for k in list(result_ns):
73 if k.startswith("__") and k.endswith("__"):
74 if k not in expected_ns:
75 result_ns.pop(k)
76 if k not in expected_ns["nested"]:
77 result_ns["nested"].pop(k)
78 # Don't use direct dict comparison - the diffs are too hard to debug
79 self.assertEqual(set(result_ns), set(expected_ns))
80 for k in result_ns:
81 actual = (k, result_ns[k])
82 expected = (k, expected_ns[k])
83 self.assertEqual(actual, expected)
84
85 def check_code_execution(self, create_namespace, expected_namespace):
86 """Check that an interface runs the example code correctly
87
88 First argument is a callable accepting the initial globals and
89 using them to create the actual namespace
90 Second argument is the expected result
91 """
92 sentinel = object()
93 expected_ns = expected_namespace.copy()
94 run_name = expected_ns["__name__"]
95 saved_argv0 = sys.argv[0]
96 saved_mod = sys.modules.get(run_name, sentinel)
97 # Check without initial globals
98 result_ns = create_namespace(None)
99 self.assertNamespaceMatches(result_ns, expected_ns)
100 self.assertIs(sys.argv[0], saved_argv0)
101 self.assertIs(sys.modules.get(run_name, sentinel), saved_mod)
102 # And then with initial globals
103 initial_ns = {"sentinel": sentinel}
104 expected_ns["sentinel"] = sentinel
105 result_ns = create_namespace(initial_ns)
106 self.assertIsNot(result_ns, initial_ns)
107 self.assertNamespaceMatches(result_ns, expected_ns)
108 self.assertIs(sys.argv[0], saved_argv0)
109 self.assertIs(sys.modules.get(run_name, sentinel), saved_mod)
110
111
112class ExecutionLayerTestCase(unittest.TestCase, CodeExecutionMixin):
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000113 """Unit tests for runpy._run_code and runpy._run_module_code"""
Thomas Woutersa9773292006-04-21 09:43:23 +0000114
Thomas Woutersed03b412007-08-28 21:37:11 +0000115 def test_run_code(self):
Nick Coghlan761bb112012-07-14 23:59:22 +1000116 expected_ns = example_namespace.copy()
117 expected_ns.update({
118 "__loader__": None,
119 })
120 def create_ns(init_globals):
121 return _run_code(example_source, {}, init_globals)
122 self.check_code_execution(create_ns, expected_ns)
Thomas Woutersa9773292006-04-21 09:43:23 +0000123
124 def test_run_module_code(self):
Nick Coghlan761bb112012-07-14 23:59:22 +1000125 mod_name = "<Nonsense>"
126 mod_fname = "Some other nonsense"
127 mod_loader = "Now you're just being silly"
128 mod_package = '' # Treat as a top level module
129 expected_ns = example_namespace.copy()
130 expected_ns.update({
131 "__name__": mod_name,
132 "__file__": mod_fname,
133 "__loader__": mod_loader,
134 "__package__": mod_package,
135 "run_argv0": mod_fname,
136 "run_name_in_sys_modules": True,
137 "module_in_sys_modules": True,
138 })
139 def create_ns(init_globals):
140 return _run_module_code(example_source,
141 init_globals,
142 mod_name,
143 mod_fname,
144 mod_loader,
145 mod_package)
146 self.check_code_execution(create_ns, expected_ns)
Thomas Woutersed03b412007-08-28 21:37:11 +0000147
Thomas Woutersa9773292006-04-21 09:43:23 +0000148
Nick Coghlan761bb112012-07-14 23:59:22 +1000149class RunModuleTestCase(unittest.TestCase, CodeExecutionMixin):
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000150 """Unit tests for runpy.run_module"""
Thomas Woutersa9773292006-04-21 09:43:23 +0000151
152 def expect_import_error(self, mod_name):
153 try:
154 run_module(mod_name)
155 except ImportError:
156 pass
157 else:
158 self.fail("Expected import error for " + mod_name)
159
160 def test_invalid_names(self):
Guido van Rossum806c2462007-08-06 23:33:07 +0000161 # Builtin module
Thomas Woutersa9773292006-04-21 09:43:23 +0000162 self.expect_import_error("sys")
Guido van Rossum806c2462007-08-06 23:33:07 +0000163 # Non-existent modules
Thomas Woutersa9773292006-04-21 09:43:23 +0000164 self.expect_import_error("sys.imp.eric")
165 self.expect_import_error("os.path.half")
166 self.expect_import_error("a.bee")
167 self.expect_import_error(".howard")
168 self.expect_import_error("..eaten")
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000169 # Package without __main__.py
170 self.expect_import_error("multiprocessing")
Thomas Woutersa9773292006-04-21 09:43:23 +0000171
172 def test_library_module(self):
Nick Coghlan761bb112012-07-14 23:59:22 +1000173 self.assertEqual(run_module("runpy")["__name__"], "runpy")
Thomas Woutersa9773292006-04-21 09:43:23 +0000174
Guido van Rossum806c2462007-08-06 23:33:07 +0000175 def _add_pkg_dir(self, pkg_dir):
176 os.mkdir(pkg_dir)
Skip Montanaro7a98be22007-08-16 14:35:24 +0000177 pkg_fname = os.path.join(pkg_dir, "__init__.py")
Guido van Rossum806c2462007-08-06 23:33:07 +0000178 pkg_file = open(pkg_fname, "w")
179 pkg_file.close()
180 return pkg_fname
181
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000182 def _make_pkg(self, source, depth, mod_base="runpy_test"):
Thomas Woutersa9773292006-04-21 09:43:23 +0000183 pkg_name = "__runpy_pkg__"
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000184 test_fname = mod_base+os.extsep+"py"
Nick Coghlaneb3e62f2012-07-17 20:42:39 +1000185 pkg_dir = sub_dir = os.path.realpath(tempfile.mkdtemp())
Nick Coghlan761bb112012-07-14 23:59:22 +1000186 if verbose > 1: print(" Package tree in:", sub_dir)
Thomas Woutersa9773292006-04-21 09:43:23 +0000187 sys.path.insert(0, pkg_dir)
Nick Coghlan761bb112012-07-14 23:59:22 +1000188 if verbose > 1: print(" Updated sys.path:", sys.path[0])
Thomas Woutersa9773292006-04-21 09:43:23 +0000189 for i in range(depth):
190 sub_dir = os.path.join(sub_dir, pkg_name)
Guido van Rossum806c2462007-08-06 23:33:07 +0000191 pkg_fname = self._add_pkg_dir(sub_dir)
Nick Coghlan761bb112012-07-14 23:59:22 +1000192 if verbose > 1: print(" Next level in:", sub_dir)
193 if verbose > 1: print(" Created:", pkg_fname)
Thomas Woutersa9773292006-04-21 09:43:23 +0000194 mod_fname = os.path.join(sub_dir, test_fname)
195 mod_file = open(mod_fname, "w")
196 mod_file.write(source)
197 mod_file.close()
Nick Coghlan761bb112012-07-14 23:59:22 +1000198 if verbose > 1: print(" Created:", mod_fname)
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000199 mod_name = (pkg_name+".")*depth + mod_base
Thomas Woutersa9773292006-04-21 09:43:23 +0000200 return pkg_dir, mod_fname, mod_name
201
202 def _del_pkg(self, top, depth, mod_name):
Guido van Rossum806c2462007-08-06 23:33:07 +0000203 for entry in list(sys.modules):
204 if entry.startswith("__runpy_pkg__"):
Thomas Woutersa9773292006-04-21 09:43:23 +0000205 del sys.modules[entry]
Nick Coghlan761bb112012-07-14 23:59:22 +1000206 if verbose > 1: print(" Removed sys.modules entries")
Thomas Woutersa9773292006-04-21 09:43:23 +0000207 del sys.path[0]
Nick Coghlan761bb112012-07-14 23:59:22 +1000208 if verbose > 1: print(" Removed sys.path entry")
Thomas Woutersa9773292006-04-21 09:43:23 +0000209 for root, dirs, files in os.walk(top, topdown=False):
210 for name in files:
211 try:
212 os.remove(os.path.join(root, name))
Guido van Rossumb940e112007-01-10 16:19:56 +0000213 except OSError as ex:
Nick Coghlan761bb112012-07-14 23:59:22 +1000214 if verbose > 1: print(ex) # Persist with cleaning up
Thomas Woutersa9773292006-04-21 09:43:23 +0000215 for name in dirs:
216 fullname = os.path.join(root, name)
217 try:
218 os.rmdir(fullname)
Guido van Rossumb940e112007-01-10 16:19:56 +0000219 except OSError as ex:
Nick Coghlan761bb112012-07-14 23:59:22 +1000220 if verbose > 1: print(ex) # Persist with cleaning up
Thomas Woutersa9773292006-04-21 09:43:23 +0000221 try:
222 os.rmdir(top)
Nick Coghlan761bb112012-07-14 23:59:22 +1000223 if verbose > 1: print(" Removed package tree")
Guido van Rossumb940e112007-01-10 16:19:56 +0000224 except OSError as ex:
Nick Coghlan761bb112012-07-14 23:59:22 +1000225 if verbose > 1: print(ex) # Persist with cleaning up
Thomas Woutersa9773292006-04-21 09:43:23 +0000226
Nick Coghlan761bb112012-07-14 23:59:22 +1000227 def _fix_ns_for_legacy_pyc(self, ns, alter_sys):
228 char_to_add = "c" if __debug__ else "o"
229 ns["__file__"] += char_to_add
230 if alter_sys:
231 ns["run_argv0"] += char_to_add
232
233
234 def _check_module(self, depth, alter_sys=False):
Thomas Woutersa9773292006-04-21 09:43:23 +0000235 pkg_dir, mod_fname, mod_name = (
Nick Coghlan761bb112012-07-14 23:59:22 +1000236 self._make_pkg(example_source, depth))
Guido van Rossum04110fb2007-08-24 16:32:05 +0000237 forget(mod_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000238 expected_ns = example_namespace.copy()
239 expected_ns.update({
240 "__name__": mod_name,
241 "__file__": mod_fname,
242 "__package__": mod_name.rpartition(".")[0],
243 })
244 if alter_sys:
245 expected_ns.update({
246 "run_argv0": mod_fname,
247 "run_name_in_sys_modules": True,
248 "module_in_sys_modules": True,
249 })
250 def create_ns(init_globals):
251 return run_module(mod_name, init_globals, alter_sys=alter_sys)
Thomas Woutersa9773292006-04-21 09:43:23 +0000252 try:
Nick Coghlan761bb112012-07-14 23:59:22 +1000253 if verbose > 1: print("Running from source:", mod_name)
254 self.check_code_execution(create_ns, expected_ns)
Thomas Woutersa9773292006-04-21 09:43:23 +0000255 __import__(mod_name)
256 os.remove(mod_fname)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000257 make_legacy_pyc(mod_fname)
Brett Cannon61b14252010-07-03 21:48:25 +0000258 unload(mod_name) # In case loader caches paths
Nick Coghlan761bb112012-07-14 23:59:22 +1000259 if verbose > 1: print("Running from compiled:", mod_name)
260 self._fix_ns_for_legacy_pyc(expected_ns, alter_sys)
261 self.check_code_execution(create_ns, expected_ns)
Thomas Woutersa9773292006-04-21 09:43:23 +0000262 finally:
263 self._del_pkg(pkg_dir, depth, mod_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000264 if verbose > 1: print("Module executed successfully")
Thomas Woutersa9773292006-04-21 09:43:23 +0000265
Nick Coghlan761bb112012-07-14 23:59:22 +1000266 def _check_package(self, depth, alter_sys=False):
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000267 pkg_dir, mod_fname, mod_name = (
Nick Coghlan761bb112012-07-14 23:59:22 +1000268 self._make_pkg(example_source, depth, "__main__"))
269 pkg_name = mod_name.rpartition(".")[0]
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000270 forget(mod_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000271 expected_ns = example_namespace.copy()
272 expected_ns.update({
273 "__name__": mod_name,
274 "__file__": mod_fname,
275 "__package__": pkg_name,
276 })
277 if alter_sys:
278 expected_ns.update({
279 "run_argv0": mod_fname,
280 "run_name_in_sys_modules": True,
281 "module_in_sys_modules": True,
282 })
283 def create_ns(init_globals):
284 return run_module(pkg_name, init_globals, alter_sys=alter_sys)
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000285 try:
Nick Coghlan761bb112012-07-14 23:59:22 +1000286 if verbose > 1: print("Running from source:", pkg_name)
287 self.check_code_execution(create_ns, expected_ns)
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000288 __import__(mod_name)
289 os.remove(mod_fname)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000290 make_legacy_pyc(mod_fname)
Brett Cannon61b14252010-07-03 21:48:25 +0000291 unload(mod_name) # In case loader caches paths
Nick Coghlan761bb112012-07-14 23:59:22 +1000292 if verbose > 1: print("Running from compiled:", pkg_name)
293 self._fix_ns_for_legacy_pyc(expected_ns, alter_sys)
294 self.check_code_execution(create_ns, expected_ns)
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000295 finally:
296 self._del_pkg(pkg_dir, depth, pkg_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000297 if verbose > 1: print("Package executed successfully")
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000298
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000299 def _add_relative_modules(self, base_dir, source, depth):
Guido van Rossum806c2462007-08-06 23:33:07 +0000300 if depth <= 1:
301 raise ValueError("Relative module test needs depth > 1")
302 pkg_name = "__runpy_pkg__"
303 module_dir = base_dir
304 for i in range(depth):
305 parent_dir = module_dir
306 module_dir = os.path.join(module_dir, pkg_name)
307 # Add sibling module
Skip Montanaro7a98be22007-08-16 14:35:24 +0000308 sibling_fname = os.path.join(module_dir, "sibling.py")
Guido van Rossum806c2462007-08-06 23:33:07 +0000309 sibling_file = open(sibling_fname, "w")
310 sibling_file.close()
Nick Coghlan761bb112012-07-14 23:59:22 +1000311 if verbose > 1: print(" Added sibling module:", sibling_fname)
Guido van Rossum806c2462007-08-06 23:33:07 +0000312 # Add nephew module
313 uncle_dir = os.path.join(parent_dir, "uncle")
314 self._add_pkg_dir(uncle_dir)
Nick Coghlan761bb112012-07-14 23:59:22 +1000315 if verbose > 1: print(" Added uncle package:", uncle_dir)
Guido van Rossum806c2462007-08-06 23:33:07 +0000316 cousin_dir = os.path.join(uncle_dir, "cousin")
317 self._add_pkg_dir(cousin_dir)
Nick Coghlan761bb112012-07-14 23:59:22 +1000318 if verbose > 1: print(" Added cousin package:", cousin_dir)
Skip Montanaro7a98be22007-08-16 14:35:24 +0000319 nephew_fname = os.path.join(cousin_dir, "nephew.py")
Guido van Rossum806c2462007-08-06 23:33:07 +0000320 nephew_file = open(nephew_fname, "w")
321 nephew_file.close()
Nick Coghlan761bb112012-07-14 23:59:22 +1000322 if verbose > 1: print(" Added nephew module:", nephew_fname)
Guido van Rossum806c2462007-08-06 23:33:07 +0000323
324 def _check_relative_imports(self, depth, run_name=None):
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000325 contents = r"""\
Guido van Rossum806c2462007-08-06 23:33:07 +0000326from __future__ import absolute_import
327from . import sibling
328from ..uncle.cousin import nephew
329"""
330 pkg_dir, mod_fname, mod_name = (
331 self._make_pkg(contents, depth))
Nick Coghlan761bb112012-07-14 23:59:22 +1000332 if run_name is None:
333 expected_name = mod_name
334 else:
335 expected_name = run_name
Guido van Rossum806c2462007-08-06 23:33:07 +0000336 try:
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000337 self._add_relative_modules(pkg_dir, contents, depth)
338 pkg_name = mod_name.rpartition('.')[0]
Nick Coghlan761bb112012-07-14 23:59:22 +1000339 if verbose > 1: print("Running from source:", mod_name)
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000340 d1 = run_module(mod_name, run_name=run_name) # Read from source
Nick Coghlan761bb112012-07-14 23:59:22 +1000341 self.assertEqual(d1["__name__"], expected_name)
342 self.assertEqual(d1["__package__"], pkg_name)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000343 self.assertIn("sibling", d1)
344 self.assertIn("nephew", d1)
Guido van Rossum806c2462007-08-06 23:33:07 +0000345 del d1 # Ensure __loader__ entry doesn't keep file open
346 __import__(mod_name)
347 os.remove(mod_fname)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000348 make_legacy_pyc(mod_fname)
Brett Cannon61b14252010-07-03 21:48:25 +0000349 unload(mod_name) # In case the loader caches paths
Nick Coghlan761bb112012-07-14 23:59:22 +1000350 if verbose > 1: print("Running from compiled:", mod_name)
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000351 d2 = run_module(mod_name, run_name=run_name) # Read from bytecode
Nick Coghlan761bb112012-07-14 23:59:22 +1000352 self.assertEqual(d2["__name__"], expected_name)
353 self.assertEqual(d2["__package__"], pkg_name)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000354 self.assertIn("sibling", d2)
355 self.assertIn("nephew", d2)
Guido van Rossum806c2462007-08-06 23:33:07 +0000356 del d2 # Ensure __loader__ entry doesn't keep file open
357 finally:
358 self._del_pkg(pkg_dir, depth, mod_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000359 if verbose > 1: print("Module executed successfully")
Guido van Rossum806c2462007-08-06 23:33:07 +0000360
Thomas Woutersa9773292006-04-21 09:43:23 +0000361 def test_run_module(self):
362 for depth in range(4):
Nick Coghlan761bb112012-07-14 23:59:22 +1000363 if verbose > 1: print("Testing package depth:", depth)
Thomas Woutersa9773292006-04-21 09:43:23 +0000364 self._check_module(depth)
365
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000366 def test_run_package(self):
367 for depth in range(1, 4):
Nick Coghlan761bb112012-07-14 23:59:22 +1000368 if verbose > 1: print("Testing package depth:", depth)
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000369 self._check_package(depth)
370
Nick Coghlan761bb112012-07-14 23:59:22 +1000371 def test_run_module_alter_sys(self):
372 for depth in range(4):
373 if verbose > 1: print("Testing package depth:", depth)
374 self._check_module(depth, alter_sys=True)
375
376 def test_run_package_alter_sys(self):
377 for depth in range(1, 4):
378 if verbose > 1: print("Testing package depth:", depth)
379 self._check_package(depth, alter_sys=True)
380
Guido van Rossum806c2462007-08-06 23:33:07 +0000381 def test_explicit_relative_import(self):
382 for depth in range(2, 5):
Nick Coghlan761bb112012-07-14 23:59:22 +1000383 if verbose > 1: print("Testing relative imports at depth:", depth)
Guido van Rossum806c2462007-08-06 23:33:07 +0000384 self._check_relative_imports(depth)
385
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000386 def test_main_relative_import(self):
387 for depth in range(2, 5):
Nick Coghlan761bb112012-07-14 23:59:22 +1000388 if verbose > 1: print("Testing main relative imports at depth:", depth)
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000389 self._check_relative_imports(depth, "__main__")
390
Nick Coghlan761bb112012-07-14 23:59:22 +1000391 def test_run_name(self):
392 depth = 1
393 run_name = "And now for something completely different"
394 pkg_dir, mod_fname, mod_name = (
395 self._make_pkg(example_source, depth))
396 forget(mod_name)
397 expected_ns = example_namespace.copy()
398 expected_ns.update({
399 "__name__": run_name,
400 "__file__": mod_fname,
401 "__package__": mod_name.rpartition(".")[0],
402 })
403 def create_ns(init_globals):
404 return run_module(mod_name, init_globals, run_name)
405 try:
406 self.check_code_execution(create_ns, expected_ns)
407 finally:
408 self._del_pkg(pkg_dir, depth, mod_name)
Thomas Woutersa9773292006-04-21 09:43:23 +0000409
Nick Coghlan761bb112012-07-14 23:59:22 +1000410
411class RunPathTestCase(unittest.TestCase, CodeExecutionMixin):
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000412 """Unit tests for runpy.run_path"""
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000413
414 def _make_test_script(self, script_dir, script_basename, source=None):
415 if source is None:
Nick Coghlan761bb112012-07-14 23:59:22 +1000416 source = example_source
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000417 return make_script(script_dir, script_basename, source)
418
419 def _check_script(self, script_name, expected_name, expected_file,
Nick Coghlan761bb112012-07-14 23:59:22 +1000420 expected_argv0):
421 # First check is without run_name
422 def create_ns(init_globals):
423 return run_path(script_name, init_globals)
424 expected_ns = example_namespace.copy()
425 expected_ns.update({
426 "__name__": expected_name,
427 "__file__": expected_file,
428 "__package__": "",
429 "run_argv0": expected_argv0,
430 "run_name_in_sys_modules": True,
431 "module_in_sys_modules": True,
432 })
433 self.check_code_execution(create_ns, expected_ns)
434 # Second check makes sure run_name works in all cases
435 run_name = "prove.issue15230.is.fixed"
436 def create_ns(init_globals):
437 return run_path(script_name, init_globals, run_name)
438 expected_ns["__name__"] = run_name
439 expected_ns["__package__"] = run_name.rpartition(".")[0]
440 self.check_code_execution(create_ns, expected_ns)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000441
442 def _check_import_error(self, script_name, msg):
Nick Coghlan16eb0fb2009-11-18 11:35:25 +0000443 msg = re.escape(msg)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000444 self.assertRaisesRegex(ImportError, msg, run_path, script_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000445
446 def test_basic_script(self):
447 with temp_dir() as script_dir:
448 mod_name = 'script'
449 script_name = self._make_test_script(script_dir, mod_name)
450 self._check_script(script_name, "<run_path>", script_name,
Nick Coghlan761bb112012-07-14 23:59:22 +1000451 script_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000452
453 def test_script_compiled(self):
454 with temp_dir() as script_dir:
455 mod_name = 'script'
456 script_name = self._make_test_script(script_dir, mod_name)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000457 compiled_name = py_compile.compile(script_name, doraise=True)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000458 os.remove(script_name)
459 self._check_script(compiled_name, "<run_path>", compiled_name,
Nick Coghlan761bb112012-07-14 23:59:22 +1000460 compiled_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000461
462 def test_directory(self):
463 with temp_dir() as script_dir:
464 mod_name = '__main__'
465 script_name = self._make_test_script(script_dir, mod_name)
466 self._check_script(script_dir, "<run_path>", script_name,
Nick Coghlan761bb112012-07-14 23:59:22 +1000467 script_dir)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000468
469 def test_directory_compiled(self):
470 with temp_dir() as script_dir:
471 mod_name = '__main__'
472 script_name = self._make_test_script(script_dir, mod_name)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000473 compiled_name = py_compile.compile(script_name, doraise=True)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000474 os.remove(script_name)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000475 legacy_pyc = make_legacy_pyc(script_name)
476 self._check_script(script_dir, "<run_path>", legacy_pyc,
Nick Coghlan761bb112012-07-14 23:59:22 +1000477 script_dir)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000478
479 def test_directory_error(self):
480 with temp_dir() as script_dir:
481 mod_name = 'not_main'
482 script_name = self._make_test_script(script_dir, mod_name)
483 msg = "can't find '__main__' module in %r" % script_dir
484 self._check_import_error(script_dir, msg)
485
486 def test_zipfile(self):
487 with temp_dir() as script_dir:
488 mod_name = '__main__'
489 script_name = self._make_test_script(script_dir, mod_name)
490 zip_name, fname = make_zip_script(script_dir, 'test_zip', script_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000491 self._check_script(zip_name, "<run_path>", fname, zip_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000492
493 def test_zipfile_compiled(self):
494 with temp_dir() as script_dir:
495 mod_name = '__main__'
496 script_name = self._make_test_script(script_dir, mod_name)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000497 compiled_name = py_compile.compile(script_name, doraise=True)
498 zip_name, fname = make_zip_script(script_dir, 'test_zip',
499 compiled_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000500 self._check_script(zip_name, "<run_path>", fname, zip_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000501
502 def test_zipfile_error(self):
503 with temp_dir() as script_dir:
504 mod_name = 'not_main'
505 script_name = self._make_test_script(script_dir, mod_name)
506 zip_name, fname = make_zip_script(script_dir, 'test_zip', script_name)
507 msg = "can't find '__main__' module in %r" % zip_name
508 self._check_import_error(zip_name, msg)
509
510 def test_main_recursion_error(self):
511 with temp_dir() as script_dir, temp_dir() as dummy_dir:
512 mod_name = '__main__'
513 source = ("import runpy\n"
514 "runpy.run_path(%r)\n") % dummy_dir
515 script_name = self._make_test_script(script_dir, mod_name, source)
516 zip_name, fname = make_zip_script(script_dir, 'test_zip', script_name)
517 msg = "recursion depth exceeded"
Ezio Melottied3a7d22010-12-01 02:32:32 +0000518 self.assertRaisesRegex(RuntimeError, msg, run_path, zip_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000519
Victor Stinner6c471022011-07-04 01:45:39 +0200520 def test_encoding(self):
521 with temp_dir() as script_dir:
522 filename = os.path.join(script_dir, 'script.py')
523 with open(filename, 'w', encoding='latin1') as f:
524 f.write("""
525#coding:latin1
Benjamin Peterson951a9e32012-10-12 11:44:10 -0400526s = "non-ASCII: h\xe9"
Victor Stinner6c471022011-07-04 01:45:39 +0200527""")
528 result = run_path(filename)
Benjamin Peterson951a9e32012-10-12 11:44:10 -0400529 self.assertEqual(result['s'], "non-ASCII: h\xe9")
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000530
531
Thomas Woutersa9773292006-04-21 09:43:23 +0000532def test_main():
Brett Cannon61b14252010-07-03 21:48:25 +0000533 run_unittest(
Nick Coghlan761bb112012-07-14 23:59:22 +1000534 ExecutionLayerTestCase,
535 RunModuleTestCase,
536 RunPathTestCase
Brett Cannon61b14252010-07-03 21:48:25 +0000537 )
Thomas Woutersa9773292006-04-21 09:43:23 +0000538
539if __name__ == "__main__":
540 test_main()