blob: f0bd013e55367240e117a30872bcb7ca0e0ecae0 [file] [log] [blame]
Barry Warsaw28a691b2010-04-17 00:19:56 +00001# tests command line execution of scripts
Christian Heimes9cd17752007-11-18 19:35:23 +00002
Antoine Pitrou9845c7e2014-05-11 13:42:17 +02003import contextlib
Brett Cannone0d88a12012-04-25 20:54:04 -04004import importlib
Nick Coghlan85e729e2012-07-15 18:09:52 +10005import importlib.machinery
6import zipimport
Christian Heimes9cd17752007-11-18 19:35:23 +00007import unittest
Georg Brandlf5247e32010-10-14 08:08:56 +00008import sys
Christian Heimes9cd17752007-11-18 19:35:23 +00009import os
10import os.path
Barry Warsaw28a691b2010-04-17 00:19:56 +000011import py_compile
Antoine Pitrou9845c7e2014-05-11 13:42:17 +020012import subprocess
Martin Panterca3263c2016-12-11 00:18:36 +000013import io
Barry Warsaw28a691b2010-04-17 00:19:56 +000014
Nick Coghlan1d5ccdb2012-05-21 23:03:30 +100015import textwrap
Nick Coghland26c18a2010-08-17 13:06:11 +000016from test import support
Berker Peksagce643912015-05-06 06:33:17 +030017from test.support.script_helper import (
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000018 make_pkg, make_script, make_zip_pkg, make_zip_script,
Berker Peksagce643912015-05-06 06:33:17 +030019 assert_python_ok, assert_python_failure, spawn_python, kill_python)
Christian Heimes9cd17752007-11-18 19:35:23 +000020
Nick Coghland26c18a2010-08-17 13:06:11 +000021verbose = support.verbose
Christian Heimes9cd17752007-11-18 19:35:23 +000022
Nick Coghlan37fc4012012-04-22 17:11:33 +100023example_args = ['test1', 'test2', 'test3']
24
Christian Heimescbf3b5c2007-12-03 21:02:03 +000025test_source = """\
Christian Heimes9cd17752007-11-18 19:35:23 +000026# Script may be run with optimisation enabled, so don't rely on assert
27# statements being executed
28def assertEqual(lhs, rhs):
29 if lhs != rhs:
Christian Heimescbf3b5c2007-12-03 21:02:03 +000030 raise AssertionError('%r != %r' % (lhs, rhs))
Christian Heimes9cd17752007-11-18 19:35:23 +000031def assertIdentical(lhs, rhs):
32 if lhs is not rhs:
Christian Heimescbf3b5c2007-12-03 21:02:03 +000033 raise AssertionError('%r is not %r' % (lhs, rhs))
Christian Heimes9cd17752007-11-18 19:35:23 +000034# Check basic code execution
35result = ['Top level assignment']
36def f():
37 result.append('Lower level reference')
38f()
39assertEqual(result, ['Top level assignment', 'Lower level reference'])
40# Check population of magic variables
41assertEqual(__name__, '__main__')
Nick Coghlan3f94cbf2012-07-15 19:10:39 +100042from importlib.machinery import BuiltinImporter
43_loader = __loader__ if __loader__ is BuiltinImporter else type(__loader__)
Nick Coghlan85e729e2012-07-15 18:09:52 +100044print('__loader__==%a' % _loader)
Victor Stinnere3874ed2010-10-17 01:41:09 +000045print('__file__==%a' % __file__)
Nick Coghlan720c7e22013-12-15 20:33:02 +100046print('__cached__==%a' % __cached__)
Christian Heimescbf3b5c2007-12-03 21:02:03 +000047print('__package__==%r' % __package__)
Nick Coghlan720c7e22013-12-15 20:33:02 +100048# Check PEP 451 details
49import os.path
50if __package__ is not None:
51 print('__main__ was located through the import system')
52 assertIdentical(__spec__.loader, __loader__)
53 expected_spec_name = os.path.splitext(os.path.basename(__file__))[0]
54 if __package__:
55 expected_spec_name = __package__ + "." + expected_spec_name
56 assertEqual(__spec__.name, expected_spec_name)
57 assertEqual(__spec__.parent, __package__)
58 assertIdentical(__spec__.submodule_search_locations, None)
59 assertEqual(__spec__.origin, __file__)
60 if __spec__.cached is not None:
61 assertEqual(__spec__.cached, __cached__)
Christian Heimes9cd17752007-11-18 19:35:23 +000062# Check the sys module
63import sys
64assertIdentical(globals(), sys.modules[__name__].__dict__)
Nick Coghlan720c7e22013-12-15 20:33:02 +100065if __spec__ is not None:
66 # XXX: We're not currently making __main__ available under its real name
67 pass # assertIdentical(globals(), sys.modules[__spec__.name].__dict__)
Nick Coghlan37fc4012012-04-22 17:11:33 +100068from test import test_cmd_line_script
69example_args_list = test_cmd_line_script.example_args
70assertEqual(sys.argv[1:], example_args_list)
Victor Stinnere3874ed2010-10-17 01:41:09 +000071print('sys.argv[0]==%a' % sys.argv[0])
72print('sys.path[0]==%a' % sys.path[0])
Nick Coghland26c18a2010-08-17 13:06:11 +000073# Check the working directory
74import os
Victor Stinnere3874ed2010-10-17 01:41:09 +000075print('cwd==%a' % os.getcwd())
Christian Heimescbf3b5c2007-12-03 21:02:03 +000076"""
Christian Heimes9cd17752007-11-18 19:35:23 +000077
Christian Heimescbf3b5c2007-12-03 21:02:03 +000078def _make_test_script(script_dir, script_basename, source=test_source):
Brett Cannone0d88a12012-04-25 20:54:04 -040079 to_return = make_script(script_dir, script_basename, source)
80 importlib.invalidate_caches()
81 return to_return
Christian Heimescbf3b5c2007-12-03 21:02:03 +000082
Nick Coghlanf088e5e2008-12-14 11:50:48 +000083def _make_test_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
84 source=test_source, depth=1):
Brett Cannone0d88a12012-04-25 20:54:04 -040085 to_return = make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
86 source, depth)
87 importlib.invalidate_caches()
88 return to_return
Nick Coghlanf088e5e2008-12-14 11:50:48 +000089
Christian Heimes9cd17752007-11-18 19:35:23 +000090class CmdLineTest(unittest.TestCase):
Nick Coghland26c18a2010-08-17 13:06:11 +000091 def _check_output(self, script_name, exit_code, data,
92 expected_file, expected_argv0,
Nick Coghlan85e729e2012-07-15 18:09:52 +100093 expected_path0, expected_package,
Nick Coghland5d9e022018-03-25 23:03:10 +100094 expected_loader, expected_cwd=None):
Nick Coghland26c18a2010-08-17 13:06:11 +000095 if verbose > 1:
Guido van Rossum87c0f1d2007-11-19 18:03:44 +000096 print("Output from test script %r:" % script_name)
Serhiy Storchakab0749ca2015-03-25 01:33:19 +020097 print(repr(data))
Christian Heimescbf3b5c2007-12-03 21:02:03 +000098 self.assertEqual(exit_code, 0)
Nick Coghlan85e729e2012-07-15 18:09:52 +100099 printed_loader = '__loader__==%a' % expected_loader
Victor Stinnere3874ed2010-10-17 01:41:09 +0000100 printed_file = '__file__==%a' % expected_file
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000101 printed_package = '__package__==%r' % expected_package
Victor Stinnere3874ed2010-10-17 01:41:09 +0000102 printed_argv0 = 'sys.argv[0]==%a' % expected_argv0
103 printed_path0 = 'sys.path[0]==%a' % expected_path0
Nick Coghland5d9e022018-03-25 23:03:10 +1000104 if expected_cwd is None:
105 expected_cwd = os.getcwd()
106 printed_cwd = 'cwd==%a' % expected_cwd
Nick Coghland26c18a2010-08-17 13:06:11 +0000107 if verbose > 1:
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000108 print('Expected output:')
109 print(printed_file)
110 print(printed_package)
111 print(printed_argv0)
Nick Coghland26c18a2010-08-17 13:06:11 +0000112 print(printed_cwd)
Benjamin Petersonab078e92016-07-13 21:13:29 -0700113 self.assertIn(printed_loader.encode('utf-8'), data)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000114 self.assertIn(printed_file.encode('utf-8'), data)
115 self.assertIn(printed_package.encode('utf-8'), data)
116 self.assertIn(printed_argv0.encode('utf-8'), data)
Nick Coghland26c18a2010-08-17 13:06:11 +0000117 self.assertIn(printed_path0.encode('utf-8'), data)
118 self.assertIn(printed_cwd.encode('utf-8'), data)
119
Nick Coghland5d9e022018-03-25 23:03:10 +1000120 def _check_script(self, script_exec_args, expected_file,
Nick Coghland26c18a2010-08-17 13:06:11 +0000121 expected_argv0, expected_path0,
Nick Coghlan85e729e2012-07-15 18:09:52 +1000122 expected_package, expected_loader,
Nick Coghland5d9e022018-03-25 23:03:10 +1000123 *cmd_line_switches, cwd=None, **env_vars):
124 if isinstance(script_exec_args, str):
125 script_exec_args = [script_exec_args]
Victor Stinner9def2842016-01-18 12:15:08 +0100126 run_args = [*support.optim_args_from_interpreter_flags(),
Nick Coghland5d9e022018-03-25 23:03:10 +1000127 *cmd_line_switches, *script_exec_args, *example_args]
Nick Coghland5d9e022018-03-25 23:03:10 +1000128 rc, out, err = assert_python_ok(
129 *run_args, __isolated=False, __cwd=cwd, **env_vars
130 )
131 self._check_output(script_exec_args, rc, out + err, expected_file,
Nick Coghlan85e729e2012-07-15 18:09:52 +1000132 expected_argv0, expected_path0,
Nick Coghland5d9e022018-03-25 23:03:10 +1000133 expected_package, expected_loader, cwd)
Christian Heimes9cd17752007-11-18 19:35:23 +0000134
Nick Coghland5d9e022018-03-25 23:03:10 +1000135 def _check_import_error(self, script_exec_args, expected_msg,
136 *cmd_line_switches, cwd=None, **env_vars):
137 if isinstance(script_exec_args, str):
138 script_exec_args = (script_exec_args,)
139 else:
140 script_exec_args = tuple(script_exec_args)
141 run_args = cmd_line_switches + script_exec_args
142 rc, out, err = assert_python_failure(
143 *run_args, __isolated=False, __cwd=cwd, **env_vars
144 )
Nick Coghland26c18a2010-08-17 13:06:11 +0000145 if verbose > 1:
Nick Coghland5d9e022018-03-25 23:03:10 +1000146 print('Output from test script %r:' % script_exec_args)
Serhiy Storchakab0749ca2015-03-25 01:33:19 +0200147 print(repr(err))
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000148 print('Expected output: %r' % expected_msg)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000149 self.assertIn(expected_msg.encode('utf-8'), err)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000150
Nick Coghlan85e729e2012-07-15 18:09:52 +1000151 def test_dash_c_loader(self):
152 rc, out, err = assert_python_ok("-c", "print(__loader__)")
153 expected = repr(importlib.machinery.BuiltinImporter).encode("utf-8")
154 self.assertIn(expected, out)
155
156 def test_stdin_loader(self):
Nick Coghlan37b3b902012-07-15 18:24:42 +1000157 # Unfortunately, there's no way to automatically test the fully
158 # interactive REPL, since that code path only gets executed when
Nick Coghlan8e6e7d32012-07-15 23:13:18 +1000159 # stdin is an interactive tty.
Nick Coghlan85e729e2012-07-15 18:09:52 +1000160 p = spawn_python()
161 try:
162 p.stdin.write(b"print(__loader__)\n")
163 p.stdin.flush()
164 finally:
165 out = kill_python(p)
166 expected = repr(importlib.machinery.BuiltinImporter).encode("utf-8")
167 self.assertIn(expected, out)
168
Antoine Pitrou9845c7e2014-05-11 13:42:17 +0200169 @contextlib.contextmanager
170 def interactive_python(self, separate_stderr=False):
171 if separate_stderr:
Alexey Izbysheva2670562018-10-20 03:22:31 +0300172 p = spawn_python('-i', stderr=subprocess.PIPE)
Antoine Pitrou9845c7e2014-05-11 13:42:17 +0200173 stderr = p.stderr
174 else:
Alexey Izbysheva2670562018-10-20 03:22:31 +0300175 p = spawn_python('-i', stderr=subprocess.STDOUT)
Antoine Pitrou9845c7e2014-05-11 13:42:17 +0200176 stderr = p.stdout
177 try:
178 # Drain stderr until prompt
179 while True:
180 data = stderr.read(4)
181 if data == b">>> ":
182 break
183 stderr.readline()
184 yield p
185 finally:
186 kill_python(p)
187 stderr.close()
188
189 def check_repl_stdout_flush(self, separate_stderr=False):
190 with self.interactive_python(separate_stderr) as p:
191 p.stdin.write(b"print('foo')\n")
192 p.stdin.flush()
193 self.assertEqual(b'foo', p.stdout.readline().strip())
194
195 def check_repl_stderr_flush(self, separate_stderr=False):
196 with self.interactive_python(separate_stderr) as p:
197 p.stdin.write(b"1/0\n")
198 p.stdin.flush()
199 stderr = p.stderr if separate_stderr else p.stdout
200 self.assertIn(b'Traceback ', stderr.readline())
201 self.assertIn(b'File "<stdin>"', stderr.readline())
202 self.assertIn(b'ZeroDivisionError', stderr.readline())
203
204 def test_repl_stdout_flush(self):
205 self.check_repl_stdout_flush()
206
207 def test_repl_stdout_flush_separate_stderr(self):
208 self.check_repl_stdout_flush(True)
209
210 def test_repl_stderr_flush(self):
211 self.check_repl_stderr_flush()
212
213 def test_repl_stderr_flush_separate_stderr(self):
214 self.check_repl_stderr_flush(True)
215
Christian Heimes9cd17752007-11-18 19:35:23 +0000216 def test_basic_script(self):
Berker Peksagce643912015-05-06 06:33:17 +0300217 with support.temp_dir() as script_dir:
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000218 script_name = _make_test_script(script_dir, 'script')
Nick Coghland26c18a2010-08-17 13:06:11 +0000219 self._check_script(script_name, script_name, script_name,
Nick Coghlan85e729e2012-07-15 18:09:52 +1000220 script_dir, None,
221 importlib.machinery.SourceFileLoader)
Christian Heimes9cd17752007-11-18 19:35:23 +0000222
223 def test_script_compiled(self):
Berker Peksagce643912015-05-06 06:33:17 +0300224 with support.temp_dir() as script_dir:
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000225 script_name = _make_test_script(script_dir, 'script')
Nick Coghland26c18a2010-08-17 13:06:11 +0000226 py_compile.compile(script_name, doraise=True)
Christian Heimes9cd17752007-11-18 19:35:23 +0000227 os.remove(script_name)
Nick Coghland26c18a2010-08-17 13:06:11 +0000228 pyc_file = support.make_legacy_pyc(script_name)
229 self._check_script(pyc_file, pyc_file,
Nick Coghlan85e729e2012-07-15 18:09:52 +1000230 pyc_file, script_dir, None,
231 importlib.machinery.SourcelessFileLoader)
Christian Heimes9cd17752007-11-18 19:35:23 +0000232
233 def test_directory(self):
Berker Peksagce643912015-05-06 06:33:17 +0300234 with support.temp_dir() as script_dir:
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000235 script_name = _make_test_script(script_dir, '__main__')
Nick Coghland26c18a2010-08-17 13:06:11 +0000236 self._check_script(script_dir, script_name, script_dir,
Nick Coghlan85e729e2012-07-15 18:09:52 +1000237 script_dir, '',
238 importlib.machinery.SourceFileLoader)
Christian Heimes9cd17752007-11-18 19:35:23 +0000239
240 def test_directory_compiled(self):
Berker Peksagce643912015-05-06 06:33:17 +0300241 with support.temp_dir() as script_dir:
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000242 script_name = _make_test_script(script_dir, '__main__')
Nick Coghland26c18a2010-08-17 13:06:11 +0000243 py_compile.compile(script_name, doraise=True)
Christian Heimes9cd17752007-11-18 19:35:23 +0000244 os.remove(script_name)
Nick Coghland26c18a2010-08-17 13:06:11 +0000245 pyc_file = support.make_legacy_pyc(script_name)
246 self._check_script(script_dir, pyc_file, script_dir,
Nick Coghlan85e729e2012-07-15 18:09:52 +1000247 script_dir, '',
248 importlib.machinery.SourcelessFileLoader)
Christian Heimes9cd17752007-11-18 19:35:23 +0000249
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000250 def test_directory_error(self):
Berker Peksagce643912015-05-06 06:33:17 +0300251 with support.temp_dir() as script_dir:
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000252 msg = "can't find '__main__' module in %r" % script_dir
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000253 self._check_import_error(script_dir, msg)
254
Christian Heimes9cd17752007-11-18 19:35:23 +0000255 def test_zipfile(self):
Berker Peksagce643912015-05-06 06:33:17 +0300256 with support.temp_dir() as script_dir:
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000257 script_name = _make_test_script(script_dir, '__main__')
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000258 zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name)
Nick Coghlan85e729e2012-07-15 18:09:52 +1000259 self._check_script(zip_name, run_name, zip_name, zip_name, '',
260 zipimport.zipimporter)
Christian Heimes9cd17752007-11-18 19:35:23 +0000261
Elvis Pranskevichusa6e956b2018-11-07 13:34:59 -0500262 def test_zipfile_compiled_timestamp(self):
Berker Peksagce643912015-05-06 06:33:17 +0300263 with support.temp_dir() as script_dir:
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000264 script_name = _make_test_script(script_dir, '__main__')
Elvis Pranskevichusa6e956b2018-11-07 13:34:59 -0500265 compiled_name = py_compile.compile(
266 script_name, doraise=True,
267 invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP)
268 zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name)
269 self._check_script(zip_name, run_name, zip_name, zip_name, '',
270 zipimport.zipimporter)
271
272 def test_zipfile_compiled_checked_hash(self):
273 with support.temp_dir() as script_dir:
274 script_name = _make_test_script(script_dir, '__main__')
275 compiled_name = py_compile.compile(
276 script_name, doraise=True,
277 invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH)
278 zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name)
279 self._check_script(zip_name, run_name, zip_name, zip_name, '',
280 zipimport.zipimporter)
281
282 def test_zipfile_compiled_unchecked_hash(self):
283 with support.temp_dir() as script_dir:
284 script_name = _make_test_script(script_dir, '__main__')
285 compiled_name = py_compile.compile(
286 script_name, doraise=True,
287 invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH)
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000288 zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name)
Nick Coghlan85e729e2012-07-15 18:09:52 +1000289 self._check_script(zip_name, run_name, zip_name, zip_name, '',
290 zipimport.zipimporter)
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000291
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000292 def test_zipfile_error(self):
Berker Peksagce643912015-05-06 06:33:17 +0300293 with support.temp_dir() as script_dir:
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000294 script_name = _make_test_script(script_dir, 'not_main')
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000295 zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name)
296 msg = "can't find '__main__' module in %r" % zip_name
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000297 self._check_import_error(zip_name, msg)
298
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000299 def test_module_in_package(self):
Berker Peksagce643912015-05-06 06:33:17 +0300300 with support.temp_dir() as script_dir:
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000301 pkg_dir = os.path.join(script_dir, 'test_pkg')
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000302 make_pkg(pkg_dir)
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000303 script_name = _make_test_script(pkg_dir, 'script')
Nick Coghland5d9e022018-03-25 23:03:10 +1000304 self._check_script(["-m", "test_pkg.script"], script_name, script_name,
Nick Coghlan85e729e2012-07-15 18:09:52 +1000305 script_dir, 'test_pkg',
Nick Coghland5d9e022018-03-25 23:03:10 +1000306 importlib.machinery.SourceFileLoader,
307 cwd=script_dir)
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000308
309 def test_module_in_package_in_zipfile(self):
Berker Peksagce643912015-05-06 06:33:17 +0300310 with support.temp_dir() as script_dir:
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000311 zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script')
Nick Coghland5d9e022018-03-25 23:03:10 +1000312 self._check_script(["-m", "test_pkg.script"], run_name, run_name,
313 script_dir, 'test_pkg', zipimport.zipimporter,
314 PYTHONPATH=zip_name, cwd=script_dir)
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000315
316 def test_module_in_subpackage_in_zipfile(self):
Berker Peksagce643912015-05-06 06:33:17 +0300317 with support.temp_dir() as script_dir:
Nick Coghlanf088e5e2008-12-14 11:50:48 +0000318 zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script', depth=2)
Nick Coghland5d9e022018-03-25 23:03:10 +1000319 self._check_script(["-m", "test_pkg.test_pkg.script"], run_name, run_name,
320 script_dir, 'test_pkg.test_pkg',
321 zipimport.zipimporter,
322 PYTHONPATH=zip_name, cwd=script_dir)
Christian Heimes9cd17752007-11-18 19:35:23 +0000323
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000324 def test_package(self):
Berker Peksagce643912015-05-06 06:33:17 +0300325 with support.temp_dir() as script_dir:
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000326 pkg_dir = os.path.join(script_dir, 'test_pkg')
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000327 make_pkg(pkg_dir)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000328 script_name = _make_test_script(pkg_dir, '__main__')
Nick Coghland5d9e022018-03-25 23:03:10 +1000329 self._check_script(["-m", "test_pkg"], script_name,
Nick Coghlan85e729e2012-07-15 18:09:52 +1000330 script_name, script_dir, 'test_pkg',
Nick Coghland5d9e022018-03-25 23:03:10 +1000331 importlib.machinery.SourceFileLoader,
332 cwd=script_dir)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000333
334 def test_package_compiled(self):
Berker Peksagce643912015-05-06 06:33:17 +0300335 with support.temp_dir() as script_dir:
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000336 pkg_dir = os.path.join(script_dir, 'test_pkg')
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000337 make_pkg(pkg_dir)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000338 script_name = _make_test_script(pkg_dir, '__main__')
Barry Warsaw28a691b2010-04-17 00:19:56 +0000339 compiled_name = py_compile.compile(script_name, doraise=True)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000340 os.remove(script_name)
Nick Coghland26c18a2010-08-17 13:06:11 +0000341 pyc_file = support.make_legacy_pyc(script_name)
Nick Coghland5d9e022018-03-25 23:03:10 +1000342 self._check_script(["-m", "test_pkg"], pyc_file,
Nick Coghlan85e729e2012-07-15 18:09:52 +1000343 pyc_file, script_dir, 'test_pkg',
Nick Coghland5d9e022018-03-25 23:03:10 +1000344 importlib.machinery.SourcelessFileLoader,
345 cwd=script_dir)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000346
347 def test_package_error(self):
Berker Peksagce643912015-05-06 06:33:17 +0300348 with support.temp_dir() as script_dir:
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000349 pkg_dir = os.path.join(script_dir, 'test_pkg')
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000350 make_pkg(pkg_dir)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000351 msg = ("'test_pkg' is a package and cannot "
352 "be directly executed")
Nick Coghland5d9e022018-03-25 23:03:10 +1000353 self._check_import_error(["-m", "test_pkg"], msg, cwd=script_dir)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000354
355 def test_package_recursion(self):
Berker Peksagce643912015-05-06 06:33:17 +0300356 with support.temp_dir() as script_dir:
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000357 pkg_dir = os.path.join(script_dir, 'test_pkg')
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000358 make_pkg(pkg_dir)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000359 main_dir = os.path.join(pkg_dir, '__main__')
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000360 make_pkg(main_dir)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000361 msg = ("Cannot use package as __main__ module; "
362 "'test_pkg' is a package and cannot "
363 "be directly executed")
Nick Coghland5d9e022018-03-25 23:03:10 +1000364 self._check_import_error(["-m", "test_pkg"], msg, cwd=script_dir)
Nick Coghlan3f48ae32009-02-08 01:58:26 +0000365
Nick Coghland26c18a2010-08-17 13:06:11 +0000366 def test_issue8202(self):
367 # Make sure package __init__ modules see "-m" in sys.argv0 while
368 # searching for the module to execute
Berker Peksagce643912015-05-06 06:33:17 +0300369 with support.temp_dir() as script_dir:
Nick Coghlan55175962013-07-28 22:11:50 +1000370 with support.change_cwd(path=script_dir):
Nick Coghland26c18a2010-08-17 13:06:11 +0000371 pkg_dir = os.path.join(script_dir, 'test_pkg')
372 make_pkg(pkg_dir, "import sys; print('init_argv0==%r' % sys.argv[0])")
373 script_name = _make_test_script(pkg_dir, 'script')
Victor Stinnere8785ff2013-10-12 14:44:01 +0200374 rc, out, err = assert_python_ok('-m', 'test_pkg.script', *example_args, __isolated=False)
Nick Coghland26c18a2010-08-17 13:06:11 +0000375 if verbose > 1:
Serhiy Storchakab0749ca2015-03-25 01:33:19 +0200376 print(repr(out))
Nick Coghland26c18a2010-08-17 13:06:11 +0000377 expected = "init_argv0==%r" % '-m'
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000378 self.assertIn(expected.encode('utf-8'), out)
379 self._check_output(script_name, rc, out,
Nick Coghland5d9e022018-03-25 23:03:10 +1000380 script_name, script_name, script_dir, 'test_pkg',
Nick Coghlan85e729e2012-07-15 18:09:52 +1000381 importlib.machinery.SourceFileLoader)
Nick Coghland26c18a2010-08-17 13:06:11 +0000382
383 def test_issue8202_dash_c_file_ignored(self):
384 # Make sure a "-c" file in the current directory
385 # does not alter the value of sys.path[0]
Berker Peksagce643912015-05-06 06:33:17 +0300386 with support.temp_dir() as script_dir:
Nick Coghlan55175962013-07-28 22:11:50 +1000387 with support.change_cwd(path=script_dir):
Nick Coghland26c18a2010-08-17 13:06:11 +0000388 with open("-c", "w") as f:
389 f.write("data")
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000390 rc, out, err = assert_python_ok('-c',
Victor Stinnere8785ff2013-10-12 14:44:01 +0200391 'import sys; print("sys.path[0]==%r" % sys.path[0])',
392 __isolated=False)
Nick Coghland26c18a2010-08-17 13:06:11 +0000393 if verbose > 1:
Serhiy Storchakab0749ca2015-03-25 01:33:19 +0200394 print(repr(out))
Nick Coghland26c18a2010-08-17 13:06:11 +0000395 expected = "sys.path[0]==%r" % ''
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000396 self.assertIn(expected.encode('utf-8'), out)
Nick Coghland26c18a2010-08-17 13:06:11 +0000397
398 def test_issue8202_dash_m_file_ignored(self):
399 # Make sure a "-m" file in the current directory
400 # does not alter the value of sys.path[0]
Berker Peksagce643912015-05-06 06:33:17 +0300401 with support.temp_dir() as script_dir:
Nick Coghland26c18a2010-08-17 13:06:11 +0000402 script_name = _make_test_script(script_dir, 'other')
Nick Coghlan55175962013-07-28 22:11:50 +1000403 with support.change_cwd(path=script_dir):
Nick Coghland26c18a2010-08-17 13:06:11 +0000404 with open("-m", "w") as f:
405 f.write("data")
Victor Stinnere8785ff2013-10-12 14:44:01 +0200406 rc, out, err = assert_python_ok('-m', 'other', *example_args,
407 __isolated=False)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000408 self._check_output(script_name, rc, out,
Nick Coghland5d9e022018-03-25 23:03:10 +1000409 script_name, script_name, script_dir, '',
Nick Coghlan85e729e2012-07-15 18:09:52 +1000410 importlib.machinery.SourceFileLoader)
Christian Heimes9cd17752007-11-18 19:35:23 +0000411
Inada Naoki10654c12019-04-01 18:35:20 +0900412 def test_issue20884(self):
413 # On Windows, script with encoding cookie and LF line ending
414 # will be failed.
415 with support.temp_dir() as script_dir:
416 script_name = os.path.join(script_dir, "issue20884.py")
417 with open(script_name, "w", newline='\n') as f:
418 f.write("#coding: iso-8859-1\n")
419 f.write('"""\n')
420 for _ in range(30):
421 f.write('x'*80 + '\n')
422 f.write('"""\n')
423
424 with support.change_cwd(path=script_dir):
425 rc, out, err = assert_python_ok(script_name)
426 self.assertEqual(b"", out)
427 self.assertEqual(b"", err)
428
Martin Panter657257e2015-12-03 01:23:10 +0000429 @contextlib.contextmanager
430 def setup_test_pkg(self, *args):
431 with support.temp_dir() as script_dir, \
432 support.change_cwd(path=script_dir):
433 pkg_dir = os.path.join(script_dir, 'test_pkg')
434 make_pkg(pkg_dir, *args)
435 yield pkg_dir
436
437 def check_dash_m_failure(self, *args):
438 rc, out, err = assert_python_failure('-m', *args, __isolated=False)
439 if verbose > 1:
440 print(repr(out))
441 self.assertEqual(rc, 1)
442 return err
443
Senthil Kumaranf01a3372012-07-04 19:28:16 -0700444 def test_dash_m_error_code_is_one(self):
445 # If a module is invoked with the -m command line flag
446 # and results in an error that the return code to the
447 # shell is '1'
Martin Panter657257e2015-12-03 01:23:10 +0000448 with self.setup_test_pkg() as pkg_dir:
449 script_name = _make_test_script(pkg_dir, 'other',
450 "if __name__ == '__main__': raise ValueError")
451 err = self.check_dash_m_failure('test_pkg.other', *example_args)
452 self.assertIn(b'ValueError', err)
453
454 def test_dash_m_errors(self):
455 # Exercise error reporting for various invalid package executions
456 tests = (
457 ('builtins', br'No code object available'),
Martin Panter9c8aa9b2016-08-21 04:07:58 +0000458 ('builtins.x', br'Error while finding module specification.*'
Milan Oberkirch8c3f05e2017-06-15 07:34:50 +1000459 br'ModuleNotFoundError'),
Martin Panter9c8aa9b2016-08-21 04:07:58 +0000460 ('builtins.x.y', br'Error while finding module specification.*'
Eric Snow46f97b82016-09-07 16:56:15 -0700461 br'ModuleNotFoundError.*No module named.*not a package'),
Martin Panter657257e2015-12-03 01:23:10 +0000462 ('os.path', br'loader.*cannot handle'),
463 ('importlib', br'No module named.*'
464 br'is a package and cannot be directly executed'),
Miss Islington (bot)4bd1d052019-08-30 13:42:54 -0700465 ('importlib.nonexistent', br'No module named'),
Martin Panter7dda4212015-12-10 06:47:06 +0000466 ('.unittest', br'Relative module names not supported'),
Martin Panter657257e2015-12-03 01:23:10 +0000467 )
468 for name, regex in tests:
469 with self.subTest(name):
470 rc, _, err = assert_python_failure('-m', name)
Senthil Kumaranf01a3372012-07-04 19:28:16 -0700471 self.assertEqual(rc, 1)
Martin Panter657257e2015-12-03 01:23:10 +0000472 self.assertRegex(err, regex)
473 self.assertNotIn(b'Traceback', err)
474
Martin Panterdda58432015-12-12 06:58:55 +0000475 def test_dash_m_bad_pyc(self):
476 with support.temp_dir() as script_dir, \
477 support.change_cwd(path=script_dir):
478 os.mkdir('test_pkg')
479 # Create invalid *.pyc as empty file
480 with open('test_pkg/__init__.pyc', 'wb'):
481 pass
482 err = self.check_dash_m_failure('test_pkg')
Martin Panter9c8aa9b2016-08-21 04:07:58 +0000483 self.assertRegex(err,
484 br'Error while finding module specification.*'
Martin Panterdda58432015-12-12 06:58:55 +0000485 br'ImportError.*bad magic number')
486 self.assertNotIn(b'is a package', err)
487 self.assertNotIn(b'Traceback', err)
488
Martin Panter657257e2015-12-03 01:23:10 +0000489 def test_dash_m_init_traceback(self):
490 # These were wrapped in an ImportError and tracebacks were
491 # suppressed; see Issue 14285
492 exceptions = (ImportError, AttributeError, TypeError, ValueError)
493 for exception in exceptions:
494 exception = exception.__name__
495 init = "raise {0}('Exception in __init__.py')".format(exception)
496 with self.subTest(exception), \
497 self.setup_test_pkg(init) as pkg_dir:
498 err = self.check_dash_m_failure('test_pkg')
499 self.assertIn(exception.encode('ascii'), err)
500 self.assertIn(b'Exception in __init__.py', err)
501 self.assertIn(b'Traceback', err)
502
503 def test_dash_m_main_traceback(self):
504 # Ensure that an ImportError's traceback is reported
505 with self.setup_test_pkg() as pkg_dir:
506 main = "raise ImportError('Exception in __main__ module')"
507 _make_test_script(pkg_dir, '__main__', main)
508 err = self.check_dash_m_failure('test_pkg')
509 self.assertIn(b'ImportError', err)
510 self.assertIn(b'Exception in __main__ module', err)
511 self.assertIn(b'Traceback', err)
Senthil Kumaranf01a3372012-07-04 19:28:16 -0700512
Nick Coghlan1d5ccdb2012-05-21 23:03:30 +1000513 def test_pep_409_verbiage(self):
514 # Make sure PEP 409 syntax properly suppresses
515 # the context of an exception
516 script = textwrap.dedent("""\
517 try:
518 raise ValueError
519 except:
520 raise NameError from None
521 """)
Berker Peksagce643912015-05-06 06:33:17 +0300522 with support.temp_dir() as script_dir:
Nick Coghlan1d5ccdb2012-05-21 23:03:30 +1000523 script_name = _make_test_script(script_dir, 'script', script)
524 exitcode, stdout, stderr = assert_python_failure(script_name)
525 text = stderr.decode('ascii').split('\n')
526 self.assertEqual(len(text), 4)
527 self.assertTrue(text[0].startswith('Traceback'))
528 self.assertTrue(text[1].startswith(' File '))
529 self.assertTrue(text[3].startswith('NameError'))
530
Victor Stinnere667e982012-11-12 01:23:15 +0100531 def test_non_ascii(self):
532 # Mac OS X denies the creation of a file with an invalid UTF-8 name.
Martin Panterc04fb562016-02-10 05:44:01 +0000533 # Windows allows creating a name with an arbitrary bytes name, but
Victor Stinnere667e982012-11-12 01:23:15 +0100534 # Python cannot a undecodable bytes argument to a subprocess.
Victor Stinner0af71aa2013-01-03 01:50:30 +0100535 if (support.TESTFN_UNDECODABLE
536 and sys.platform not in ('win32', 'darwin')):
537 name = os.fsdecode(support.TESTFN_UNDECODABLE)
538 elif support.TESTFN_NONASCII:
Victor Stinnere667e982012-11-12 01:23:15 +0100539 name = support.TESTFN_NONASCII
540 else:
541 self.skipTest("need support.TESTFN_NONASCII")
542
Andrew Svetlov90c0eb22012-11-01 14:51:14 +0200543 # Issue #16218
Victor Stinnere667e982012-11-12 01:23:15 +0100544 source = 'print(ascii(__file__))\n'
545 script_name = _make_test_script(os.curdir, name, source)
546 self.addCleanup(support.unlink, script_name)
547 rc, stdout, stderr = assert_python_ok(script_name)
548 self.assertEqual(
549 ascii(script_name),
550 stdout.rstrip().decode('ascii'),
551 'stdout=%r stderr=%r' % (stdout, stderr))
552 self.assertEqual(0, rc)
553
Nick Coghland979e432014-02-09 10:43:21 +1000554 def test_issue20500_exit_with_exception_value(self):
555 script = textwrap.dedent("""\
556 import sys
557 error = None
558 try:
559 raise ValueError('some text')
560 except ValueError as err:
561 error = err
562
563 if error:
564 sys.exit(error)
565 """)
Berker Peksagce643912015-05-06 06:33:17 +0300566 with support.temp_dir() as script_dir:
Nick Coghland979e432014-02-09 10:43:21 +1000567 script_name = _make_test_script(script_dir, 'script', script)
568 exitcode, stdout, stderr = assert_python_failure(script_name)
569 text = stderr.decode('ascii')
570 self.assertEqual(text, "some text")
571
Martin Panterca3263c2016-12-11 00:18:36 +0000572 def test_syntaxerror_unindented_caret_position(self):
573 script = "1 + 1 = 2\n"
574 with support.temp_dir() as script_dir:
575 script_name = _make_test_script(script_dir, 'script', script)
576 exitcode, stdout, stderr = assert_python_failure(script_name)
577 text = io.TextIOWrapper(io.BytesIO(stderr), 'ascii').read()
578 # Confirm that the caret is located under the first 1 character
579 self.assertIn("\n 1 + 1 = 2\n ^", text)
580
581 def test_syntaxerror_indented_caret_position(self):
582 script = textwrap.dedent("""\
583 if True:
584 1 + 1 = 2
585 """)
586 with support.temp_dir() as script_dir:
587 script_name = _make_test_script(script_dir, 'script', script)
588 exitcode, stdout, stderr = assert_python_failure(script_name)
589 text = io.TextIOWrapper(io.BytesIO(stderr), 'ascii').read()
590 # Confirm that the caret is located under the first 1 character
591 self.assertIn("\n 1 + 1 = 2\n ^", text)
592
593 # Try the same with a form feed at the start of the indented line
594 script = (
595 "if True:\n"
596 "\f 1 + 1 = 2\n"
597 )
598 script_name = _make_test_script(script_dir, "script", script)
599 exitcode, stdout, stderr = assert_python_failure(script_name)
600 text = io.TextIOWrapper(io.BytesIO(stderr), "ascii").read()
601 self.assertNotIn("\f", text)
602 self.assertIn("\n 1 + 1 = 2\n ^", text)
603
Miss Islington (bot)cf52bd02019-07-29 07:18:47 -0700604 def test_syntaxerror_multi_line_fstring(self):
605 script = 'foo = f"""{}\nfoo"""\n'
606 with support.temp_dir() as script_dir:
607 script_name = _make_test_script(script_dir, 'script', script)
608 exitcode, stdout, stderr = assert_python_failure(script_name)
609 self.assertEqual(
610 stderr.splitlines()[-3:],
611 [
612 b' foo = f"""{}',
613 b' ^',
614 b'SyntaxError: f-string: empty expression not allowed',
615 ],
616 )
617
Miss Islington (bot)bf0b8a62019-07-29 08:26:29 -0700618 def test_syntaxerror_invalid_escape_sequence_multi_line(self):
619 script = 'foo = """\\q\n"""\n'
620 with support.temp_dir() as script_dir:
621 script_name = _make_test_script(script_dir, 'script', script)
622 exitcode, stdout, stderr = assert_python_failure(
623 '-Werror', script_name,
624 )
625 self.assertEqual(
626 stderr.splitlines()[-3:],
627 [
628 b' foo = """\\q',
629 b' ^',
630 b'SyntaxError: invalid escape sequence \\q',
631 ],
632 )
633
Nick Coghland2977a32017-03-12 20:38:32 +1000634 def test_consistent_sys_path_for_direct_execution(self):
635 # This test case ensures that the following all give the same
636 # sys.path configuration:
637 #
638 # ./python -s script_dir/__main__.py
639 # ./python -s script_dir
640 # ./python -I script_dir
641 script = textwrap.dedent("""\
642 import sys
643 for entry in sys.path:
644 print(entry)
645 """)
646 # Always show full path diffs on errors
647 self.maxDiff = None
648 with support.temp_dir() as work_dir, support.temp_dir() as script_dir:
649 script_name = _make_test_script(script_dir, '__main__', script)
650 # Reference output comes from directly executing __main__.py
651 # We omit PYTHONPATH and user site to align with isolated mode
652 p = spawn_python("-Es", script_name, cwd=work_dir)
653 out_by_name = kill_python(p).decode().splitlines()
654 self.assertEqual(out_by_name[0], script_dir)
655 self.assertNotIn(work_dir, out_by_name)
656 # Directory execution should give the same output
657 p = spawn_python("-Es", script_dir, cwd=work_dir)
658 out_by_dir = kill_python(p).decode().splitlines()
659 self.assertEqual(out_by_dir, out_by_name)
660 # As should directory execution in isolated mode
661 p = spawn_python("-I", script_dir, cwd=work_dir)
662 out_by_dir_isolated = kill_python(p).decode().splitlines()
663 self.assertEqual(out_by_dir_isolated, out_by_dir, out_by_name)
664
665 def test_consistent_sys_path_for_module_execution(self):
666 # This test case ensures that the following both give the same
667 # sys.path configuration:
668 # ./python -sm script_pkg.__main__
669 # ./python -sm script_pkg
670 #
671 # And that this fails as unable to find the package:
672 # ./python -Im script_pkg
673 script = textwrap.dedent("""\
674 import sys
675 for entry in sys.path:
676 print(entry)
677 """)
678 # Always show full path diffs on errors
679 self.maxDiff = None
680 with support.temp_dir() as work_dir:
681 script_dir = os.path.join(work_dir, "script_pkg")
682 os.mkdir(script_dir)
683 script_name = _make_test_script(script_dir, '__main__', script)
684 # Reference output comes from `-m script_pkg.__main__`
685 # We omit PYTHONPATH and user site to better align with the
686 # direct execution test cases
687 p = spawn_python("-sm", "script_pkg.__main__", cwd=work_dir)
688 out_by_module = kill_python(p).decode().splitlines()
Nick Coghland5d9e022018-03-25 23:03:10 +1000689 self.assertEqual(out_by_module[0], work_dir)
Nick Coghland2977a32017-03-12 20:38:32 +1000690 self.assertNotIn(script_dir, out_by_module)
691 # Package execution should give the same output
692 p = spawn_python("-sm", "script_pkg", cwd=work_dir)
693 out_by_package = kill_python(p).decode().splitlines()
694 self.assertEqual(out_by_package, out_by_module)
695 # Isolated mode should fail with an import error
696 exitcode, stdout, stderr = assert_python_failure(
697 "-Im", "script_pkg", cwd=work_dir
698 )
699 traceback_lines = stderr.decode().splitlines()
700 self.assertIn("No module named script_pkg", traceback_lines[-1])
Andrew Svetlov90c0eb22012-11-01 14:51:14 +0200701
Victor Stinnera46467f2018-09-24 08:06:29 -0700702 def test_nonexisting_script(self):
703 # bpo-34783: "./python script.py" must not crash
704 # if the script file doesn't exist.
Ned Deilyf6c29a62018-10-12 23:54:20 -0400705 # (Skip test for macOS framework builds because sys.excutable name
706 # is not the actual Python executable file name.
Victor Stinnera46467f2018-09-24 08:06:29 -0700707 script = 'nonexistingscript.py'
708 self.assertFalse(os.path.exists(script))
Victor Stinnera46467f2018-09-24 08:06:29 -0700709
710 proc = spawn_python(script, text=True,
711 stdout=subprocess.PIPE,
712 stderr=subprocess.PIPE)
713 out, err = proc.communicate()
Victor Stinnerea751872018-10-15 23:50:55 +0200714 self.assertIn(": can't open file ", err)
Victor Stinnera46467f2018-09-24 08:06:29 -0700715 self.assertNotEqual(proc.returncode, 0)
716
717
Christian Heimes9cd17752007-11-18 19:35:23 +0000718def test_main():
Nick Coghland26c18a2010-08-17 13:06:11 +0000719 support.run_unittest(CmdLineTest)
720 support.reap_children()
Christian Heimes9cd17752007-11-18 19:35:23 +0000721
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000722if __name__ == '__main__':
Christian Heimes9cd17752007-11-18 19:35:23 +0000723 test_main()