◐ Shell
reader mode source ↗
Skip to content
Merged
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
207 changes: 176 additions & 31 deletions Lib/test/test_cmd_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
import subprocess
import sys
import tempfile
import unittest
from test import support
from test.support.script_helper import (
spawn_python, kill_python, assert_python_ok, assert_python_failure,
interpreter_requires_environment
)
from test.support import os_helper


# Debug build?
Py_DEBUG = hasattr(sys, "gettotalrefcount")
Expand All @@ -25,38 +28,63 @@ def _kill_python_and_exit_code(p):
returncode = p.wait()
return data, returncode

class CmdLineTest(unittest.TestCase):
def test_directories(self):
assert_python_failure('.')
assert_python_failure('< .')

def verify_valid_flag(self, cmd_line):
rc, out, err = assert_python_ok(*cmd_line)
self.assertTrue(out == b'' or out.endswith(b'\n'))
self.assertNotIn(b'Traceback', out)
self.assertNotIn(b'Traceback', err)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_optimize(self):
self.verify_valid_flag('-O')
self.verify_valid_flag('-OO')

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_site_flag(self):
self.verify_valid_flag('-S')

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_usage(self):
rc, out, err = assert_python_ok('-h')
lines = out.splitlines()
self.assertIn(b'usage', lines[0])
# The first line contains the program name,
# but the rest should be ASCII-only
b''.join(lines[1:]).decode('ascii')

# NOTE: RUSTPYTHON version never starts with Python
@unittest.expectedFailure
def test_version(self):
Expand Down @@ -114,13 +142,32 @@ def run_python(*args):
self.assertEqual(out.rstrip(), b'{}')
self.assertEqual(err, b'')
# "-X showrefcount" shows the refcount, but only in debug builds
rc, out, err = run_python('-X', 'showrefcount', '-c', code)
self.assertEqual(out.rstrip(), b"{'showrefcount': True}")
if Py_DEBUG:
self.assertRegex(err, br'^\[\d+ refs, \d+ blocks\]')
else:
self.assertEqual(err, b'')

def test_run_module(self):
# Test expected operation of the '-m' switch
# Switch needs an argument
Expand All @@ -146,6 +193,16 @@ def test_run_module_bug1764407(self):
self.assertTrue(data.find(b'1 loop') != -1)
self.assertTrue(data.find(b'__main__.Timer') != -1)

def test_run_code(self):
# Test expected operation of the '-c' switch
# Switch needs an argument
@@ -162,6 +219,14 @@ def test_non_ascii(self):
% (os_helper.FS_NONASCII, ord(os_helper.FS_NONASCII)))
assert_python_ok('-c', command)

# On Windows, pass bytes to subprocess doesn't test how Python decodes the
# command line, but how subprocess does decode bytes to unicode. Python
# doesn't decode the command line because Windows provides directly the
Expand All @@ -179,7 +244,7 @@ def test_undecodable_code(self):
code = (
b'import locale; '
b'print(ascii("' + undecodable + b'"), '
b'locale.getpreferredencoding())')
p = subprocess.Popen(
[sys.executable, "-c", code],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
Expand Down @@ -214,7 +279,6 @@ def test_invalid_utf8_arg(self):
#
# Test with default config, in the C locale, in the Python UTF-8 Mode.
code = 'import sys, os; s=os.fsencode(sys.argv[1]); print(ascii(s))'
base_cmd = [sys.executable, '-c', code]

# TODO: RUSTPYTHON
@unittest.expectedFailure
Expand Up @@ -277,6 +341,23 @@ def test_osx_android_utf8(self):
self.assertEqual(stdout, expected)
self.assertEqual(p.returncode, 0)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_unbuffered_output(self):
Expand Down Expand Up @@ -320,6 +401,8 @@ def test_large_PYTHONPATH(self):
self.assertIn(path1.encode('ascii'), out)
self.assertIn(path2.encode('ascii'), out)

def test_empty_PYTHONPATH_issue16309(self):
# On Posix, it is documented that setting PATH to the
# empty string is equivalent to not setting PATH at all,
Expand Up @@ -369,23 +452,25 @@ def check_input(self, code, expected):
stdout, stderr = proc.communicate()
self.assertEqual(stdout.rstrip(), expected)

@unittest.skipIf(sys.platform == "win32", "AssertionError: b"'abc\\r'" != b"'abc'"")
def test_stdin_readline(self):
# Issue #11272: check that sys.stdin.readline() replaces '\r\n' by '\n'
# on Windows (sys.stdin is opened in binary mode)
self.check_input(
"import sys; print(repr(sys.stdin.readline()))",
b"'abc\\n'")

@unittest.skipIf(sys.platform == "win32", "AssertionError: b"'abc\\r'" != b"'abc'"")
def test_builtin_input(self):
# Issue #11272: check that input() strips newlines ('\n' or '\r\n')
self.check_input(
"print(repr(input()))",
b"'abc'")

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_output_newline(self):
# Issue 13119 Newline for print() should be \r\n on Windows.
code = """if 1:
Expand All @@ -398,10 +483,10 @@ def test_output_newline(self):

if sys.platform == 'win32':
self.assertEqual(b'1\r\n2\r\n', out)
self.assertEqual(b'3\r\n4', err)
else:
self.assertEqual(b'1\n2\n', out)
self.assertEqual(b'3\n4', err)

def test_unmached_quote(self):
# Issue #10206: python program starting with unmatched quote
Expand Down @@ -459,7 +544,7 @@ def preexec():
stderr=subprocess.PIPE,
preexec_fn=preexec)
out, err = p.communicate()
self.assertEqual(support.strip_python_stderr(err), b'')
self.assertEqual(p.returncode, 42)

# TODO: RUSTPYTHON
Expand Down Expand Up @@ -527,7 +612,7 @@ def test_del___main__(self):
# the dict whereas the module was destroyed
filename = os_helper.TESTFN
self.addCleanup(os_helper.unlink, filename)
with open(filename, "w") as script:
print("import sys", file=script)
print("del sys.modules['__main__']", file=script)
assert_python_ok(filename)
Expand Down Expand Up @@ -558,24 +643,25 @@ def test_unknown_options(self):
'Cannot run -I tests when PYTHON env vars are required.')
def test_isolatedmode(self):
self.verify_valid_flag('-I')
self.verify_valid_flag('-IEs')
rc, out, err = assert_python_ok('-I', '-c',
'from sys import flags as f; '
'print(f.no_user_site, f.ignore_environment, f.isolated)',
# dummyvar to prevent extraneous -E
dummyvar="")
self.assertEqual(out.strip(), b'1 1 1')
with os_helper.temp_cwd() as tmpdir:
fake = os.path.join(tmpdir, "uuid.py")
main = os.path.join(tmpdir, "main.py")
with open(fake, "w") as f:
f.write("raise RuntimeError('isolated mode test')\n")
with open(main, "w") as f:
f.write("import uuid\n")
f.write("print('ok')\n")
self.assertRaises(subprocess.CalledProcessError,
subprocess.check_output,
[sys.executable, main], cwd=tmpdir,
stderr=subprocess.DEVNULL)
out = subprocess.check_output([sys.executable, "-I", main],
cwd=tmpdir)
Expand Down Expand Up @@ -716,7 +802,8 @@ def test_xdev(self):

def check_warnings_filters(self, cmdline_option, envvar, use_pywarning=False):
if use_pywarning:
code = ("import sys; from test.support.import_helper import import_fresh_module; "
"warnings = import_fresh_module('warnings', blocked=['_warnings']); ")
else:
code = "import sys, warnings; "
Expand Down Expand Up @@ -846,6 +933,43 @@ def test_parsing_error(self):
self.assertTrue(proc.stderr.startswith(err_msg), proc.stderr)
self.assertNotEqual(proc.returncode, 0)


@unittest.skipIf(interpreter_requires_environment(),
'Cannot run -I tests when PYTHON env vars are required.')
Expand Down Expand Up @@ -874,20 +998,41 @@ def test_sys_flags_not_set(self):
# Issue 31845: a startup refactoring broke reading flags from env vars
expected_outcome = """
(sys.flags.debug == sys.flags.optimize ==
sys.flags.dont_write_bytecode == sys.flags.verbose == 0)
"""
self.run_ignoring_vars(
expected_outcome,
PYTHONDEBUG="1",
PYTHONOPTIMIZE="1",
PYTHONDONTWRITEBYTECODE="1",
PYTHONVERBOSE="1",
)


def test_main():
support.run_unittest(CmdLineTest, IgnoreEnvironmentTest)
support.reap_children()

if __name__ == "__main__":
test_main()
Toggle all file notes Toggle all file annotations