blob: 6f0a840f3bb9d6dbbe5c945191ace39d1dcf8b03 [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)
Ezio Melottic28f6fa2013-03-16 19:48:51 +0200257 if not sys.dont_write_bytecode:
258 make_legacy_pyc(mod_fname)
259 unload(mod_name) # In case loader caches paths
260 if verbose > 1: print("Running from compiled:", mod_name)
261 self._fix_ns_for_legacy_pyc(expected_ns, alter_sys)
262 self.check_code_execution(create_ns, expected_ns)
Thomas Woutersa9773292006-04-21 09:43:23 +0000263 finally:
264 self._del_pkg(pkg_dir, depth, mod_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000265 if verbose > 1: print("Module executed successfully")
Thomas Woutersa9773292006-04-21 09:43:23 +0000266
Nick Coghlan761bb112012-07-14 23:59:22 +1000267 def _check_package(self, depth, alter_sys=False):
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000268 pkg_dir, mod_fname, mod_name = (
Nick Coghlan761bb112012-07-14 23:59:22 +1000269 self._make_pkg(example_source, depth, "__main__"))
270 pkg_name = mod_name.rpartition(".")[0]
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000271 forget(mod_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000272 expected_ns = example_namespace.copy()
273 expected_ns.update({
274 "__name__": mod_name,
275 "__file__": mod_fname,
276 "__package__": pkg_name,
277 })
278 if alter_sys:
279 expected_ns.update({
280 "run_argv0": mod_fname,
281 "run_name_in_sys_modules": True,
282 "module_in_sys_modules": True,
283 })
284 def create_ns(init_globals):
285 return run_module(pkg_name, init_globals, alter_sys=alter_sys)
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000286 try:
Nick Coghlan761bb112012-07-14 23:59:22 +1000287 if verbose > 1: print("Running from source:", pkg_name)
288 self.check_code_execution(create_ns, expected_ns)
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000289 __import__(mod_name)
290 os.remove(mod_fname)
Ezio Melottic28f6fa2013-03-16 19:48:51 +0200291 if not sys.dont_write_bytecode:
292 make_legacy_pyc(mod_fname)
293 unload(mod_name) # In case loader caches paths
294 if verbose > 1: print("Running from compiled:", pkg_name)
295 self._fix_ns_for_legacy_pyc(expected_ns, alter_sys)
296 self.check_code_execution(create_ns, expected_ns)
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000297 finally:
298 self._del_pkg(pkg_dir, depth, pkg_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000299 if verbose > 1: print("Package executed successfully")
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000300
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000301 def _add_relative_modules(self, base_dir, source, depth):
Guido van Rossum806c2462007-08-06 23:33:07 +0000302 if depth <= 1:
303 raise ValueError("Relative module test needs depth > 1")
304 pkg_name = "__runpy_pkg__"
305 module_dir = base_dir
306 for i in range(depth):
307 parent_dir = module_dir
308 module_dir = os.path.join(module_dir, pkg_name)
309 # Add sibling module
Skip Montanaro7a98be22007-08-16 14:35:24 +0000310 sibling_fname = os.path.join(module_dir, "sibling.py")
Guido van Rossum806c2462007-08-06 23:33:07 +0000311 sibling_file = open(sibling_fname, "w")
312 sibling_file.close()
Nick Coghlan761bb112012-07-14 23:59:22 +1000313 if verbose > 1: print(" Added sibling module:", sibling_fname)
Guido van Rossum806c2462007-08-06 23:33:07 +0000314 # Add nephew module
315 uncle_dir = os.path.join(parent_dir, "uncle")
316 self._add_pkg_dir(uncle_dir)
Nick Coghlan761bb112012-07-14 23:59:22 +1000317 if verbose > 1: print(" Added uncle package:", uncle_dir)
Guido van Rossum806c2462007-08-06 23:33:07 +0000318 cousin_dir = os.path.join(uncle_dir, "cousin")
319 self._add_pkg_dir(cousin_dir)
Nick Coghlan761bb112012-07-14 23:59:22 +1000320 if verbose > 1: print(" Added cousin package:", cousin_dir)
Skip Montanaro7a98be22007-08-16 14:35:24 +0000321 nephew_fname = os.path.join(cousin_dir, "nephew.py")
Guido van Rossum806c2462007-08-06 23:33:07 +0000322 nephew_file = open(nephew_fname, "w")
323 nephew_file.close()
Nick Coghlan761bb112012-07-14 23:59:22 +1000324 if verbose > 1: print(" Added nephew module:", nephew_fname)
Guido van Rossum806c2462007-08-06 23:33:07 +0000325
326 def _check_relative_imports(self, depth, run_name=None):
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000327 contents = r"""\
Guido van Rossum806c2462007-08-06 23:33:07 +0000328from __future__ import absolute_import
329from . import sibling
330from ..uncle.cousin import nephew
331"""
332 pkg_dir, mod_fname, mod_name = (
333 self._make_pkg(contents, depth))
Nick Coghlan761bb112012-07-14 23:59:22 +1000334 if run_name is None:
335 expected_name = mod_name
336 else:
337 expected_name = run_name
Guido van Rossum806c2462007-08-06 23:33:07 +0000338 try:
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000339 self._add_relative_modules(pkg_dir, contents, depth)
340 pkg_name = mod_name.rpartition('.')[0]
Nick Coghlan761bb112012-07-14 23:59:22 +1000341 if verbose > 1: print("Running from source:", mod_name)
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000342 d1 = run_module(mod_name, run_name=run_name) # Read from source
Nick Coghlan761bb112012-07-14 23:59:22 +1000343 self.assertEqual(d1["__name__"], expected_name)
344 self.assertEqual(d1["__package__"], pkg_name)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000345 self.assertIn("sibling", d1)
346 self.assertIn("nephew", d1)
Guido van Rossum806c2462007-08-06 23:33:07 +0000347 del d1 # Ensure __loader__ entry doesn't keep file open
348 __import__(mod_name)
349 os.remove(mod_fname)
Ezio Melottic28f6fa2013-03-16 19:48:51 +0200350 if not sys.dont_write_bytecode:
351 make_legacy_pyc(mod_fname)
352 unload(mod_name) # In case the loader caches paths
353 if verbose > 1: print("Running from compiled:", mod_name)
354 d2 = run_module(mod_name, run_name=run_name) # Read from bytecode
355 self.assertEqual(d2["__name__"], expected_name)
356 self.assertEqual(d2["__package__"], pkg_name)
357 self.assertIn("sibling", d2)
358 self.assertIn("nephew", d2)
359 del d2 # Ensure __loader__ entry doesn't keep file open
Guido van Rossum806c2462007-08-06 23:33:07 +0000360 finally:
361 self._del_pkg(pkg_dir, depth, mod_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000362 if verbose > 1: print("Module executed successfully")
Guido van Rossum806c2462007-08-06 23:33:07 +0000363
Thomas Woutersa9773292006-04-21 09:43:23 +0000364 def test_run_module(self):
365 for depth in range(4):
Nick Coghlan761bb112012-07-14 23:59:22 +1000366 if verbose > 1: print("Testing package depth:", depth)
Thomas Woutersa9773292006-04-21 09:43:23 +0000367 self._check_module(depth)
368
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000369 def test_run_package(self):
370 for depth in range(1, 4):
Nick Coghlan761bb112012-07-14 23:59:22 +1000371 if verbose > 1: print("Testing package depth:", depth)
Benjamin Petersonf6489f92009-11-25 17:46:26 +0000372 self._check_package(depth)
373
Nick Coghlan761bb112012-07-14 23:59:22 +1000374 def test_run_module_alter_sys(self):
375 for depth in range(4):
376 if verbose > 1: print("Testing package depth:", depth)
377 self._check_module(depth, alter_sys=True)
378
379 def test_run_package_alter_sys(self):
380 for depth in range(1, 4):
381 if verbose > 1: print("Testing package depth:", depth)
382 self._check_package(depth, alter_sys=True)
383
Guido van Rossum806c2462007-08-06 23:33:07 +0000384 def test_explicit_relative_import(self):
385 for depth in range(2, 5):
Nick Coghlan761bb112012-07-14 23:59:22 +1000386 if verbose > 1: print("Testing relative imports at depth:", depth)
Guido van Rossum806c2462007-08-06 23:33:07 +0000387 self._check_relative_imports(depth)
388
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000389 def test_main_relative_import(self):
390 for depth in range(2, 5):
Nick Coghlan761bb112012-07-14 23:59:22 +1000391 if verbose > 1: print("Testing main relative imports at depth:", depth)
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000392 self._check_relative_imports(depth, "__main__")
393
Nick Coghlan761bb112012-07-14 23:59:22 +1000394 def test_run_name(self):
395 depth = 1
396 run_name = "And now for something completely different"
397 pkg_dir, mod_fname, mod_name = (
398 self._make_pkg(example_source, depth))
399 forget(mod_name)
400 expected_ns = example_namespace.copy()
401 expected_ns.update({
402 "__name__": run_name,
403 "__file__": mod_fname,
404 "__package__": mod_name.rpartition(".")[0],
405 })
406 def create_ns(init_globals):
407 return run_module(mod_name, init_globals, run_name)
408 try:
409 self.check_code_execution(create_ns, expected_ns)
410 finally:
411 self._del_pkg(pkg_dir, depth, mod_name)
Thomas Woutersa9773292006-04-21 09:43:23 +0000412
Nick Coghlan761bb112012-07-14 23:59:22 +1000413
414class RunPathTestCase(unittest.TestCase, CodeExecutionMixin):
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000415 """Unit tests for runpy.run_path"""
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000416
417 def _make_test_script(self, script_dir, script_basename, source=None):
418 if source is None:
Nick Coghlan761bb112012-07-14 23:59:22 +1000419 source = example_source
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000420 return make_script(script_dir, script_basename, source)
421
422 def _check_script(self, script_name, expected_name, expected_file,
Nick Coghlan761bb112012-07-14 23:59:22 +1000423 expected_argv0):
424 # First check is without run_name
425 def create_ns(init_globals):
426 return run_path(script_name, init_globals)
427 expected_ns = example_namespace.copy()
428 expected_ns.update({
429 "__name__": expected_name,
430 "__file__": expected_file,
431 "__package__": "",
432 "run_argv0": expected_argv0,
433 "run_name_in_sys_modules": True,
434 "module_in_sys_modules": True,
435 })
436 self.check_code_execution(create_ns, expected_ns)
437 # Second check makes sure run_name works in all cases
438 run_name = "prove.issue15230.is.fixed"
439 def create_ns(init_globals):
440 return run_path(script_name, init_globals, run_name)
441 expected_ns["__name__"] = run_name
442 expected_ns["__package__"] = run_name.rpartition(".")[0]
443 self.check_code_execution(create_ns, expected_ns)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000444
445 def _check_import_error(self, script_name, msg):
Nick Coghlan16eb0fb2009-11-18 11:35:25 +0000446 msg = re.escape(msg)
Ezio Melottied3a7d22010-12-01 02:32:32 +0000447 self.assertRaisesRegex(ImportError, msg, run_path, script_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000448
449 def test_basic_script(self):
450 with temp_dir() as script_dir:
451 mod_name = 'script'
452 script_name = self._make_test_script(script_dir, mod_name)
453 self._check_script(script_name, "<run_path>", script_name,
Nick Coghlan761bb112012-07-14 23:59:22 +1000454 script_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000455
456 def test_script_compiled(self):
457 with temp_dir() as script_dir:
458 mod_name = 'script'
459 script_name = self._make_test_script(script_dir, mod_name)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000460 compiled_name = py_compile.compile(script_name, doraise=True)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000461 os.remove(script_name)
462 self._check_script(compiled_name, "<run_path>", compiled_name,
Nick Coghlan761bb112012-07-14 23:59:22 +1000463 compiled_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000464
465 def test_directory(self):
466 with temp_dir() as script_dir:
467 mod_name = '__main__'
468 script_name = self._make_test_script(script_dir, mod_name)
469 self._check_script(script_dir, "<run_path>", script_name,
Nick Coghlan761bb112012-07-14 23:59:22 +1000470 script_dir)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000471
472 def test_directory_compiled(self):
473 with temp_dir() as script_dir:
474 mod_name = '__main__'
475 script_name = self._make_test_script(script_dir, mod_name)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000476 compiled_name = py_compile.compile(script_name, doraise=True)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000477 os.remove(script_name)
Ezio Melottic28f6fa2013-03-16 19:48:51 +0200478 if not sys.dont_write_bytecode:
479 legacy_pyc = make_legacy_pyc(script_name)
480 self._check_script(script_dir, "<run_path>", legacy_pyc,
481 script_dir)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000482
483 def test_directory_error(self):
484 with temp_dir() as script_dir:
485 mod_name = 'not_main'
486 script_name = self._make_test_script(script_dir, mod_name)
487 msg = "can't find '__main__' module in %r" % script_dir
488 self._check_import_error(script_dir, msg)
489
490 def test_zipfile(self):
491 with temp_dir() as script_dir:
492 mod_name = '__main__'
493 script_name = self._make_test_script(script_dir, mod_name)
494 zip_name, fname = make_zip_script(script_dir, 'test_zip', script_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000495 self._check_script(zip_name, "<run_path>", fname, zip_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000496
497 def test_zipfile_compiled(self):
498 with temp_dir() as script_dir:
499 mod_name = '__main__'
500 script_name = self._make_test_script(script_dir, mod_name)
Barry Warsaw28a691b2010-04-17 00:19:56 +0000501 compiled_name = py_compile.compile(script_name, doraise=True)
502 zip_name, fname = make_zip_script(script_dir, 'test_zip',
503 compiled_name)
Nick Coghlan761bb112012-07-14 23:59:22 +1000504 self._check_script(zip_name, "<run_path>", fname, zip_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000505
506 def test_zipfile_error(self):
507 with temp_dir() as script_dir:
508 mod_name = 'not_main'
509 script_name = self._make_test_script(script_dir, mod_name)
510 zip_name, fname = make_zip_script(script_dir, 'test_zip', script_name)
511 msg = "can't find '__main__' module in %r" % zip_name
512 self._check_import_error(zip_name, msg)
513
514 def test_main_recursion_error(self):
515 with temp_dir() as script_dir, temp_dir() as dummy_dir:
516 mod_name = '__main__'
517 source = ("import runpy\n"
518 "runpy.run_path(%r)\n") % dummy_dir
519 script_name = self._make_test_script(script_dir, mod_name, source)
520 zip_name, fname = make_zip_script(script_dir, 'test_zip', script_name)
521 msg = "recursion depth exceeded"
Ezio Melottied3a7d22010-12-01 02:32:32 +0000522 self.assertRaisesRegex(RuntimeError, msg, run_path, zip_name)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000523
Victor Stinner6c471022011-07-04 01:45:39 +0200524 def test_encoding(self):
525 with temp_dir() as script_dir:
526 filename = os.path.join(script_dir, 'script.py')
527 with open(filename, 'w', encoding='latin1') as f:
528 f.write("""
529#coding:latin1
Benjamin Peterson951a9e32012-10-12 11:44:10 -0400530s = "non-ASCII: h\xe9"
Victor Stinner6c471022011-07-04 01:45:39 +0200531""")
532 result = run_path(filename)
Benjamin Peterson951a9e32012-10-12 11:44:10 -0400533 self.assertEqual(result['s'], "non-ASCII: h\xe9")
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000534
535
Thomas Woutersa9773292006-04-21 09:43:23 +0000536def test_main():
Brett Cannon61b14252010-07-03 21:48:25 +0000537 run_unittest(
Nick Coghlan761bb112012-07-14 23:59:22 +1000538 ExecutionLayerTestCase,
539 RunModuleTestCase,
540 RunPathTestCase
Brett Cannon61b14252010-07-03 21:48:25 +0000541 )
Thomas Woutersa9773292006-04-21 09:43:23 +0000542
543if __name__ == "__main__":
544 test_main()