(root)/
Python-3.12.0/
Lib/
idlelib/
idle_test/
test_editor.py
       1  "Test editor, coverage 53%."
       2  
       3  from idlelib import editor
       4  import unittest
       5  from collections import namedtuple
       6  from test.support import requires
       7  from tkinter import Tk, Text
       8  
       9  Editor = editor.EditorWindow
      10  
      11  
      12  class ESC[4;38;5;81mEditorWindowTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      13  
      14      @classmethod
      15      def setUpClass(cls):
      16          requires('gui')
      17          cls.root = Tk()
      18          cls.root.withdraw()
      19  
      20      @classmethod
      21      def tearDownClass(cls):
      22          cls.root.update_idletasks()
      23          for id in cls.root.tk.call('after', 'info'):
      24              cls.root.after_cancel(id)
      25          cls.root.destroy()
      26          del cls.root
      27  
      28      def test_init(self):
      29          e = Editor(root=self.root)
      30          self.assertEqual(e.root, self.root)
      31          e._close()
      32  
      33  
      34  class ESC[4;38;5;81mGetLineIndentTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      35      def test_empty_lines(self):
      36          for tabwidth in [1, 2, 4, 6, 8]:
      37              for line in ['', '\n']:
      38                  with self.subTest(line=line, tabwidth=tabwidth):
      39                      self.assertEqual(
      40                          editor.get_line_indent(line, tabwidth=tabwidth),
      41                          (0, 0),
      42                      )
      43  
      44      def test_tabwidth_4(self):
      45          #        (line, (raw, effective))
      46          tests = (('no spaces', (0, 0)),
      47                   # Internal space isn't counted.
      48                   ('    space test', (4, 4)),
      49                   ('\ttab test', (1, 4)),
      50                   ('\t\tdouble tabs test', (2, 8)),
      51                   # Different results when mixing tabs and spaces.
      52                   ('    \tmixed test', (5, 8)),
      53                   ('  \t  mixed test', (5, 6)),
      54                   ('\t    mixed test', (5, 8)),
      55                   # Spaces not divisible by tabwidth.
      56                   ('  \tmixed test', (3, 4)),
      57                   (' \t mixed test', (3, 5)),
      58                   ('\t  mixed test', (3, 6)),
      59                   # Only checks spaces and tabs.
      60                   ('\nnewline test', (0, 0)))
      61  
      62          for line, expected in tests:
      63              with self.subTest(line=line):
      64                  self.assertEqual(
      65                      editor.get_line_indent(line, tabwidth=4),
      66                      expected,
      67                  )
      68  
      69      def test_tabwidth_8(self):
      70          #        (line, (raw, effective))
      71          tests = (('no spaces', (0, 0)),
      72                   # Internal space isn't counted.
      73                   ('        space test', (8, 8)),
      74                   ('\ttab test', (1, 8)),
      75                   ('\t\tdouble tabs test', (2, 16)),
      76                   # Different results when mixing tabs and spaces.
      77                   ('        \tmixed test', (9, 16)),
      78                   ('      \t  mixed test', (9, 10)),
      79                   ('\t        mixed test', (9, 16)),
      80                   # Spaces not divisible by tabwidth.
      81                   ('  \tmixed test', (3, 8)),
      82                   (' \t mixed test', (3, 9)),
      83                   ('\t  mixed test', (3, 10)),
      84                   # Only checks spaces and tabs.
      85                   ('\nnewline test', (0, 0)))
      86  
      87          for line, expected in tests:
      88              with self.subTest(line=line):
      89                  self.assertEqual(
      90                      editor.get_line_indent(line, tabwidth=8),
      91                      expected,
      92                  )
      93  
      94  
      95  def insert(text, string):
      96      text.delete('1.0', 'end')
      97      text.insert('end', string)
      98      text.update()  # Force update for colorizer to finish.
      99  
     100  
     101  class ESC[4;38;5;81mIndentAndNewlineTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     102  
     103      @classmethod
     104      def setUpClass(cls):
     105          requires('gui')
     106          cls.root = Tk()
     107          cls.root.withdraw()
     108          cls.window = Editor(root=cls.root)
     109          cls.window.indentwidth = 2
     110          cls.window.tabwidth = 2
     111  
     112      @classmethod
     113      def tearDownClass(cls):
     114          cls.window._close()
     115          del cls.window
     116          cls.root.update_idletasks()
     117          for id in cls.root.tk.call('after', 'info'):
     118              cls.root.after_cancel(id)
     119          cls.root.destroy()
     120          del cls.root
     121  
     122      def test_indent_and_newline_event(self):
     123          eq = self.assertEqual
     124          w = self.window
     125          text = w.text
     126          get = text.get
     127          nl = w.newline_and_indent_event
     128  
     129          TestInfo = namedtuple('Tests', ['label', 'text', 'expected', 'mark'])
     130  
     131          tests = (TestInfo('Empty line inserts with no indent.',
     132                            '  \n  def __init__(self):',
     133                            '\n  \n  def __init__(self):\n',
     134                            '1.end'),
     135                   TestInfo('Inside bracket before space, deletes space.',
     136                            '  def f1(self, a, b):',
     137                            '  def f1(self,\n         a, b):\n',
     138                            '1.14'),
     139                   TestInfo('Inside bracket after space, deletes space.',
     140                            '  def f1(self, a, b):',
     141                            '  def f1(self,\n         a, b):\n',
     142                            '1.15'),
     143                   TestInfo('Inside string with one line - no indent.',
     144                            '  """Docstring."""',
     145                            '  """Docstring.\n"""\n',
     146                            '1.15'),
     147                   TestInfo('Inside string with more than one line.',
     148                            '  """Docstring.\n  Docstring Line 2"""',
     149                            '  """Docstring.\n  Docstring Line 2\n  """\n',
     150                            '2.18'),
     151                   TestInfo('Backslash with one line.',
     152                            'a =\\',
     153                            'a =\\\n  \n',
     154                            '1.end'),
     155                   TestInfo('Backslash with more than one line.',
     156                            'a =\\\n          multiline\\',
     157                            'a =\\\n          multiline\\\n          \n',
     158                            '2.end'),
     159                   TestInfo('Block opener - indents +1 level.',
     160                            '  def f1(self):\n    pass',
     161                            '  def f1(self):\n    \n    pass\n',
     162                            '1.end'),
     163                   TestInfo('Block closer - dedents -1 level.',
     164                            '  def f1(self):\n    pass',
     165                            '  def f1(self):\n    pass\n  \n',
     166                            '2.end'),
     167                   )
     168  
     169          for test in tests:
     170              with self.subTest(label=test.label):
     171                  insert(text, test.text)
     172                  text.mark_set('insert', test.mark)
     173                  nl(event=None)
     174                  eq(get('1.0', 'end'), test.expected)
     175  
     176          # Selected text.
     177          insert(text, '  def f1(self, a, b):\n    return a + b')
     178          text.tag_add('sel', '1.17', '1.end')
     179          nl(None)
     180          # Deletes selected text before adding new line.
     181          eq(get('1.0', 'end'), '  def f1(self, a,\n         \n    return a + b\n')
     182  
     183  
     184  class ESC[4;38;5;81mIndentSearcherTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     185  
     186      @classmethod
     187      def setUpClass(cls):
     188          requires('gui')
     189          cls.root = Tk()
     190          cls.root.withdraw()
     191          cls.text = Text(cls.root)
     192  
     193      @classmethod
     194      def tearDownClass(cls):
     195          cls.root.destroy()
     196          del cls.root
     197  
     198      def test_searcher(self):
     199          text = self.text
     200          searcher = (self.text)
     201          test_info = (# text, (block, indent))
     202                       ("", (None, None)),
     203                       ("[1,", (None, None)),  # TokenError
     204                       ("if 1:\n", ('if 1:\n', None)),
     205                       ("if 1:\n  2\n  3\n", ('if 1:\n', '  2\n')),
     206                       )
     207          for code, expected_pair in test_info:
     208              with self.subTest(code=code):
     209                  insert(text, code)
     210                  actual_pair = editor.IndentSearcher(text).run()
     211                  self.assertEqual(actual_pair, expected_pair)
     212  
     213  
     214  class ESC[4;38;5;81mRMenuTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     215  
     216      @classmethod
     217      def setUpClass(cls):
     218          requires('gui')
     219          cls.root = Tk()
     220          cls.root.withdraw()
     221          cls.window = Editor(root=cls.root)
     222  
     223      @classmethod
     224      def tearDownClass(cls):
     225          cls.window._close()
     226          del cls.window
     227          cls.root.update_idletasks()
     228          for id in cls.root.tk.call('after', 'info'):
     229              cls.root.after_cancel(id)
     230          cls.root.destroy()
     231          del cls.root
     232  
     233      class ESC[4;38;5;81mDummyRMenu:
     234          def tk_popup(x, y): pass
     235  
     236      def test_rclick(self):
     237          pass
     238  
     239  
     240  if __name__ == '__main__':
     241      unittest.main(verbosity=2)