def test_consistent_sys_path_for_direct_execution(self): # This test case ensures that the following all give the same # sys.path configuration: # # ./python -s script_dir/__main__.py # ./python -s script_dir # ./python -I script_dir script = textwrap.dedent("""\ import sys for entry in sys.path: print(entry) """) # Always show full path diffs on errors self.maxDiff = None with support.temp_dir() as work_dir, support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', script) # Reference output comes from directly executing __main__.py # We omit PYTHONPATH and user site to align with isolated mode p = spawn_python("-Es", script_name, cwd=work_dir) out_by_name = kill_python(p).decode().splitlines() self.assertEqual(out_by_name[0], script_dir) self.assertNotIn(work_dir, out_by_name) # Directory execution should give the same output p = spawn_python("-Es", script_dir, cwd=work_dir) out_by_dir = kill_python(p).decode().splitlines() self.assertEqual(out_by_dir, out_by_name) # As should directory execution in isolated mode p = spawn_python("-I", script_dir, cwd=work_dir) out_by_dir_isolated = kill_python(p).decode().splitlines() self.assertEqual(out_by_dir_isolated, out_by_dir, out_by_name)
def interactive_python(self, separate_stderr=False): if separate_stderr: p = spawn_python('-i', bufsize=1, stderr=subprocess.PIPE) stderr = p.stderr else: p = spawn_python('-i', bufsize=1, stderr=subprocess.STDOUT) stderr = p.stdout try: # Drain stderr until prompt if support.check_impl_detail(pypy=True): ps1 = b">>>> " # PyPy: the prompt is still printed to stdout, like it # is in CPython 2.7. This messes up the logic below # if stdout and stderr are different. Skip for now. if separate_stderr: self.skipTest("the prompt is still written to " "stdout in pypy") else: ps1 = b">>> " # logic fixed to support the case of lines that are shorter # than len(ps1) characters got = b"" while not got.endswith(ps1): got += stderr.read(1) yield p finally: kill_python(p) stderr.close()
def test_include_on_stdin(self): f1 = script_helper.make_script(self.pkgdir, "f1", "") f2 = script_helper.make_script(self.pkgdir, "f2", "") f3 = script_helper.make_script(self.pkgdir, "f3", "") f4 = script_helper.make_script(self.pkgdir, "f4", "") p = script_helper.spawn_python(*(self._get_run_args(()) + ["-i", "-"])) p.stdin.write((f3 + os.linesep).encode("ascii")) script_helper.kill_python(p) self.assertNotCompiled(f1) self.assertNotCompiled(f2) self.assertCompiled(f3) self.assertNotCompiled(f4)
def test_include_on_stdin(self): f1 = script_helper.make_script(self.pkgdir, 'f1', '') f2 = script_helper.make_script(self.pkgdir, 'f2', '') f3 = script_helper.make_script(self.pkgdir, 'f3', '') f4 = script_helper.make_script(self.pkgdir, 'f4', '') p = script_helper.spawn_python(*(self._get_run_args(()) + ['-i', '-'])) p.stdin.write((f3 + os.linesep).encode('ascii')) script_helper.kill_python(p) self.assertNotCompiled(f1) self.assertNotCompiled(f2) self.assertCompiled(f3) self.assertNotCompiled(f4)
def test_include_on_stdin(self): f1 = script_helper.make_script(self.pkgdir, 'f1', '') f2 = script_helper.make_script(self.pkgdir, 'f2', '') f3 = script_helper.make_script(self.pkgdir, 'f3', '') f4 = script_helper.make_script(self.pkgdir, 'f4', '') p = script_helper.spawn_python(*(self._get_run_args(()) + ['-i', '-'])) p.stdin.write((f3+os.linesep).encode('ascii')) script_helper.kill_python(p) self.assertNotCompiled(f1) self.assertNotCompiled(f2) self.assertCompiled(f3) self.assertNotCompiled(f4)
def test_run_module_bug1764407(self): p = spawn_python('-i', '-m', 'timeit', '-n', '1') p.stdin.write(b'Timer\n') p.stdin.write(b'exit()\n') data = kill_python(p) self.assertTrue(data.find(b'1 loop') != -1) self.assertTrue(data.find(b'__main__.Timer') != -1)
def test_multiline_string_parsing(self): # bpo-39209: Multiline string tokens need to be handled in the tokenizer # in two places: the interactive path and the non-interactive path. user_input = '''\ x = """<?xml version="1.0" encoding="iso-8859-1"?> <test> <Users> <fun25> <limits> <total>0KiB</total> <kbps>0</kbps> <rps>1.3</rps> <connections>0</connections> </limits> <usages> <total>16738211KiB</total> <kbps>237.15</kbps> <rps>1.3</rps> <connections>0</connections> </usages> <time_to_refresh>never</time_to_refresh> <limit_exceeded_URL>none</limit_exceeded_URL> </fun25> </Users> </test>""" ''' user_input = dedent(user_input) p = spawn_repl() p.stdin.write(user_input) output = kill_python(p) self.assertEqual(p.returncode, 0)
def interactive_python(self, separate_stderr=False): if separate_stderr: p = spawn_python('-i', bufsize=1, stderr=subprocess.PIPE) stderr = p.stderr else: p = spawn_python('-i', bufsize=1, stderr=subprocess.STDOUT) stderr = p.stdout try: while True: data = stderr.read(4) if data == b'>>> ': break stderr.readline() yield p finally: kill_python(p) stderr.close()
def test_fill(self): data = self._merge_helper(FIRST, SECOND).decode("ascii") with tempfile.NamedTemporaryFile(mode="w+") as merged: merged.file.write(data) merged.file.flush() p = spawn_python('csvprogs/src/csvfill.py', '-k', 'position', merged.name) data = kill_python(p) self.assertEqual(data, FILLED)
def test_consistent_sys_path_for_direct_execution(self): script = textwrap.dedent(""" import sys for entry in sys.path: print(entry) """) self.maxDiff = None with support.temp_dir() as work_dir, support.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__', script) p = spawn_python('-Es', script_name, cwd=work_dir) out_by_name = kill_python(p).decode().splitlines() self.assertEqual(out_by_name[0], script_dir) self.assertNotIn(work_dir, out_by_name) p = spawn_python('-Es', script_dir, cwd=work_dir) out_by_dir = kill_python(p).decode().splitlines() self.assertEqual(out_by_dir, out_by_name) p = spawn_python('-I', script_dir, cwd=work_dir) out_by_dir_isolated = kill_python(p).decode().splitlines() self.assertEqual(out_by_dir_isolated, out_by_dir, out_by_name)
def test_stdin_loader(self): p = spawn_python() try: p.stdin.write(b'print(__loader__)\n') p.stdin.flush() finally: out = kill_python(p) expected = repr(importlib.machinery.BuiltinImporter).encode('utf-8') self.assertIn(expected, out)
def interactive_python(self, separate_stderr=False): if separate_stderr: p = spawn_python('-i', stderr=subprocess.PIPE) stderr = p.stderr else: p = spawn_python('-i', stderr=subprocess.STDOUT) stderr = p.stdout try: # Drain stderr until prompt while True: data = stderr.read(4) if data == b">>> ": break stderr.readline() yield p finally: kill_python(p) stderr.close()
def interactive_python(self, separate_stderr=False): if separate_stderr: p = spawn_python('-i', bufsize=1, stderr=subprocess.PIPE) stderr = p.stderr else: p = spawn_python('-i', bufsize=1, stderr=subprocess.STDOUT) stderr = p.stdout try: # Drain stderr until prompt while True: data = stderr.read(4) if data == b">>> ": break stderr.readline() yield p finally: kill_python(p) stderr.close()
def test_run_module_bug1764407(self): # -m and -i need to play well together # Runs the timeit module and checks the __main__ # namespace has been populated appropriately p = spawn_python('-i', '-m', 'timeit', '-n', '1') p.stdin.write(b'Timer\n') p.stdin.write(b'exit()\n') data = kill_python(p) self.assertTrue(data.find(b'1 loop') != -1) self.assertTrue(data.find(b'__main__.Timer') != -1)
def test_pdb_issue4201(self): test_src = textwrap.dedent(""" def f(): pass import pdb pdb.Pdb(nosigint=True).runcall(f) """) with test.support.temp_dir() as d: script_name = make_script(d, 'script', test_src) p = spawn_python(script_name) p.stdin.write(b'l\n') data = kill_python(p) self.assertIn(os.path.normcase(script_name.encode('utf-8')), data) zip_name, run_name = make_zip_script(d, 'test_zip', script_name, '__main__.py') p = spawn_python(zip_name) p.stdin.write(b'l\n') data = kill_python(p) self.assertIn(os.path.normcase(run_name.encode('utf-8')), data)
def test_stdin_loader(self): # Unfortunately, there's no way to automatically test the fully # interactive REPL, since that code path only gets executed when # stdin is an interactive tty. p = spawn_python() try: p.stdin.write(b"print(__loader__)\n") p.stdin.flush() finally: out = kill_python(p) expected = repr(importlib.machinery.BuiltinImporter).encode("utf-8") self.assertIn(expected, out)
def _merge_helper(self, first, second): with tempfile.NamedTemporaryFile(mode="w+") as first: with tempfile.NamedTemporaryFile(mode="w+") as second: writer = csv.writer(first.file) writer.writerows(FIRST) first.file.flush() writer = csv.writer(second.file) writer.writerows(SECOND) second.file.flush() p = spawn_python('csvprogs/src/csvmerge.py', '-k', 'time', first.name, second.name) return kill_python(p)
def test_pdb_issue4201(self): test_src = textwrap.dedent("""\ def f(): pass import pdb pdb.Pdb(nosigint=True).runcall(f) """) with test.support.temp_dir() as d: script_name = make_script(d, 'script', test_src) p = spawn_python(script_name) p.stdin.write(b'l\n') data = kill_python(p) # bdb/pdb applies normcase to its filename before displaying self.assertIn(os.path.normcase(script_name.encode('utf-8')), data) zip_name, run_name = make_zip_script(d, "test_zip", script_name, '__main__.py') p = spawn_python(zip_name) p.stdin.write(b'l\n') data = kill_python(p) # bdb/pdb applies normcase to its filename before displaying self.assertIn(os.path.normcase(run_name.encode('utf-8')), data)
def run_on_interactive_mode(source): """Spawn a new Python interpreter, pass the given input source code from the stdin and return the result back. If the interpreter exits non-zero, it raises a ValueError.""" process = spawn_repl() process.stdin.write(source) output = kill_python(process) if process.returncode != 0: raise ValueError("Process didn't exit properly.") return output
def test_consistent_sys_path_for_module_execution(self): # This test case ensures that the following both give the same # sys.path configuration: # ./python -sm script_pkg.__main__ # ./python -sm script_pkg # # And that this fails as unable to find the package: # ./python -Im script_pkg script = textwrap.dedent("""\ import sys for entry in sys.path: print(entry) """) # Always show full path diffs on errors self.maxDiff = None with support.temp_dir() as work_dir: script_dir = os.path.join(work_dir, "script_pkg") os.mkdir(script_dir) script_name = _make_test_script(script_dir, '__main__', script) # Reference output comes from `-m script_pkg.__main__` # We omit PYTHONPATH and user site to better align with the # direct execution test cases p = spawn_python("-sm", "script_pkg.__main__", cwd=work_dir) out_by_module = kill_python(p).decode().splitlines() if sys.platform == 'OpenVMS': work_dir = work_dir.replace('/tmp/', tmp_folder_real) script_dir = script_dir.replace('/tmp/', tmp_folder_real) self.assertEqual(out_by_module[0], work_dir) self.assertNotIn(script_dir, out_by_module) # Package execution should give the same output p = spawn_python("-sm", "script_pkg", cwd=work_dir) out_by_package = kill_python(p).decode().splitlines() self.assertEqual(out_by_package, out_by_module) # Isolated mode should fail with an import error exitcode, stdout, stderr = assert_python_failure("-Im", "script_pkg", cwd=work_dir) traceback_lines = stderr.decode().splitlines() self.assertIn("No module named script_pkg", traceback_lines[-1])
def test_pdb_issue4201(self): test_src = textwrap.dedent("""\ def f(): pass import pdb pdb.Pdb(nosigint=True).runcall(f) """) with os_helper.temp_dir() as d: script_name = make_script(d, 'script', test_src) p = spawn_python(script_name) p.stdin.write(b'l\n') data = kill_python(p) # bdb/pdb applies normcase to its filename before displaying self.assertIn(os.path.normcase(script_name.encode('utf-8')), data) zip_name, run_name = make_zip_script(d, "test_zip", script_name, '__main__.py') p = spawn_python(zip_name) p.stdin.write(b'l\n') data = kill_python(p) # bdb/pdb applies normcase to its filename before displaying self.assertIn(os.path.normcase(run_name.encode('utf-8')), data)
def test_consistent_sys_path_for_module_execution(self): script = textwrap.dedent(""" import sys for entry in sys.path: print(entry) """) self.maxDiff = None with support.temp_dir() as work_dir: script_dir = os.path.join(work_dir, 'script_pkg') os.mkdir(script_dir) script_name = _make_test_script(script_dir, '__main__', script) p = spawn_python('-sm', 'script_pkg.__main__', cwd=work_dir) out_by_module = kill_python(p).decode().splitlines() self.assertEqual(out_by_module[0], '') self.assertNotIn(script_dir, out_by_module) p = spawn_python('-sm', 'script_pkg', cwd=work_dir) out_by_package = kill_python(p).decode().splitlines() self.assertEqual(out_by_package, out_by_module) exitcode, stdout, stderr = assert_python_failure('-Im', 'script_pkg', cwd=work_dir) traceback_lines = stderr.decode().splitlines() self.assertIn('No module named script_pkg', traceback_lines[-1])
def test_consistent_sys_path_for_module_execution(self): # This test case ensures that the following both give the same # sys.path configuration: # ./python -sm script_pkg.__main__ # ./python -sm script_pkg # # And that this fails as unable to find the package: # ./python -Im script_pkg script = textwrap.dedent("""\ import sys for entry in sys.path: print(entry) """) # Always show full path diffs on errors self.maxDiff = None with support.temp_dir() as work_dir: script_dir = os.path.join(work_dir, "script_pkg") os.mkdir(script_dir) script_name = _make_test_script(script_dir, '__main__', script) # Reference output comes from `-m script_pkg.__main__` # We omit PYTHONPATH and user site to better align with the # direct execution test cases p = spawn_python("-sm", "script_pkg.__main__", cwd=work_dir) out_by_module = kill_python(p).decode().splitlines() self.assertEqual(out_by_module[0], '') self.assertNotIn(script_dir, out_by_module) # Package execution should give the same output p = spawn_python("-sm", "script_pkg", cwd=work_dir) out_by_package = kill_python(p).decode().splitlines() self.assertEqual(out_by_package, out_by_module) # Isolated mode should fail with an import error exitcode, stdout, stderr = assert_python_failure( "-Im", "script_pkg", cwd=work_dir ) traceback_lines = stderr.decode().splitlines() self.assertIn("No module named script_pkg", traceback_lines[-1])
def test_displayhook_unencodable(self): for encoding in ('ascii', 'latin-1', 'utf-8'): env = os.environ.copy() env['PYTHONIOENCODING'] = encoding p = subprocess.Popen([sys.executable, '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env) # non-ascii, surrogate, non-BMP printable, non-BMP unprintable text = "a=\xe9 b=\uDC80 c=\U00010000 d=\U0010FFFF" p.stdin.write(ascii(text).encode('ascii') + b"\n") p.stdin.write(b'exit()\n') data = kill_python(p) escaped = repr(text).encode(encoding, 'backslashreplace') self.assertIn(escaped, data)
def test_displayhook_unencodable(self): for encoding in ('ascii', 'latin-1', 'utf-8'): env = os.environ.copy() env['PYTHONIOENCODING'] = encoding p = subprocess.Popen( [sys.executable, '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env) # non-ascii, surrogate, non-BMP printable, non-BMP unprintable text = "a=\xe9 b=\uDC80 c=\U00010000 d=\U0010FFFF" p.stdin.write(ascii(text).encode('ascii') + b"\n") p.stdin.write(b'exit()\n') data = kill_python(p) escaped = repr(text).encode(encoding, 'backslashreplace') self.assertIn(escaped, data)
def test_displayhook_unencodable(self): for encoding in ('ascii', 'latin-1', 'utf-8'): env = { key: value for key, value in os.environ.copy().items() if not key.startswith('PYTHON') } env['PYTHONIOENCODING'] = encoding p = subprocess.Popen([sys.executable, '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env) text = 'a=é b=\udc80 c=𐀀 d=\U0010ffff' p.stdin.write(ascii(text).encode('ascii') + b'\n') p.stdin.write(b'exit()\n') data = kill_python(p) escaped = repr(text).encode(encoding, 'backslashreplace') self.assertIn(escaped, data)
def test_no_memory(self): # Issue #30696: Fix the interactive interpreter looping endlessly when # no memory. Check also that the fix does not break the interactive # loop when an exception is raised. user_input = """ import sys, _testcapi 1/0 print('After the exception.') _testcapi.set_nomemory(0) sys.exit(0) """ user_input = dedent(user_input) p = spawn_repl() with SuppressCrashReport(): p.stdin.write(user_input) output = kill_python(p) self.assertIn('After the exception.', output) # Exit code 120: Py_FinalizeEx() failed to flush stdout and stderr. self.assertIn(p.returncode, (1, 120))
def test_no_memory(self): # Issue #30696: Fix the interactive interpreter looping endlessly when # no memory. Check also that the fix does not break the interactive # loop when an exception is raised. user_input = """ import sys, _testcapi 1/0 print('After the exception.') _testcapi.set_nomemory(0) sys.exit(0) """ user_input = dedent(user_input) user_input = user_input.encode() p = spawn_repl() with SuppressCrashReport(): p.stdin.write(user_input) output = kill_python(p) self.assertIn(b'After the exception.', output) # Exit code 120: Py_FinalizeEx() failed to flush stdout and stderr. self.assertIn(p.returncode, (1, 120))
def test_displayhook_unencodable(self): for encoding in ('ascii', 'latin-1', 'utf-8'): # We are testing a PYTHON environment variable here, so we can't # use -E, -I, or script_helper (which uses them). So instead we do # poor-man's isolation by deleting the PYTHON vars from env. env = {key:value for (key,value) in os.environ.copy().items() if not key.startswith('PYTHON')} env['PYTHONIOENCODING'] = encoding p = subprocess.Popen( [sys.executable, '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env) # non-ascii, surrogate, non-BMP printable, non-BMP unprintable text = "a=\xe9 b=\uDC80 c=\U00010000 d=\U0010FFFF" p.stdin.write(ascii(text).encode('ascii') + b"\n") p.stdin.write(b'exit()\n') data = kill_python(p) escaped = repr(text).encode(encoding, 'backslashreplace') self.assertIn(escaped, data)
def _kill_python_and_exit_code(p): data = kill_python(p) returncode = p.wait() return data, returncode