(root)/
Python-3.12.0/
Lib/
idlelib/
idle_test/
test_run.py
       1  "Test run, coverage 54%."
       2  
       3  from idlelib import run
       4  import io
       5  import sys
       6  from test.support import captured_output, captured_stderr
       7  import unittest
       8  from unittest import mock
       9  import idlelib
      10  from idlelib.idle_test.mock_idle import Func
      11  
      12  idlelib.testing = True  # Use {} for executing test user code.
      13  
      14  
      15  class ESC[4;38;5;81mExceptionTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      16  
      17      def test_print_exception_unhashable(self):
      18          class ESC[4;38;5;81mUnhashableException(ESC[4;38;5;149mException):
      19              def __eq__(self, other):
      20                  return True
      21  
      22          ex1 = UnhashableException('ex1')
      23          ex2 = UnhashableException('ex2')
      24          try:
      25              raise ex2 from ex1
      26          except UnhashableException:
      27              try:
      28                  raise ex1
      29              except UnhashableException:
      30                  with captured_stderr() as output:
      31                      with mock.patch.object(run, 'cleanup_traceback') as ct:
      32                          ct.side_effect = lambda t, e: t
      33                          run.print_exception()
      34  
      35          tb = output.getvalue().strip().splitlines()
      36          self.assertEqual(11, len(tb))
      37          self.assertIn('UnhashableException: ex2', tb[3])
      38          self.assertIn('UnhashableException: ex1', tb[10])
      39  
      40      data = (('1/0', ZeroDivisionError, "division by zero\n"),
      41              ('abc', NameError, "name 'abc' is not defined. "
      42                                 "Did you mean: 'abs'? "
      43                                 "Or did you forget to import 'abc'?\n"),
      44              ('int.reel', AttributeError,
      45                   "type object 'int' has no attribute 'reel'. "
      46                   "Did you mean: 'real'?\n"),
      47              )
      48  
      49      def test_get_message(self):
      50          for code, exc, msg in self.data:
      51              with self.subTest(code=code):
      52                  try:
      53                      eval(compile(code, '', 'eval'))
      54                  except exc:
      55                      typ, val, tb = sys.exc_info()
      56                      actual = run.get_message_lines(typ, val, tb)[0]
      57                      expect = f'{exc.__name__}: {msg}'
      58                      self.assertEqual(actual, expect)
      59  
      60      @mock.patch.object(run, 'cleanup_traceback',
      61                         new_callable=lambda: (lambda t, e: None))
      62      def test_get_multiple_message(self, mock):
      63          d = self.data
      64          data2 = ((d[0], d[1]), (d[1], d[2]), (d[2], d[0]))
      65          subtests = 0
      66          for (code1, exc1, msg1), (code2, exc2, msg2) in data2:
      67              with self.subTest(codes=(code1,code2)):
      68                  try:
      69                      eval(compile(code1, '', 'eval'))
      70                  except exc1:
      71                      try:
      72                          eval(compile(code2, '', 'eval'))
      73                      except exc2:
      74                          with captured_stderr() as output:
      75                              run.print_exception()
      76                          actual = output.getvalue()
      77                          self.assertIn(msg1, actual)
      78                          self.assertIn(msg2, actual)
      79                          subtests += 1
      80          self.assertEqual(subtests, len(data2))  # All subtests ran?
      81  
      82  # StdioFile tests.
      83  
      84  class ESC[4;38;5;81mS(ESC[4;38;5;149mstr):
      85      def __str__(self):
      86          return '%s:str' % type(self).__name__
      87      def __unicode__(self):
      88          return '%s:unicode' % type(self).__name__
      89      def __len__(self):
      90          return 3
      91      def __iter__(self):
      92          return iter('abc')
      93      def __getitem__(self, *args):
      94          return '%s:item' % type(self).__name__
      95      def __getslice__(self, *args):
      96          return '%s:slice' % type(self).__name__
      97  
      98  
      99  class ESC[4;38;5;81mMockShell:
     100      def __init__(self):
     101          self.reset()
     102      def write(self, *args):
     103          self.written.append(args)
     104      def readline(self):
     105          return self.lines.pop()
     106      def close(self):
     107          pass
     108      def reset(self):
     109          self.written = []
     110      def push(self, lines):
     111          self.lines = list(lines)[::-1]
     112  
     113  
     114  class ESC[4;38;5;81mStdInputFilesTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     115  
     116      def test_misc(self):
     117          shell = MockShell()
     118          f = run.StdInputFile(shell, 'stdin')
     119          self.assertIsInstance(f, io.TextIOBase)
     120          self.assertEqual(f.encoding, 'utf-8')
     121          self.assertEqual(f.errors, 'strict')
     122          self.assertIsNone(f.newlines)
     123          self.assertEqual(f.name, '<stdin>')
     124          self.assertFalse(f.closed)
     125          self.assertTrue(f.isatty())
     126          self.assertTrue(f.readable())
     127          self.assertFalse(f.writable())
     128          self.assertFalse(f.seekable())
     129  
     130      def test_unsupported(self):
     131          shell = MockShell()
     132          f = run.StdInputFile(shell, 'stdin')
     133          self.assertRaises(OSError, f.fileno)
     134          self.assertRaises(OSError, f.tell)
     135          self.assertRaises(OSError, f.seek, 0)
     136          self.assertRaises(OSError, f.write, 'x')
     137          self.assertRaises(OSError, f.writelines, ['x'])
     138  
     139      def test_read(self):
     140          shell = MockShell()
     141          f = run.StdInputFile(shell, 'stdin')
     142          shell.push(['one\n', 'two\n', ''])
     143          self.assertEqual(f.read(), 'one\ntwo\n')
     144          shell.push(['one\n', 'two\n', ''])
     145          self.assertEqual(f.read(-1), 'one\ntwo\n')
     146          shell.push(['one\n', 'two\n', ''])
     147          self.assertEqual(f.read(None), 'one\ntwo\n')
     148          shell.push(['one\n', 'two\n', 'three\n', ''])
     149          self.assertEqual(f.read(2), 'on')
     150          self.assertEqual(f.read(3), 'e\nt')
     151          self.assertEqual(f.read(10), 'wo\nthree\n')
     152  
     153          shell.push(['one\n', 'two\n'])
     154          self.assertEqual(f.read(0), '')
     155          self.assertRaises(TypeError, f.read, 1.5)
     156          self.assertRaises(TypeError, f.read, '1')
     157          self.assertRaises(TypeError, f.read, 1, 1)
     158  
     159      def test_readline(self):
     160          shell = MockShell()
     161          f = run.StdInputFile(shell, 'stdin')
     162          shell.push(['one\n', 'two\n', 'three\n', 'four\n'])
     163          self.assertEqual(f.readline(), 'one\n')
     164          self.assertEqual(f.readline(-1), 'two\n')
     165          self.assertEqual(f.readline(None), 'three\n')
     166          shell.push(['one\ntwo\n'])
     167          self.assertEqual(f.readline(), 'one\n')
     168          self.assertEqual(f.readline(), 'two\n')
     169          shell.push(['one', 'two', 'three'])
     170          self.assertEqual(f.readline(), 'one')
     171          self.assertEqual(f.readline(), 'two')
     172          shell.push(['one\n', 'two\n', 'three\n'])
     173          self.assertEqual(f.readline(2), 'on')
     174          self.assertEqual(f.readline(1), 'e')
     175          self.assertEqual(f.readline(1), '\n')
     176          self.assertEqual(f.readline(10), 'two\n')
     177  
     178          shell.push(['one\n', 'two\n'])
     179          self.assertEqual(f.readline(0), '')
     180          self.assertRaises(TypeError, f.readlines, 1.5)
     181          self.assertRaises(TypeError, f.readlines, '1')
     182          self.assertRaises(TypeError, f.readlines, 1, 1)
     183  
     184      def test_readlines(self):
     185          shell = MockShell()
     186          f = run.StdInputFile(shell, 'stdin')
     187          shell.push(['one\n', 'two\n', ''])
     188          self.assertEqual(f.readlines(), ['one\n', 'two\n'])
     189          shell.push(['one\n', 'two\n', ''])
     190          self.assertEqual(f.readlines(-1), ['one\n', 'two\n'])
     191          shell.push(['one\n', 'two\n', ''])
     192          self.assertEqual(f.readlines(None), ['one\n', 'two\n'])
     193          shell.push(['one\n', 'two\n', ''])
     194          self.assertEqual(f.readlines(0), ['one\n', 'two\n'])
     195          shell.push(['one\n', 'two\n', ''])
     196          self.assertEqual(f.readlines(3), ['one\n'])
     197          shell.push(['one\n', 'two\n', ''])
     198          self.assertEqual(f.readlines(4), ['one\n', 'two\n'])
     199  
     200          shell.push(['one\n', 'two\n', ''])
     201          self.assertRaises(TypeError, f.readlines, 1.5)
     202          self.assertRaises(TypeError, f.readlines, '1')
     203          self.assertRaises(TypeError, f.readlines, 1, 1)
     204  
     205      def test_close(self):
     206          shell = MockShell()
     207          f = run.StdInputFile(shell, 'stdin')
     208          shell.push(['one\n', 'two\n', ''])
     209          self.assertFalse(f.closed)
     210          self.assertEqual(f.readline(), 'one\n')
     211          f.close()
     212          self.assertFalse(f.closed)
     213          self.assertEqual(f.readline(), 'two\n')
     214          self.assertRaises(TypeError, f.close, 1)
     215  
     216  
     217  class ESC[4;38;5;81mStdOutputFilesTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     218  
     219      def test_misc(self):
     220          shell = MockShell()
     221          f = run.StdOutputFile(shell, 'stdout')
     222          self.assertIsInstance(f, io.TextIOBase)
     223          self.assertEqual(f.encoding, 'utf-8')
     224          self.assertEqual(f.errors, 'strict')
     225          self.assertIsNone(f.newlines)
     226          self.assertEqual(f.name, '<stdout>')
     227          self.assertFalse(f.closed)
     228          self.assertTrue(f.isatty())
     229          self.assertFalse(f.readable())
     230          self.assertTrue(f.writable())
     231          self.assertFalse(f.seekable())
     232  
     233      def test_unsupported(self):
     234          shell = MockShell()
     235          f = run.StdOutputFile(shell, 'stdout')
     236          self.assertRaises(OSError, f.fileno)
     237          self.assertRaises(OSError, f.tell)
     238          self.assertRaises(OSError, f.seek, 0)
     239          self.assertRaises(OSError, f.read, 0)
     240          self.assertRaises(OSError, f.readline, 0)
     241  
     242      def test_write(self):
     243          shell = MockShell()
     244          f = run.StdOutputFile(shell, 'stdout')
     245          f.write('test')
     246          self.assertEqual(shell.written, [('test', 'stdout')])
     247          shell.reset()
     248          f.write('t\xe8\u015b\U0001d599')
     249          self.assertEqual(shell.written, [('t\xe8\u015b\U0001d599', 'stdout')])
     250          shell.reset()
     251  
     252          f.write(S('t\xe8\u015b\U0001d599'))
     253          self.assertEqual(shell.written, [('t\xe8\u015b\U0001d599', 'stdout')])
     254          self.assertEqual(type(shell.written[0][0]), str)
     255          shell.reset()
     256  
     257          self.assertRaises(TypeError, f.write)
     258          self.assertEqual(shell.written, [])
     259          self.assertRaises(TypeError, f.write, b'test')
     260          self.assertRaises(TypeError, f.write, 123)
     261          self.assertEqual(shell.written, [])
     262          self.assertRaises(TypeError, f.write, 'test', 'spam')
     263          self.assertEqual(shell.written, [])
     264  
     265      def test_write_stderr_nonencodable(self):
     266          shell = MockShell()
     267          f = run.StdOutputFile(shell, 'stderr', 'iso-8859-15', 'backslashreplace')
     268          f.write('t\xe8\u015b\U0001d599\xa4')
     269          self.assertEqual(shell.written, [('t\xe8\\u015b\\U0001d599\\xa4', 'stderr')])
     270          shell.reset()
     271  
     272          f.write(S('t\xe8\u015b\U0001d599\xa4'))
     273          self.assertEqual(shell.written, [('t\xe8\\u015b\\U0001d599\\xa4', 'stderr')])
     274          self.assertEqual(type(shell.written[0][0]), str)
     275          shell.reset()
     276  
     277          self.assertRaises(TypeError, f.write)
     278          self.assertEqual(shell.written, [])
     279          self.assertRaises(TypeError, f.write, b'test')
     280          self.assertRaises(TypeError, f.write, 123)
     281          self.assertEqual(shell.written, [])
     282          self.assertRaises(TypeError, f.write, 'test', 'spam')
     283          self.assertEqual(shell.written, [])
     284  
     285      def test_writelines(self):
     286          shell = MockShell()
     287          f = run.StdOutputFile(shell, 'stdout')
     288          f.writelines([])
     289          self.assertEqual(shell.written, [])
     290          shell.reset()
     291          f.writelines(['one\n', 'two'])
     292          self.assertEqual(shell.written,
     293                           [('one\n', 'stdout'), ('two', 'stdout')])
     294          shell.reset()
     295          f.writelines(['on\xe8\n', 'tw\xf2'])
     296          self.assertEqual(shell.written,
     297                           [('on\xe8\n', 'stdout'), ('tw\xf2', 'stdout')])
     298          shell.reset()
     299  
     300          f.writelines([S('t\xe8st')])
     301          self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
     302          self.assertEqual(type(shell.written[0][0]), str)
     303          shell.reset()
     304  
     305          self.assertRaises(TypeError, f.writelines)
     306          self.assertEqual(shell.written, [])
     307          self.assertRaises(TypeError, f.writelines, 123)
     308          self.assertEqual(shell.written, [])
     309          self.assertRaises(TypeError, f.writelines, [b'test'])
     310          self.assertRaises(TypeError, f.writelines, [123])
     311          self.assertEqual(shell.written, [])
     312          self.assertRaises(TypeError, f.writelines, [], [])
     313          self.assertEqual(shell.written, [])
     314  
     315      def test_close(self):
     316          shell = MockShell()
     317          f = run.StdOutputFile(shell, 'stdout')
     318          self.assertFalse(f.closed)
     319          f.write('test')
     320          f.close()
     321          self.assertTrue(f.closed)
     322          self.assertRaises(ValueError, f.write, 'x')
     323          self.assertEqual(shell.written, [('test', 'stdout')])
     324          f.close()
     325          self.assertRaises(TypeError, f.close, 1)
     326  
     327  
     328  class ESC[4;38;5;81mRecursionLimitTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     329      # Test (un)install_recursionlimit_wrappers and fixdoc.
     330  
     331      def test_bad_setrecursionlimit_calls(self):
     332          run.install_recursionlimit_wrappers()
     333          self.addCleanup(run.uninstall_recursionlimit_wrappers)
     334          f = sys.setrecursionlimit
     335          self.assertRaises(TypeError, f, limit=100)
     336          self.assertRaises(TypeError, f, 100, 1000)
     337          self.assertRaises(ValueError, f, 0)
     338  
     339      def test_roundtrip(self):
     340          run.install_recursionlimit_wrappers()
     341          self.addCleanup(run.uninstall_recursionlimit_wrappers)
     342  
     343          # Check that setting the recursion limit works.
     344          orig_reclimit = sys.getrecursionlimit()
     345          self.addCleanup(sys.setrecursionlimit, orig_reclimit)
     346          sys.setrecursionlimit(orig_reclimit + 3)
     347  
     348          # Check that the new limit is returned by sys.getrecursionlimit().
     349          new_reclimit = sys.getrecursionlimit()
     350          self.assertEqual(new_reclimit, orig_reclimit + 3)
     351  
     352      def test_default_recursion_limit_preserved(self):
     353          orig_reclimit = sys.getrecursionlimit()
     354          run.install_recursionlimit_wrappers()
     355          self.addCleanup(run.uninstall_recursionlimit_wrappers)
     356          new_reclimit = sys.getrecursionlimit()
     357          self.assertEqual(new_reclimit, orig_reclimit)
     358  
     359      def test_fixdoc(self):
     360          # Put here until better place for miscellaneous test.
     361          def func(): "docstring"
     362          run.fixdoc(func, "more")
     363          self.assertEqual(func.__doc__, "docstring\n\nmore")
     364          func.__doc__ = None
     365          run.fixdoc(func, "more")
     366          self.assertEqual(func.__doc__, "more")
     367  
     368  
     369  class ESC[4;38;5;81mHandleErrorTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     370      # Method of MyRPCServer
     371      def test_fatal_error(self):
     372          eq = self.assertEqual
     373          with captured_output('__stderr__') as err,\
     374               mock.patch('idlelib.run.thread.interrupt_main',
     375                          new_callable=Func) as func:
     376              try:
     377                  raise EOFError
     378              except EOFError:
     379                  run.MyRPCServer.handle_error(None, 'abc', '123')
     380              eq(run.exit_now, True)
     381              run.exit_now = False
     382              eq(err.getvalue(), '')
     383  
     384              try:
     385                  raise IndexError
     386              except IndexError:
     387                  run.MyRPCServer.handle_error(None, 'abc', '123')
     388              eq(run.quitting, True)
     389              run.quitting = False
     390              msg = err.getvalue()
     391              self.assertIn('abc', msg)
     392              self.assertIn('123', msg)
     393              self.assertIn('IndexError', msg)
     394              eq(func.called, 2)
     395  
     396  
     397  class ESC[4;38;5;81mExecRuncodeTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     398  
     399      @classmethod
     400      def setUpClass(cls):
     401          cls.addClassCleanup(setattr,run,'print_exception',run.print_exception)
     402          cls.prt = Func()  # Need reference.
     403          run.print_exception = cls.prt
     404          mockrpc = mock.Mock()
     405          mockrpc.console.getvar = Func(result=False)
     406          cls.ex = run.Executive(mockrpc)
     407  
     408      @classmethod
     409      def tearDownClass(cls):
     410          assert sys.excepthook == sys.__excepthook__
     411  
     412      def test_exceptions(self):
     413          ex = self.ex
     414          ex.runcode('1/0')
     415          self.assertIs(ex.user_exc_info[0], ZeroDivisionError)
     416  
     417          self.addCleanup(setattr, sys, 'excepthook', sys.__excepthook__)
     418          sys.excepthook = lambda t, e, tb: run.print_exception(t)
     419          ex.runcode('1/0')
     420          self.assertIs(self.prt.args[0], ZeroDivisionError)
     421  
     422          sys.excepthook = lambda: None
     423          ex.runcode('1/0')
     424          t, e, tb = ex.user_exc_info
     425          self.assertIs(t, TypeError)
     426          self.assertTrue(isinstance(e.__context__, ZeroDivisionError))
     427  
     428  
     429  if __name__ == '__main__':
     430      unittest.main(verbosity=2)