File: test_exc.py

package info (click to toggle)
pypy3 7.3.19%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 212,236 kB
  • sloc: python: 2,098,316; ansic: 540,565; sh: 21,462; asm: 14,419; cpp: 4,451; makefile: 4,209; objc: 761; xml: 530; exp: 499; javascript: 314; pascal: 244; lisp: 45; csh: 12; awk: 4
file content (591 lines) | stat: -rw-r--r-- 21,832 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
# -*- coding: utf-8 -*-

from pypy.interpreter.gateway import interp2app_temp
from pypy.interpreter.error import OperationError


class AppTestExc(object):
    def setup_class(cls):
        cls.w_file = cls.space.wrap(__file__)

    def test_baseexc(self):
        assert str(BaseException()) == ''
        assert repr(BaseException()) == 'BaseException()'
        raises(AttributeError, getattr, BaseException(), 'message')
        raises(AttributeError, getattr, BaseException(3), 'message')
        assert repr(BaseException(3)) == 'BaseException(3)'
        assert str(BaseException(3)) == '3'
        assert BaseException().args == ()
        assert BaseException(3).args == (3,)
        assert BaseException(3, "x").args == (3, "x")
        assert repr(BaseException(3, "x")) == "BaseException(3, 'x')"
        assert str(BaseException(3, "x")) == "(3, 'x')"
        raises(AttributeError, getattr, BaseException(3, "x"), 'message')
        x = BaseException()
        x.xyz = 3
        assert x.xyz == 3
        x.args = [42]
        assert x.args == (42,)
        assert str(x) == '42'
        raises(TypeError, 'x[0] == 42')
        x.message = "xyz"
        assert x.message == "xyz"
        del x.message
        assert not hasattr(x, "message")

    def test_kwargs(self):
        class X(Exception):
            def __init__(self, x=3):
                self.x = x

        x = X(x=8)
        assert x.x == 8

    def test_args(self):
        class X(Exception):
            def __init__(self, x=3):
                self.x = x

        assert X(8).args == (8,)
        assert X(x=8).args == ()

    def test_exc(self):
        assert issubclass(Exception, BaseException)
        assert isinstance(Exception(), Exception)
        assert isinstance(Exception(), BaseException)
        assert repr(Exception(3, "x")) == "Exception(3, 'x')"
        assert str(IOError("foo", "bar")) == "[Errno foo] bar"
        assert isinstance(IOError("foo", "bar"), IOError)
        assert str(IOError(1, 2)) == "[Errno 1] 2"

    def test_custom_class(self):
        class MyException(Exception):
            def __init__(self, x):
                self.x = x

            def __str__(self):
                return self.x

        assert issubclass(MyException, Exception)
        assert issubclass(MyException, BaseException)
        assert not issubclass(MyException, LookupError)
        assert str(MyException("x")) == "x"

    def test_unicode_translate_error(self):
        ut = UnicodeTranslateError("x", 1, 5, "bah")
        assert ut.object == 'x'
        assert ut.start == 1
        assert ut.end == 5
        assert ut.reason == 'bah'
        assert ut.args == ('x', 1, 5, 'bah')
        ut.object = 'y'
        assert ut.object == 'y'
        assert str(ut) == "can't translate characters in position 1-4: bah"
        ut.start = 4
        ut.object = '012345'
        assert str(ut) == "can't translate character '\\x34' in position 4: bah"
        ut.object = []
        assert ut.object == []

    def test_key_error(self):
        assert str(KeyError('s')) == "'s'"

    def test_environment_error(self):
        ee = EnvironmentError(3, "x", "y")
        assert str(ee) == "[Errno 3] x: 'y'"
        assert str(EnvironmentError(3, "x")) == "[Errno 3] x"
        assert ee.errno == 3
        assert ee.strerror == "x"
        assert ee.filename == "y"
        assert EnvironmentError(3, "x").filename is None
        e = EnvironmentError(1, "hello", "world")
        assert str(e) == "[Errno 1] hello: 'world'"

    def test_windows_error(self):
        try:
            WindowsError
        except NameError:
            skip('WindowsError not present')
        ee = WindowsError(None, "x", "y", 3)
        assert type(ee) is FileNotFoundError
        assert str(ee) == "[WinError 3] x: 'y'"
        # winerror=3 (ERROR_PATH_NOT_FOUND) maps to errno=2 (ENOENT)
        assert ee.winerror == 3
        assert ee.errno == 2
        assert str(WindowsError(3, "x")) == "[Errno 3] x"

    def test_syntax_error(self):
        s = SyntaxError()
        assert s.msg is None
        s = SyntaxError(3)
        assert str(s) == '3'
        assert str(SyntaxError("a", "b", 123)) == "a"
        assert str(SyntaxError("a", (1, 2, 3, 4))) == "a (line 2)"
        s = SyntaxError("a", (1, 2, 3, 4))
        assert s.msg == "a"
        assert s.filename == 1
        assert s.offset == 3
        assert s.text == 4
        assert str(SyntaxError("msg", ("file.py", 2, 3, 4))) == "msg (file.py, line 2)"

        s = SyntaxError("a", (1, 2, 3, 4, 5, 6))
        assert s.msg == "a"
        assert s.filename == 1
        assert s.lineno == 2
        assert s.offset == 3
        assert s.text == 4
        assert s.end_lineno == 5
        assert s.end_offset == 6

    def test_system_exit(self):
        assert issubclass(SystemExit, BaseException)
        assert SystemExit().code is None
        assert SystemExit("x").code == "x"
        assert SystemExit(1, 2).code == (1, 2)

    def test_str_unicode(self):
        e = ValueError('àèì')
        assert str(e) == 'àèì'

    def test_unicode_decode_error(self):
        for mybytes in (b'y', bytearray(b'y')):
            ud = UnicodeDecodeError("x", mybytes, 1, 5, "bah")
            assert ud.encoding == 'x'
            assert ud.object == b'y'
            assert type(ud.object) is bytes
            assert ud.start == 1
            assert ud.end == 5
            assert ud.reason == 'bah'
            assert ud.args == ('x', b'y', 1, 5, 'bah')
            assert type(ud.args[1]) is type(mybytes)
            ud.object = b'z9'
            assert ud.object == b'z9'
            assert str(ud) == "'x' codec can't decode bytes in position 1-4: bah"
            ud.end = 2
            assert str(ud) == "'x' codec can't decode byte 0x39 in position 1: bah"

    def test_unicode_encode_error(self):
        ue = UnicodeEncodeError("x", "y", 1, 5, "bah")
        assert ue.encoding == 'x'
        assert ue.object == 'y'
        assert ue.start == 1
        assert ue.end == 5
        assert ue.reason == 'bah'
        assert ue.args == ('x', 'y', 1, 5, 'bah')
        ue.object = 'z9'
        assert ue.object == 'z9'
        assert str(ue) == "'x' codec can't encode characters in position 1-4: bah"
        ue.end = 2
        assert str(ue) == "'x' codec can't encode character '\\x39' in position 1: bah"
        ue.object = []
        assert ue.object == []
        raises(TypeError, UnicodeEncodeError, "x", b"y", 1, 5, "bah")

    def test_multiple_inheritance(self):
        class A(LookupError, ValueError):
            pass
        assert issubclass(A, A)
        assert issubclass(A, Exception)
        assert issubclass(A, LookupError)
        assert issubclass(A, ValueError)
        assert not issubclass(A, KeyError)
        a = A()
        assert isinstance(a, A)
        assert isinstance(a, Exception)
        assert isinstance(a, LookupError)
        assert isinstance(a, ValueError)
        assert not isinstance(a, KeyError)

        try:
            class B(UnicodeTranslateError, UnicodeEncodeError):
                pass
        except TypeError:
            pass
        else:
            fail("bah")

        class C(ValueError, IOError):
            pass
        c = C()
        assert isinstance(ValueError(), ValueError)
        assert isinstance(c, C)
        assert isinstance(c, Exception)
        assert isinstance(c, ValueError)
        assert isinstance(c, IOError)
        assert isinstance(c, EnvironmentError)
        assert not isinstance(c, KeyError)

    def test_doc_and_module(self):
        import builtins
        for name, e in builtins.__dict__.items():
            if isinstance(e, type) and issubclass(e, BaseException):
                if e not in (ExceptionGroup,):
                    assert e.__doc__, e
                assert e.__module__ == 'builtins', e
        assert 'run-time' in RuntimeError.__doc__

    def test_reduce(self):
        le = LookupError(1, 2, "a")
        assert le.__reduce__() == (LookupError, (1, 2, "a"))
        le.xyz = (1, 2)
        assert le.__reduce__() == (LookupError, (1, 2, "a"), {"xyz": (1, 2)})
        ee = EnvironmentError(1, 2, "a")
        assert ee.__reduce__() == (PermissionError, (1, 2, "a"))
        ee = ImportError("a", "b", "c", name="x", path="y")
        assert ee.__reduce__() == (ImportError, ("a", "b", "c"), {"name": "x", "path": "y"})

    def test_setstate(self):
        fw = FutureWarning()
        fw.__setstate__({"xyz": (1, 2)})
        assert fw.xyz == (1, 2)
        fw.__setstate__({'z': 1})
        assert fw.z == 1
        assert fw.xyz == (1, 2)

        i = ImportError()
        i.foo = "x"
        i.__setstate__({"name": "x", "path": "y", "bar": 1})
        assert i.foo == "x"
        assert i.name == "x"
        assert i.path == "y"
        assert i.bar == 1

    def test_unicode_error_uninitialized_str(self):
        assert str(UnicodeEncodeError.__new__(UnicodeEncodeError)) == ""
        assert str(UnicodeDecodeError.__new__(UnicodeDecodeError)) == ""
        assert str(UnicodeTranslateError.__new__(UnicodeTranslateError)) == ""

    def test_cause(self):
        e1 = TypeError()
        e2 = ValueError()
        assert e1.__cause__ is None
        e1.__cause__ = e2
        assert e1.__cause__ is e2
        e1.__cause__ = None
        raises(TypeError, setattr, e1, '__cause__', 1)
        raises((AttributeError, TypeError), delattr, e1, '__cause__')

    def test_context(self):
        e1 = TypeError()
        e2 = ValueError()
        assert e1.__context__ is None
        e1.__context__ = e2
        assert e1.__context__ is e2
        e1.__context__ = None
        raises(TypeError, setattr, e1, '__context__', 1)
        raises((AttributeError, TypeError), delattr, e1, '__context__')

    def test_traceback(self):
        assert ValueError().with_traceback(None).__traceback__ is None
        raises(TypeError, ValueError().with_traceback, 3)
        try:
            XXX
        except NameError as e:
            import sys
            tb = sys.exc_info()[2]
            assert e.with_traceback(tb) is e
            assert e.__traceback__ is tb

    def test_set_traceback(self):
        e = Exception()
        raises(TypeError, "e.__traceback__ = 42")

    def test_errno_ENOTDIR(self):
        # CPython issue #12802: "not a directory" errors are ENOTDIR
        # even on Windows
        import os
        import errno
        try:
            os.listdir(self.file)
        except OSError as e:
            assert e.errno == errno.ENOTDIR
        else:
            assert False, "Expected OSError"

    def test_nonascii_name(self):
        """
        class 日本(Exception):
            pass
        assert '日本' in repr(日本)
        class 日本2(SyntaxError):
            pass
        assert '日本2' in repr(日本2)
        """

    def test_stopiteration(self):
        assert StopIteration().value is None
        assert StopIteration(42).value == 42
        assert StopIteration(42, 5).value == 42

    def test_importerror(self):
        assert ImportError("message").name is None
        assert ImportError("message").path is None
        assert ImportError("message", name="x").name == "x"
        assert ImportError("message", path="y").path == "y"
        with raises(TypeError) as e:
            ImportError(invalid="z")
        assert "__init__() got an unexpected keyword argument 'invalid'" in str(e.value)
        assert ImportError("message").msg == "message"
        assert ImportError("message").args == ("message", )
        assert ImportError("message", "foo").msg is None
        assert ImportError("message", "foo").args == ("message", "foo")

    def test_importerror_reduce(self):
        d = {'name': 'a',
             'path': 'b',
            } 
        s = ImportError('c', **d).__reduce__()
        e = s[0](*s[1], **s[2])
        for k, v in d.items():
            assert getattr(e, k) == v

    def test_modulenotfounderror(self):
        assert ModuleNotFoundError("message").name is None
        assert ModuleNotFoundError("message").path is None
        assert ModuleNotFoundError("message", name="x").name == "x"
        assert ModuleNotFoundError("message", path="y").path == "y"
        raises(TypeError, ModuleNotFoundError, invalid="z")
        assert repr(ModuleNotFoundError('test')) == "ModuleNotFoundError('test')"

    def test_blockingioerror(self):
        args = ("a", "b", "c", "d", "e")
        for n in range(6):
            e = BlockingIOError(*args[:n])
            raises(AttributeError, getattr, e, 'characters_written')
        e = BlockingIOError("a", "b", 3)
        assert e.characters_written == 3
        e.characters_written = 5
        assert e.characters_written == 5
        del e.characters_written
        with raises(AttributeError):
            e.characters_written

    def test_errno_mapping(self):
        # The OSError constructor maps errnos to subclasses
        map_lines = """
        +-- BlockingIOError        EAGAIN, EALREADY, EWOULDBLOCK, EINPROGRESS
        +-- ChildProcessError                                          ECHILD
        +-- ConnectionError
            +-- BrokenPipeError                              EPIPE, ESHUTDOWN
            +-- ConnectionAbortedError                           ECONNABORTED
            +-- ConnectionRefusedError                           ECONNREFUSED
            +-- ConnectionResetError                               ECONNRESET
        +-- FileExistsError                                            EEXIST
        +-- FileNotFoundError                                          ENOENT
        +-- InterruptedError                                            EINTR
        +-- IsADirectoryError                                          EISDIR
        +-- NotADirectoryError                                        ENOTDIR
        +-- PermissionError                                     EACCES, EPERM
        +-- ProcessLookupError                                          ESRCH
        +-- TimeoutError                                            ETIMEDOUT
        """
        import errno, builtins
        map = {}
        for line in map_lines.splitlines():
            line = line.strip('+- ')
            if not line:
                continue
            excname, _, errnames = line.partition(' ')
            for errname in filter(None, errnames.strip().split(', ')):
                map[getattr(errno, errname)] = getattr(builtins, excname)
        e = OSError(errno.EEXIST, "Bad file descriptor")
        assert type(e) is FileExistsError
        # Exhaustive testing
        for errcode, exc in map.items():
            e = OSError(errcode, "Some message")
            assert type(e) is exc
        othercodes = set(errno.errorcode) - set(map)
        for errcode in othercodes:
            e = OSError(errcode, "Some message")
            assert type(e) is OSError

    def test_oserror_init_overriden(self):
        class SubOSErrorWithInit(OSError):
            def __init__(self, message, bar):
                self.bar = bar
                super().__init__(message)

        e = SubOSErrorWithInit("some message", "baz")
        assert e.bar == "baz"
        assert e.args == ("some message",)

        e = SubOSErrorWithInit("some message", bar="baz")
        assert e.bar == "baz"
        assert e.args == ("some message",)

    def test_oserror_new_overriden(self):
        class SubOSErrorWithNew(OSError):
            def __new__(cls, message, baz):
                self = super().__new__(cls, message)
                self.baz = baz
                return self

        e = SubOSErrorWithNew("some message", "baz")
        assert e.baz == "baz"
        assert e.args == ("some message",)

        e = SubOSErrorWithNew("some message", baz="baz")
        assert e.baz == "baz"
        assert e.args == ("some message",)
        assert e.filename is None
        assert e.filename2 is None

    def test_oserror_3_args(self):
        e = OSError(42, "bar", "baz")
        assert e.args == (42, "bar")
        assert e.filename == "baz"
        assert e.filename2 is None
        assert str(e) == "[Errno 42] bar: 'baz'"

    def test_oserror_5_args(self):
        # NB. argument 4 is only parsed on Windows
        e = OSError(42, "bar", "baz", None, "bok")
        assert e.args == (42, "bar")
        assert e.filename == "baz"
        assert e.filename2 == "bok"
        assert str(e) == "[Errno 42] bar: 'baz' -> 'bok'"

    def test_oserror_None(self):
        assert str(OSError()) == ""
        assert str(OSError(None)) == "None"
        assert str(OSError(None, None)) == "[Errno None] None"
        assert str(OSError(None, None, None, None)) == "[Errno None] None"

    # Check the heuristic for print & exec covers significant cases
    # As well as placing some limits on false positives
    def test_former_statements_refer_to_builtins(self):
        keywords = "print", "exec"
        def exec_(s): exec(s)
        # Cases where we want the custom error
        cases = [
            "{} foo",
            "{} {{1:foo}}",
            "if 1: {} foo",
            "if 1: {} {{1:foo}}",
            "if 1:\n    {} foo",
            "if 1:\n    {} {{1:foo}}",
        ]
        for keyword in keywords:
            custom_msg = "call to '{}'".format(keyword)
            for case in cases:
                source = case.format(keyword)
                exc = raises(SyntaxError, exec_, source)
                assert custom_msg in exc.value.msg
                # XXX the following line passes on CPython but not on
                # PyPy, but do we really care about this single special
                # case?
                #assert exc.value.args[0] == 'invalid syntax'

                source = source.replace("foo", "(foo.)")
                exc = raises(SyntaxError, exec_, source)
                print('source "%s"' % source)
                print('custom_msg "%s"' % custom_msg)
                print('exc.value.msg "%s"' % exc.value.msg)
                assert (custom_msg not in exc.value.msg) == (
                    ('print ' in source or 'exec ' in source))

    def test_bug_print_heuristic_shadows_better_message(self):
        def exec_(s): exec(s)
        exc = raises(SyntaxError, exec_, "print [)")
        assert "closing parenthesis ')' does not match opening parenthesis '['" in exc.value.msg

    def test_print_suggestions(self):
        def exec_(s): exec(s)
        def check(s, error):
            exc = raises(SyntaxError, exec_, s)
            print(exc.value.msg)
            assert exc.value.msg == error

        check(
            "print 1",
            "Missing parentheses in call to 'print'. Did you mean print(1)?")
        check(
            "print 1, \t",
            "Missing parentheses in call to 'print'. Did you mean print(1, end=\" \")?")
        check(
            "print 'a'\n;\t ",
            "Missing parentheses in call to 'print'. Did you mean print('a')?")
        check(
            "print p;",
            "Missing parentheses in call to 'print'. Did you mean print(p)?")
        check("print %", "invalid syntax")
        check("print 1 1",
            "Missing parentheses in call to 'print'. Did you mean print(...)?")

    def test_print_and_operators(self):
        with raises(TypeError) as excinfo:
            print >> 1, 5
        assert 'Did you mean "print(<message>, file=<output_stream>)"?' in str(excinfo.value)
        with raises(TypeError) as excinfo:
            print -1
        assert 'Did you mean "print(<-number>)"?' in str(excinfo.value)


    def test_attribute_error_name_obj_attributes(self):
        exc = AttributeError("'a' not found", name="a", obj=7)
        assert exc.name == "a"
        assert exc.obj == 7

    def test_attribute_errorr_name_obj_attributes_are_filled(self):
        class A:
            pass
        a = A()
        with raises(AttributeError) as info:
            a.blub
        exc = info.value
        assert exc.name == "blub"
        assert exc.obj is a

    def test_name_error_name_attribute(self):
        exc = NameError("'a' not found", name="a")
        assert exc.name == "a"

    def test_name_error_name_attributes_are_filled(self):
        class A:
            pass
        a = A()
        with raises(NameError) as info:
            blub
        exc = info.value
        assert exc.name == "blub"

    def test_multiple_inheritance_bug(self):
        class OptionError(AttributeError, KeyError):
            pass # does not crash
        assert issubclass(OptionError, Exception)
        assert issubclass(OptionError, AttributeError)
        assert issubclass(OptionError, KeyError)
        assert issubclass(OptionError, LookupError)
        OptionError() # check that instantiation works

    def test_multiple_inheritance_bug2(self):
        class E(EnvironmentError, KeyError): pass
        assert KeyError.__str__(E(6)) == '6'
        # harder
        class E2(KeyError, EnvironmentError): pass
        assert str(E2(6)) == '6'

    def test_keyerror_subclass(self):
        class E(KeyError):
            pass
        assert str(E(1)) == '1'

    def test_encodingwarning(self):
        assert isinstance(EncodingWarning('abc'), Warning)

class AppTestExcBugAttributeError(object):
    def setup_class(cls):
        def f(space):
            raise OperationError(space.w_AttributeError, space.newtext("buggy"))
        cls.w_f = cls.space.wrap(interp2app_temp(f))

    def test_enrich_attribute_error_bug(self):
        raiseopperr = self.f
        class A:
            def __getattr__(self, name):
                raiseopperr()
        # this used to crash
        a = A()
        with raises(AttributeError) as info:
            a.abc
        assert info.value.name is None # enrich_attribute_error couldn't do anything