text: # Tests invocation of the interpreter with various command line arguments
  # Most tests are executed with environment variables ignored
  # See test_cmd_line_script.py for testing of script execution
  
  import test.support, unittest
  import os
  import sys
  import subprocess
  import tempfile
  from test.script_helper import spawn_python, kill_python, assert_python_ok, assert_python_failure
  
  
  # XXX (ncoghlan): Move to script_helper and make consistent with run_python
  def _kill_python_and_exit_code(p):
      data = kill_python(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)
  
      def test_optimize(self):
          self.verify_valid_flag('-O')
          self.verify_valid_flag('-OO')
  
      def test_q(self):
          self.verify_valid_flag('-Qold')
          self.verify_valid_flag('-Qnew')
          self.verify_valid_flag('-Qwarn')
          self.verify_valid_flag('-Qwarnall')
  
      def test_site_flag(self):
          self.verify_valid_flag('-S')
  
      def test_usage(self):
          rc, out, err = assert_python_ok('-h')
          self.assertIn(b'usage', out)
  
      def test_version(self):
          version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii")
          rc, out, err = assert_python_ok('-V')
          self.assertTrue(err.startswith(version))
  
      def test_verbose(self):
          # -v causes imports to write to stderr.  If the write to
          # stderr itself causes an import to happen (for the output
          # codec), a recursion loop can occur.
          rc, out, err = assert_python_ok('-v')
          self.assertNotIn(b'stack overflow', err)
          rc, out, err = assert_python_ok('-vv')
          self.assertNotIn(b'stack overflow', err)
  
      def test_xoptions(self):
          rc, out, err = assert_python_ok('-c', 'import sys; print(sys._xoptions)')
          opts = eval(out.splitlines()[0])
          self.assertEqual(opts, {})
          rc, out, err = assert_python_ok(
              '-Xa', '-Xb=c,d=e', '-c', 'import sys; print(sys._xoptions)')
          opts = eval(out.splitlines()[0])
          self.assertEqual(opts, {'a': True, 'b': 'c,d=e'})
  
      def test_run_module(self):
          # Test expected operation of the '-m' switch
          # Switch needs an argument
          assert_python_failure('-m')
          # Check we get an error for a nonexistent module
          assert_python_failure('-m', 'fnord43520xyz')
          # Check the runpy module also gives an error for
          # a nonexistent module
          assert_python_failure('-m', 'runpy', 'fnord43520xyz'),
          # All good if module is located and run successfully
          assert_python_ok('-m', 'timeit', '-n', '1'),
  
      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_run_code(self):
          # Test expected operation of the '-c' switch
          # Switch needs an argument
          assert_python_failure('-c')
          # Check we get an error for an uncaught exception
          assert_python_failure('-c', 'raise Exception')
          # All good if execution is successful
          assert_python_ok('-c', 'pass')
  
      @unittest.skipIf(sys.getfilesystemencoding() == 'ascii',
                       'need a filesystem encoding different than ASCII')
      def test_non_ascii(self):
          # Test handling of non-ascii data
          if test.support.verbose:
              import locale
              print('locale encoding = %s, filesystem encoding = %s'
                    % (locale.getpreferredencoding(), sys.getfilesystemencoding()))
          command = "assert(ord('\xe9') == 0xe9)"
          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
      # arguments as unicode (using wmain() instead of main()).
      @unittest.skipIf(sys.platform == 'win32',
                       'Windows has a native unicode API')
      def test_undecodable_code(self):
          undecodable = b"\xff"
          env = os.environ.copy()
          # Use C locale to get ascii for the locale encoding
          env['LC_ALL'] = 'C'
          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,
              env=env)
          stdout, stderr = p.communicate()
          if p.returncode == 1:
              # _Py_char2wchar() decoded b'\xff' as '\udcff' (b'\xff' is not
              # decodable from ASCII) and run_command() failed on
              # PyUnicode_AsUTF8String(). This is the expected behaviour on
              # Linux.
              pattern = b"Unable to decode the command from the command line:"
          elif p.returncode == 0:
              # _Py_char2wchar() decoded b'\xff' as '\xff' even if the locale is
              # C and the locale encoding is ASCII. It occurs on FreeBSD, Solaris
              # and Mac OS X.
              pattern = b"'\\xff' "
              # The output is followed by the encoding name, an alias to ASCII.
              # Examples: "US-ASCII" or "646" (ISO 646, on Solaris).
          else:
              raise AssertionError("Unknown exit code: %s, output=%a" % (p.returncode, stdout))
          if not stdout.startswith(pattern):
              raise AssertionError("%a doesn't start with %a" % (stdout, pattern))
  
      @unittest.skipUnless(sys.platform == 'darwin', 'test specific to Mac OS X')
      def test_osx_utf8(self):
          def check_output(text):
              decoded = text.decode('utf8', 'surrogateescape')
              expected = ascii(decoded).encode('ascii') + b'\n'
  
              env = os.environ.copy()
              # C locale gives ASCII locale encoding, but Python uses UTF-8
              # to parse the command line arguments on Mac OS X
              env['LC_ALL'] = 'C'
  
              p = subprocess.Popen(
                  (sys.executable, "-c", "import sys; print(ascii(sys.argv[1]))", text),
                  stdout=subprocess.PIPE,
                  env=env)
              stdout, stderr = p.communicate()
              self.assertEqual(stdout, expected)
              self.assertEqual(p.returncode, 0)
  
          # test valid utf-8
          text = 'e:\xe9, euro:\u20ac, non-bmp:\U0010ffff'.encode('utf-8')
          check_output(text)
  
          # test invalid utf-8
          text = (
              b'\xff'         # invalid byte
              b'\xc3\xa9'     # valid utf-8 character
              b'\xc3\xff'     # invalid byte sequence
              b'\xed\xa0\x80' # lone surrogate character (invalid)
          )
          check_output(text)
  
      def test_unbuffered_output(self):
          # Test expected operation of the '-u' switch
          for stream in ('stdout', 'stderr'):
              # Binary is unbuffered
              code = ("import os, sys; sys.%s.buffer.write(b'x'); os._exit(0)"
                  % stream)
              rc, out, err = assert_python_ok('-u', '-c', code)
              data = err if stream == 'stderr' else out
              self.assertEqual(data, b'x', "binary %s not unbuffered" % stream)
              # Text is line-buffered
              code = ("import os, sys; sys.%s.write('x\\n'); os._exit(0)"
                  % stream)
              rc, out, err = assert_python_ok('-u', '-c', code)
              data = err if stream == 'stderr' else out
              self.assertEqual(data.strip(), b'x',
                  "text %s not line-buffered" % stream)
  
      def test_unbuffered_input(self):
          # sys.stdin still works with '-u'
          code = ("import sys; sys.stdout.write(sys.stdin.read(1))")
          p = spawn_python('-u', '-c', code)
          p.stdin.write(b'x')
          p.stdin.flush()
          data, rc = _kill_python_and_exit_code(p)
          self.assertEqual(rc, 0)
          self.assertTrue(data.startswith(b'x'), data)
  
      def test_large_PYTHONPATH(self):
          path1 = "ABCDE" * 100
          path2 = "FGHIJ" * 100
          path = path1 + os.pathsep + path2
  
          code = """if 1:
              import sys
              path = ":".join(sys.path)
              path = path.encode("ascii", "backslashreplace")
              sys.stdout.buffer.write(path)"""
          rc, out, err = assert_python_ok('-S', '-c', code,
                                          PYTHONPATH=path)
          self.assertIn(path1.encode('ascii'), out)
          self.assertIn(path2.encode('ascii'), out)
  
      def test_displayhook_unencodable(self):
          for encoding in ('ascii', 'latin1', 'utf8'):
              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 check_input(self, code, expected):
          with tempfile.NamedTemporaryFile("wb+") as stdin:
              sep = os.linesep.encode('ASCII')
              stdin.write(sep.join((b'abc', b'def')))
              stdin.flush()
              stdin.seek(0)
              with subprocess.Popen(
                  (sys.executable, "-c", code),
                  stdin=stdin, stdout=subprocess.PIPE) as proc:
                  stdout, stderr = proc.communicate()
          self.assertEqual(stdout.rstrip(), expected)
  
      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'")
  
      def test_builtin_input(self):
          # Issue #11272: check that input() strips newlines ('\n' or '\r\n')
          self.check_input(
              "print(repr(input()))",
              b"'abc'")
  
      def test_unmached_quote(self):
          # Issue #10206: python program starting with unmatched quote
          # spewed spaces to stdout
          rc, out, err = assert_python_failure('-c', "'")
          self.assertRegex(err.decode('ascii', 'ignore'), 'SyntaxError')
          self.assertEqual(b'', out)
  
  
  def test_main():
      test.support.run_unittest(CmdLineTest)
      test.support.reap_children()
  
  if __name__ == "__main__":
      test_main()
  