• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"Test run, coverage 49%."
2
3from idlelib import run
4import unittest
5from unittest import mock
6from idlelib.idle_test.mock_idle import Func
7from test.support import captured_output, captured_stderr
8
9import io
10import sys
11
12
13class RunTest(unittest.TestCase):
14
15    def test_print_exception_unhashable(self):
16        class UnhashableException(Exception):
17            def __eq__(self, other):
18                return True
19
20        ex1 = UnhashableException('ex1')
21        ex2 = UnhashableException('ex2')
22        try:
23            raise ex2 from ex1
24        except UnhashableException:
25            try:
26                raise ex1
27            except UnhashableException:
28                with captured_stderr() as output:
29                    with mock.patch.object(run,
30                                           'cleanup_traceback') as ct:
31                        ct.side_effect = lambda t, e: t
32                        run.print_exception()
33
34        tb = output.getvalue().strip().splitlines()
35        self.assertEqual(11, len(tb))
36        self.assertIn('UnhashableException: ex2', tb[3])
37        self.assertIn('UnhashableException: ex1', tb[10])
38
39
40# StdioFile tests.
41
42class S(str):
43    def __str__(self):
44        return '%s:str' % type(self).__name__
45    def __unicode__(self):
46        return '%s:unicode' % type(self).__name__
47    def __len__(self):
48        return 3
49    def __iter__(self):
50        return iter('abc')
51    def __getitem__(self, *args):
52        return '%s:item' % type(self).__name__
53    def __getslice__(self, *args):
54        return '%s:slice' % type(self).__name__
55
56
57class MockShell:
58    def __init__(self):
59        self.reset()
60    def write(self, *args):
61        self.written.append(args)
62    def readline(self):
63        return self.lines.pop()
64    def close(self):
65        pass
66    def reset(self):
67        self.written = []
68    def push(self, lines):
69        self.lines = list(lines)[::-1]
70
71
72class StdInputFilesTest(unittest.TestCase):
73
74    def test_misc(self):
75        shell = MockShell()
76        f = run.StdInputFile(shell, 'stdin')
77        self.assertIsInstance(f, io.TextIOBase)
78        self.assertEqual(f.encoding, 'utf-8')
79        self.assertEqual(f.errors, 'strict')
80        self.assertIsNone(f.newlines)
81        self.assertEqual(f.name, '<stdin>')
82        self.assertFalse(f.closed)
83        self.assertTrue(f.isatty())
84        self.assertTrue(f.readable())
85        self.assertFalse(f.writable())
86        self.assertFalse(f.seekable())
87
88    def test_unsupported(self):
89        shell = MockShell()
90        f = run.StdInputFile(shell, 'stdin')
91        self.assertRaises(OSError, f.fileno)
92        self.assertRaises(OSError, f.tell)
93        self.assertRaises(OSError, f.seek, 0)
94        self.assertRaises(OSError, f.write, 'x')
95        self.assertRaises(OSError, f.writelines, ['x'])
96
97    def test_read(self):
98        shell = MockShell()
99        f = run.StdInputFile(shell, 'stdin')
100        shell.push(['one\n', 'two\n', ''])
101        self.assertEqual(f.read(), 'one\ntwo\n')
102        shell.push(['one\n', 'two\n', ''])
103        self.assertEqual(f.read(-1), 'one\ntwo\n')
104        shell.push(['one\n', 'two\n', ''])
105        self.assertEqual(f.read(None), 'one\ntwo\n')
106        shell.push(['one\n', 'two\n', 'three\n', ''])
107        self.assertEqual(f.read(2), 'on')
108        self.assertEqual(f.read(3), 'e\nt')
109        self.assertEqual(f.read(10), 'wo\nthree\n')
110
111        shell.push(['one\n', 'two\n'])
112        self.assertEqual(f.read(0), '')
113        self.assertRaises(TypeError, f.read, 1.5)
114        self.assertRaises(TypeError, f.read, '1')
115        self.assertRaises(TypeError, f.read, 1, 1)
116
117    def test_readline(self):
118        shell = MockShell()
119        f = run.StdInputFile(shell, 'stdin')
120        shell.push(['one\n', 'two\n', 'three\n', 'four\n'])
121        self.assertEqual(f.readline(), 'one\n')
122        self.assertEqual(f.readline(-1), 'two\n')
123        self.assertEqual(f.readline(None), 'three\n')
124        shell.push(['one\ntwo\n'])
125        self.assertEqual(f.readline(), 'one\n')
126        self.assertEqual(f.readline(), 'two\n')
127        shell.push(['one', 'two', 'three'])
128        self.assertEqual(f.readline(), 'one')
129        self.assertEqual(f.readline(), 'two')
130        shell.push(['one\n', 'two\n', 'three\n'])
131        self.assertEqual(f.readline(2), 'on')
132        self.assertEqual(f.readline(1), 'e')
133        self.assertEqual(f.readline(1), '\n')
134        self.assertEqual(f.readline(10), 'two\n')
135
136        shell.push(['one\n', 'two\n'])
137        self.assertEqual(f.readline(0), '')
138        self.assertRaises(TypeError, f.readlines, 1.5)
139        self.assertRaises(TypeError, f.readlines, '1')
140        self.assertRaises(TypeError, f.readlines, 1, 1)
141
142    def test_readlines(self):
143        shell = MockShell()
144        f = run.StdInputFile(shell, 'stdin')
145        shell.push(['one\n', 'two\n', ''])
146        self.assertEqual(f.readlines(), ['one\n', 'two\n'])
147        shell.push(['one\n', 'two\n', ''])
148        self.assertEqual(f.readlines(-1), ['one\n', 'two\n'])
149        shell.push(['one\n', 'two\n', ''])
150        self.assertEqual(f.readlines(None), ['one\n', 'two\n'])
151        shell.push(['one\n', 'two\n', ''])
152        self.assertEqual(f.readlines(0), ['one\n', 'two\n'])
153        shell.push(['one\n', 'two\n', ''])
154        self.assertEqual(f.readlines(3), ['one\n'])
155        shell.push(['one\n', 'two\n', ''])
156        self.assertEqual(f.readlines(4), ['one\n', 'two\n'])
157
158        shell.push(['one\n', 'two\n', ''])
159        self.assertRaises(TypeError, f.readlines, 1.5)
160        self.assertRaises(TypeError, f.readlines, '1')
161        self.assertRaises(TypeError, f.readlines, 1, 1)
162
163    def test_close(self):
164        shell = MockShell()
165        f = run.StdInputFile(shell, 'stdin')
166        shell.push(['one\n', 'two\n', ''])
167        self.assertFalse(f.closed)
168        self.assertEqual(f.readline(), 'one\n')
169        f.close()
170        self.assertFalse(f.closed)
171        self.assertEqual(f.readline(), 'two\n')
172        self.assertRaises(TypeError, f.close, 1)
173
174
175class StdOutputFilesTest(unittest.TestCase):
176
177    def test_misc(self):
178        shell = MockShell()
179        f = run.StdOutputFile(shell, 'stdout')
180        self.assertIsInstance(f, io.TextIOBase)
181        self.assertEqual(f.encoding, 'utf-8')
182        self.assertEqual(f.errors, 'strict')
183        self.assertIsNone(f.newlines)
184        self.assertEqual(f.name, '<stdout>')
185        self.assertFalse(f.closed)
186        self.assertTrue(f.isatty())
187        self.assertFalse(f.readable())
188        self.assertTrue(f.writable())
189        self.assertFalse(f.seekable())
190
191    def test_unsupported(self):
192        shell = MockShell()
193        f = run.StdOutputFile(shell, 'stdout')
194        self.assertRaises(OSError, f.fileno)
195        self.assertRaises(OSError, f.tell)
196        self.assertRaises(OSError, f.seek, 0)
197        self.assertRaises(OSError, f.read, 0)
198        self.assertRaises(OSError, f.readline, 0)
199
200    def test_write(self):
201        shell = MockShell()
202        f = run.StdOutputFile(shell, 'stdout')
203        f.write('test')
204        self.assertEqual(shell.written, [('test', 'stdout')])
205        shell.reset()
206        f.write('t\xe8\u015b\U0001d599')
207        self.assertEqual(shell.written, [('t\xe8\u015b\U0001d599', 'stdout')])
208        shell.reset()
209
210        f.write(S('t\xe8\u015b\U0001d599'))
211        self.assertEqual(shell.written, [('t\xe8\u015b\U0001d599', 'stdout')])
212        self.assertEqual(type(shell.written[0][0]), str)
213        shell.reset()
214
215        self.assertRaises(TypeError, f.write)
216        self.assertEqual(shell.written, [])
217        self.assertRaises(TypeError, f.write, b'test')
218        self.assertRaises(TypeError, f.write, 123)
219        self.assertEqual(shell.written, [])
220        self.assertRaises(TypeError, f.write, 'test', 'spam')
221        self.assertEqual(shell.written, [])
222
223    def test_write_stderr_nonencodable(self):
224        shell = MockShell()
225        f = run.StdOutputFile(shell, 'stderr', 'iso-8859-15', 'backslashreplace')
226        f.write('t\xe8\u015b\U0001d599\xa4')
227        self.assertEqual(shell.written, [('t\xe8\\u015b\\U0001d599\\xa4', 'stderr')])
228        shell.reset()
229
230        f.write(S('t\xe8\u015b\U0001d599\xa4'))
231        self.assertEqual(shell.written, [('t\xe8\\u015b\\U0001d599\\xa4', 'stderr')])
232        self.assertEqual(type(shell.written[0][0]), str)
233        shell.reset()
234
235        self.assertRaises(TypeError, f.write)
236        self.assertEqual(shell.written, [])
237        self.assertRaises(TypeError, f.write, b'test')
238        self.assertRaises(TypeError, f.write, 123)
239        self.assertEqual(shell.written, [])
240        self.assertRaises(TypeError, f.write, 'test', 'spam')
241        self.assertEqual(shell.written, [])
242
243    def test_writelines(self):
244        shell = MockShell()
245        f = run.StdOutputFile(shell, 'stdout')
246        f.writelines([])
247        self.assertEqual(shell.written, [])
248        shell.reset()
249        f.writelines(['one\n', 'two'])
250        self.assertEqual(shell.written,
251                         [('one\n', 'stdout'), ('two', 'stdout')])
252        shell.reset()
253        f.writelines(['on\xe8\n', 'tw\xf2'])
254        self.assertEqual(shell.written,
255                         [('on\xe8\n', 'stdout'), ('tw\xf2', 'stdout')])
256        shell.reset()
257
258        f.writelines([S('t\xe8st')])
259        self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
260        self.assertEqual(type(shell.written[0][0]), str)
261        shell.reset()
262
263        self.assertRaises(TypeError, f.writelines)
264        self.assertEqual(shell.written, [])
265        self.assertRaises(TypeError, f.writelines, 123)
266        self.assertEqual(shell.written, [])
267        self.assertRaises(TypeError, f.writelines, [b'test'])
268        self.assertRaises(TypeError, f.writelines, [123])
269        self.assertEqual(shell.written, [])
270        self.assertRaises(TypeError, f.writelines, [], [])
271        self.assertEqual(shell.written, [])
272
273    def test_close(self):
274        shell = MockShell()
275        f = run.StdOutputFile(shell, 'stdout')
276        self.assertFalse(f.closed)
277        f.write('test')
278        f.close()
279        self.assertTrue(f.closed)
280        self.assertRaises(ValueError, f.write, 'x')
281        self.assertEqual(shell.written, [('test', 'stdout')])
282        f.close()
283        self.assertRaises(TypeError, f.close, 1)
284
285
286class RecursionLimitTest(unittest.TestCase):
287    # Test (un)install_recursionlimit_wrappers and fixdoc.
288
289    def test_bad_setrecursionlimit_calls(self):
290        run.install_recursionlimit_wrappers()
291        self.addCleanup(run.uninstall_recursionlimit_wrappers)
292        f = sys.setrecursionlimit
293        self.assertRaises(TypeError, f, limit=100)
294        self.assertRaises(TypeError, f, 100, 1000)
295        self.assertRaises(ValueError, f, 0)
296
297    def test_roundtrip(self):
298        run.install_recursionlimit_wrappers()
299        self.addCleanup(run.uninstall_recursionlimit_wrappers)
300
301        # Check that setting the recursion limit works.
302        orig_reclimit = sys.getrecursionlimit()
303        self.addCleanup(sys.setrecursionlimit, orig_reclimit)
304        sys.setrecursionlimit(orig_reclimit + 3)
305
306        # Check that the new limit is returned by sys.getrecursionlimit().
307        new_reclimit = sys.getrecursionlimit()
308        self.assertEqual(new_reclimit, orig_reclimit + 3)
309
310    def test_default_recursion_limit_preserved(self):
311        orig_reclimit = sys.getrecursionlimit()
312        run.install_recursionlimit_wrappers()
313        self.addCleanup(run.uninstall_recursionlimit_wrappers)
314        new_reclimit = sys.getrecursionlimit()
315        self.assertEqual(new_reclimit, orig_reclimit)
316
317    def test_fixdoc(self):
318        # Put here until better place for miscellaneous test.
319        def func(): "docstring"
320        run.fixdoc(func, "more")
321        self.assertEqual(func.__doc__, "docstring\n\nmore")
322        func.__doc__ = None
323        run.fixdoc(func, "more")
324        self.assertEqual(func.__doc__, "more")
325
326
327class HandleErrorTest(unittest.TestCase):
328    # Method of MyRPCServer
329    def test_fatal_error(self):
330        eq = self.assertEqual
331        with captured_output('__stderr__') as err,\
332             mock.patch('idlelib.run.thread.interrupt_main',
333                        new_callable=Func) as func:
334            try:
335                raise EOFError
336            except EOFError:
337                run.MyRPCServer.handle_error(None, 'abc', '123')
338            eq(run.exit_now, True)
339            run.exit_now = False
340            eq(err.getvalue(), '')
341
342            try:
343                raise IndexError
344            except IndexError:
345                run.MyRPCServer.handle_error(None, 'abc', '123')
346            eq(run.quitting, True)
347            run.quitting = False
348            msg = err.getvalue()
349            self.assertIn('abc', msg)
350            self.assertIn('123', msg)
351            self.assertIn('IndexError', msg)
352            eq(func.called, 2)
353
354if __name__ == '__main__':
355    unittest.main(verbosity=2)
356