source: python/trunk/Lib/test/test_exceptions.py

Last change on this file was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

  • Property svn:eol-style set to native
File size: 25.4 KB
Line 
1# Python test set -- part 5, built-in exceptions
2
3import os
4import sys
5import unittest
6import pickle, cPickle
7
8from test.test_support import (TESTFN, unlink, run_unittest, captured_output,
9 check_warnings, cpython_only)
10from test.test_pep352 import ignore_deprecation_warnings
11
12# XXX This is not really enough, each *operation* should be tested!
13
14class ExceptionTests(unittest.TestCase):
15
16 def testReload(self):
17 # Reloading the built-in exceptions module failed prior to Py2.2, while it
18 # should act the same as reloading built-in sys.
19 try:
20 from imp import reload
21 import exceptions
22 reload(exceptions)
23 except ImportError, e:
24 self.fail("reloading exceptions: %s" % e)
25
26 def raise_catch(self, exc, excname):
27 try:
28 raise exc, "spam"
29 except exc, err:
30 buf1 = str(err)
31 try:
32 raise exc("spam")
33 except exc, err:
34 buf2 = str(err)
35 self.assertEqual(buf1, buf2)
36 self.assertEqual(exc.__name__, excname)
37
38 def testRaising(self):
39 self.raise_catch(AttributeError, "AttributeError")
40 self.assertRaises(AttributeError, getattr, sys, "undefined_attribute")
41
42 self.raise_catch(EOFError, "EOFError")
43 fp = open(TESTFN, 'w')
44 fp.close()
45 fp = open(TESTFN, 'r')
46 savestdin = sys.stdin
47 try:
48 try:
49 sys.stdin = fp
50 x = raw_input()
51 except EOFError:
52 pass
53 finally:
54 sys.stdin = savestdin
55 fp.close()
56 unlink(TESTFN)
57
58 self.raise_catch(IOError, "IOError")
59 self.assertRaises(IOError, open, 'this file does not exist', 'r')
60
61 self.raise_catch(ImportError, "ImportError")
62 self.assertRaises(ImportError, __import__, "undefined_module")
63
64 self.raise_catch(IndexError, "IndexError")
65 x = []
66 self.assertRaises(IndexError, x.__getitem__, 10)
67
68 self.raise_catch(KeyError, "KeyError")
69 x = {}
70 self.assertRaises(KeyError, x.__getitem__, 'key')
71
72 self.raise_catch(KeyboardInterrupt, "KeyboardInterrupt")
73
74 self.raise_catch(MemoryError, "MemoryError")
75
76 self.raise_catch(NameError, "NameError")
77 try: x = undefined_variable
78 except NameError: pass
79
80 self.raise_catch(OverflowError, "OverflowError")
81 x = 1
82 for dummy in range(128):
83 x += x # this simply shouldn't blow up
84
85 self.raise_catch(RuntimeError, "RuntimeError")
86
87 self.raise_catch(SyntaxError, "SyntaxError")
88 try: exec '/\n'
89 except SyntaxError: pass
90
91 self.raise_catch(IndentationError, "IndentationError")
92
93 self.raise_catch(TabError, "TabError")
94 # can only be tested under -tt, and is the only test for -tt
95 #try: compile("try:\n\t1/0\n \t1/0\nfinally:\n pass\n", '<string>', 'exec')
96 #except TabError: pass
97 #else: self.fail("TabError not raised")
98
99 self.raise_catch(SystemError, "SystemError")
100
101 self.raise_catch(SystemExit, "SystemExit")
102 self.assertRaises(SystemExit, sys.exit, 0)
103
104 self.raise_catch(TypeError, "TypeError")
105 try: [] + ()
106 except TypeError: pass
107
108 self.raise_catch(ValueError, "ValueError")
109 self.assertRaises(ValueError, chr, 10000)
110
111 self.raise_catch(ZeroDivisionError, "ZeroDivisionError")
112 try: x = 1 // 0
113 except ZeroDivisionError: pass
114
115 self.raise_catch(Exception, "Exception")
116 try: x = 1 // 0
117 except Exception, e: pass
118
119 def testSyntaxErrorMessage(self):
120 # make sure the right exception message is raised for each of
121 # these code fragments
122
123 def ckmsg(src, msg):
124 try:
125 compile(src, '<fragment>', 'exec')
126 except SyntaxError, e:
127 if e.msg != msg:
128 self.fail("expected %s, got %s" % (msg, e.msg))
129 else:
130 self.fail("failed to get expected SyntaxError")
131
132 s = '''while 1:
133 try:
134 pass
135 finally:
136 continue'''
137
138 if not sys.platform.startswith('java'):
139 ckmsg(s, "'continue' not supported inside 'finally' clause")
140
141 s = '''if 1:
142 try:
143 continue
144 except:
145 pass'''
146
147 ckmsg(s, "'continue' not properly in loop")
148 ckmsg("continue\n", "'continue' not properly in loop")
149
150 @cpython_only
151 def testSettingException(self):
152 # test that setting an exception at the C level works even if the
153 # exception object can't be constructed.
154
155 class BadException:
156 def __init__(self_):
157 raise RuntimeError, "can't instantiate BadException"
158
159 def test_capi1():
160 import _testcapi
161 try:
162 _testcapi.raise_exception(BadException, 1)
163 except TypeError, err:
164 exc, err, tb = sys.exc_info()
165 co = tb.tb_frame.f_code
166 self.assertEqual(co.co_name, "test_capi1")
167 self.assertTrue(co.co_filename.endswith('test_exceptions'+os.extsep+'py'))
168 else:
169 self.fail("Expected exception")
170
171 def test_capi2():
172 import _testcapi
173 try:
174 _testcapi.raise_exception(BadException, 0)
175 except RuntimeError, err:
176 exc, err, tb = sys.exc_info()
177 co = tb.tb_frame.f_code
178 self.assertEqual(co.co_name, "__init__")
179 self.assertTrue(co.co_filename.endswith('test_exceptions'+os.extsep+'py'))
180 co2 = tb.tb_frame.f_back.f_code
181 self.assertEqual(co2.co_name, "test_capi2")
182 else:
183 self.fail("Expected exception")
184
185 if not sys.platform.startswith('java'):
186 test_capi1()
187 test_capi2()
188
189 def test_WindowsError(self):
190 try:
191 WindowsError
192 except NameError:
193 pass
194 else:
195 self.assertEqual(str(WindowsError(1001)),
196 "1001")
197 self.assertEqual(str(WindowsError(1001, "message")),
198 "[Error 1001] message")
199 self.assertEqual(WindowsError(1001, "message").errno, 22)
200 self.assertEqual(WindowsError(1001, "message").winerror, 1001)
201
202 @ignore_deprecation_warnings
203 def testAttributes(self):
204 # test that exception attributes are happy
205
206 exceptionList = [
207 (BaseException, (), {'message' : '', 'args' : ()}),
208 (BaseException, (1, ), {'message' : 1, 'args' : (1,)}),
209 (BaseException, ('foo',),
210 {'message' : 'foo', 'args' : ('foo',)}),
211 (BaseException, ('foo', 1),
212 {'message' : '', 'args' : ('foo', 1)}),
213 (SystemExit, ('foo',),
214 {'message' : 'foo', 'args' : ('foo',), 'code' : 'foo'}),
215 (IOError, ('foo',),
216 {'message' : 'foo', 'args' : ('foo',), 'filename' : None,
217 'errno' : None, 'strerror' : None}),
218 (IOError, ('foo', 'bar'),
219 {'message' : '', 'args' : ('foo', 'bar'), 'filename' : None,
220 'errno' : 'foo', 'strerror' : 'bar'}),
221 (IOError, ('foo', 'bar', 'baz'),
222 {'message' : '', 'args' : ('foo', 'bar'), 'filename' : 'baz',
223 'errno' : 'foo', 'strerror' : 'bar'}),
224 (IOError, ('foo', 'bar', 'baz', 'quux'),
225 {'message' : '', 'args' : ('foo', 'bar', 'baz', 'quux')}),
226 (EnvironmentError, ('errnoStr', 'strErrorStr', 'filenameStr'),
227 {'message' : '', 'args' : ('errnoStr', 'strErrorStr'),
228 'strerror' : 'strErrorStr', 'errno' : 'errnoStr',
229 'filename' : 'filenameStr'}),
230 (EnvironmentError, (1, 'strErrorStr', 'filenameStr'),
231 {'message' : '', 'args' : (1, 'strErrorStr'), 'errno' : 1,
232 'strerror' : 'strErrorStr', 'filename' : 'filenameStr'}),
233 (SyntaxError, (), {'message' : '', 'msg' : None, 'text' : None,
234 'filename' : None, 'lineno' : None, 'offset' : None,
235 'print_file_and_line' : None}),
236 (SyntaxError, ('msgStr',),
237 {'message' : 'msgStr', 'args' : ('msgStr',), 'text' : None,
238 'print_file_and_line' : None, 'msg' : 'msgStr',
239 'filename' : None, 'lineno' : None, 'offset' : None}),
240 (SyntaxError, ('msgStr', ('filenameStr', 'linenoStr', 'offsetStr',
241 'textStr')),
242 {'message' : '', 'offset' : 'offsetStr', 'text' : 'textStr',
243 'args' : ('msgStr', ('filenameStr', 'linenoStr',
244 'offsetStr', 'textStr')),
245 'print_file_and_line' : None, 'msg' : 'msgStr',
246 'filename' : 'filenameStr', 'lineno' : 'linenoStr'}),
247 (SyntaxError, ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
248 'textStr', 'print_file_and_lineStr'),
249 {'message' : '', 'text' : None,
250 'args' : ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
251 'textStr', 'print_file_and_lineStr'),
252 'print_file_and_line' : None, 'msg' : 'msgStr',
253 'filename' : None, 'lineno' : None, 'offset' : None}),
254 (UnicodeError, (), {'message' : '', 'args' : (),}),
255 (UnicodeEncodeError, ('ascii', u'a', 0, 1, 'ordinal not in range'),
256 {'message' : '', 'args' : ('ascii', u'a', 0, 1,
257 'ordinal not in range'),
258 'encoding' : 'ascii', 'object' : u'a',
259 'start' : 0, 'reason' : 'ordinal not in range'}),
260 (UnicodeDecodeError, ('ascii', '\xff', 0, 1, 'ordinal not in range'),
261 {'message' : '', 'args' : ('ascii', '\xff', 0, 1,
262 'ordinal not in range'),
263 'encoding' : 'ascii', 'object' : '\xff',
264 'start' : 0, 'reason' : 'ordinal not in range'}),
265 (UnicodeTranslateError, (u"\u3042", 0, 1, "ouch"),
266 {'message' : '', 'args' : (u'\u3042', 0, 1, 'ouch'),
267 'object' : u'\u3042', 'reason' : 'ouch',
268 'start' : 0, 'end' : 1}),
269 ]
270 try:
271 exceptionList.append(
272 (WindowsError, (1, 'strErrorStr', 'filenameStr'),
273 {'message' : '', 'args' : (1, 'strErrorStr'),
274 'strerror' : 'strErrorStr', 'winerror' : 1,
275 'errno' : 22, 'filename' : 'filenameStr'})
276 )
277 except NameError:
278 pass
279
280 for exc, args, expected in exceptionList:
281 try:
282 raise exc(*args)
283 except BaseException, e:
284 if type(e) is not exc:
285 raise
286 # Verify module name
287 self.assertEqual(type(e).__module__, 'exceptions')
288 # Verify no ref leaks in Exc_str()
289 s = str(e)
290 for checkArgName in expected:
291 self.assertEqual(repr(getattr(e, checkArgName)),
292 repr(expected[checkArgName]),
293 'exception "%s", attribute "%s"' %
294 (repr(e), checkArgName))
295
296 # test for pickling support
297 for p in pickle, cPickle:
298 for protocol in range(p.HIGHEST_PROTOCOL + 1):
299 new = p.loads(p.dumps(e, protocol))
300 for checkArgName in expected:
301 got = repr(getattr(new, checkArgName))
302 want = repr(expected[checkArgName])
303 self.assertEqual(got, want,
304 'pickled "%r", attribute "%s"' %
305 (e, checkArgName))
306
307
308 def testDeprecatedMessageAttribute(self):
309 # Accessing BaseException.message and relying on its value set by
310 # BaseException.__init__ triggers a deprecation warning.
311 exc = BaseException("foo")
312 with check_warnings(("BaseException.message has been deprecated "
313 "as of Python 2.6", DeprecationWarning)) as w:
314 self.assertEqual(exc.message, "foo")
315 self.assertEqual(len(w.warnings), 1)
316
317 def testRegularMessageAttribute(self):
318 # Accessing BaseException.message after explicitly setting a value
319 # for it does not trigger a deprecation warning.
320 exc = BaseException("foo")
321 exc.message = "bar"
322 with check_warnings(quiet=True) as w:
323 self.assertEqual(exc.message, "bar")
324 self.assertEqual(len(w.warnings), 0)
325 # Deleting the message is supported, too.
326 del exc.message
327 with self.assertRaises(AttributeError):
328 exc.message
329
330 @ignore_deprecation_warnings
331 def testPickleMessageAttribute(self):
332 # Pickling with message attribute must work, as well.
333 e = Exception("foo")
334 f = Exception("foo")
335 f.message = "bar"
336 for p in pickle, cPickle:
337 ep = p.loads(p.dumps(e))
338 self.assertEqual(ep.message, "foo")
339 fp = p.loads(p.dumps(f))
340 self.assertEqual(fp.message, "bar")
341
342 @ignore_deprecation_warnings
343 def testSlicing(self):
344 # Test that you can slice an exception directly instead of requiring
345 # going through the 'args' attribute.
346 args = (1, 2, 3)
347 exc = BaseException(*args)
348 self.assertEqual(exc[:], args)
349 self.assertEqual(exc.args[:], args)
350
351 def testKeywordArgs(self):
352 # test that builtin exception don't take keyword args,
353 # but user-defined subclasses can if they want
354 self.assertRaises(TypeError, BaseException, a=1)
355
356 class DerivedException(BaseException):
357 def __init__(self, fancy_arg):
358 BaseException.__init__(self)
359 self.fancy_arg = fancy_arg
360
361 x = DerivedException(fancy_arg=42)
362 self.assertEqual(x.fancy_arg, 42)
363
364 def testInfiniteRecursion(self):
365 def f():
366 return f()
367 self.assertRaises(RuntimeError, f)
368
369 def g():
370 try:
371 return g()
372 except ValueError:
373 return -1
374
375 # The test prints an unraisable recursion error when
376 # doing "except ValueError", this is because subclass
377 # checking has recursion checking too.
378 with captured_output("stderr"):
379 try:
380 g()
381 except RuntimeError:
382 pass
383 except:
384 self.fail("Should have raised KeyError")
385 else:
386 self.fail("Should have raised KeyError")
387
388 def testUnicodeStrUsage(self):
389 # Make sure both instances and classes have a str and unicode
390 # representation.
391 self.assertTrue(str(Exception))
392 self.assertTrue(unicode(Exception))
393 self.assertTrue(str(Exception('a')))
394 self.assertTrue(unicode(Exception(u'a')))
395 self.assertTrue(unicode(Exception(u'\xe1')))
396
397 def testUnicodeChangeAttributes(self):
398 # See issue 7309. This was a crasher.
399
400 u = UnicodeEncodeError('baz', u'xxxxx', 1, 5, 'foo')
401 self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: foo")
402 u.end = 2
403 self.assertEqual(str(u), "'baz' codec can't encode character u'\\x78' in position 1: foo")
404 u.end = 5
405 u.reason = 0x345345345345345345
406 self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: 965230951443685724997")
407 u.encoding = 4000
408 self.assertEqual(str(u), "'4000' codec can't encode characters in position 1-4: 965230951443685724997")
409 u.start = 1000
410 self.assertEqual(str(u), "'4000' codec can't encode characters in position 1000-4: 965230951443685724997")
411
412 u = UnicodeDecodeError('baz', 'xxxxx', 1, 5, 'foo')
413 self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: foo")
414 u.end = 2
415 self.assertEqual(str(u), "'baz' codec can't decode byte 0x78 in position 1: foo")
416 u.end = 5
417 u.reason = 0x345345345345345345
418 self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: 965230951443685724997")
419 u.encoding = 4000
420 self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1-4: 965230951443685724997")
421 u.start = 1000
422 self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1000-4: 965230951443685724997")
423
424 u = UnicodeTranslateError(u'xxxx', 1, 5, 'foo')
425 self.assertEqual(str(u), "can't translate characters in position 1-4: foo")
426 u.end = 2
427 self.assertEqual(str(u), "can't translate character u'\\x78' in position 1: foo")
428 u.end = 5
429 u.reason = 0x345345345345345345
430 self.assertEqual(str(u), "can't translate characters in position 1-4: 965230951443685724997")
431 u.start = 1000
432 self.assertEqual(str(u), "can't translate characters in position 1000-4: 965230951443685724997")
433
434 def test_badisinstance(self):
435 # Bug #2542: if issubclass(e, MyException) raises an exception,
436 # it should be ignored
437 class Meta(type):
438 def __subclasscheck__(cls, subclass):
439 raise ValueError()
440
441 class MyException(Exception):
442 __metaclass__ = Meta
443 pass
444
445 with captured_output("stderr") as stderr:
446 try:
447 raise KeyError()
448 except MyException, e:
449 self.fail("exception should not be a MyException")
450 except KeyError:
451 pass
452 except:
453 self.fail("Should have raised KeyError")
454 else:
455 self.fail("Should have raised KeyError")
456
457 with captured_output("stderr") as stderr:
458 def g():
459 try:
460 return g()
461 except RuntimeError:
462 return sys.exc_info()
463 e, v, tb = g()
464 self.assertTrue(e is RuntimeError, e)
465 self.assertIn("maximum recursion depth exceeded", str(v))
466
467 def test_new_returns_invalid_instance(self):
468 # See issue #11627.
469 class MyException(Exception):
470 def __new__(cls, *args):
471 return object()
472
473 with self.assertRaises(TypeError):
474 raise MyException
475
476 def test_assert_with_tuple_arg(self):
477 try:
478 assert False, (3,)
479 except AssertionError as e:
480 self.assertEqual(str(e), "(3,)")
481
482 def test_bad_exception_clearing(self):
483 # See issue 16445: use of Py_XDECREF instead of Py_CLEAR in
484 # BaseException_set_message gave a possible way to segfault the
485 # interpreter.
486 class Nasty(str):
487 def __del__(message):
488 del e.message
489
490 e = ValueError(Nasty("msg"))
491 e.args = ()
492 del e.message
493
494
495# Helper class used by TestSameStrAndUnicodeMsg
496class ExcWithOverriddenStr(Exception):
497 """Subclass of Exception that accepts a keyword 'msg' arg that is
498 returned by __str__. 'msg' won't be included in self.args"""
499 def __init__(self, *args, **kwargs):
500 self.msg = kwargs.pop('msg') # msg should always be present
501 super(ExcWithOverriddenStr, self).__init__(*args, **kwargs)
502 def __str__(self):
503 return self.msg
504
505
506class TestSameStrAndUnicodeMsg(unittest.TestCase):
507 """unicode(err) should return the same message of str(err). See #6108"""
508
509 def check_same_msg(self, exc, msg):
510 """Helper function that checks if str(exc) == unicode(exc) == msg"""
511 self.assertEqual(str(exc), msg)
512 self.assertEqual(str(exc), unicode(exc))
513
514 def test_builtin_exceptions(self):
515 """Check same msg for built-in exceptions"""
516 # These exceptions implement a __str__ method that uses the args
517 # to create a better error message. unicode(e) should return the same
518 # message.
519 exceptions = [
520 SyntaxError('invalid syntax', ('<string>', 1, 3, '2+*3')),
521 IOError(2, 'No such file or directory'),
522 KeyError('both should have the same quotes'),
523 UnicodeDecodeError('ascii', '\xc3\xa0', 0, 1,
524 'ordinal not in range(128)'),
525 UnicodeEncodeError('ascii', u'\u1234', 0, 1,
526 'ordinal not in range(128)')
527 ]
528 for exception in exceptions:
529 self.assertEqual(str(exception), unicode(exception))
530
531 def test_0_args(self):
532 """Check same msg for Exception with 0 args"""
533 # str() and unicode() on an Exception with no args should return an
534 # empty string
535 self.check_same_msg(Exception(), '')
536
537 def test_0_args_with_overridden___str__(self):
538 """Check same msg for exceptions with 0 args and overridden __str__"""
539 # str() and unicode() on an exception with overridden __str__ that
540 # returns an ascii-only string should return the same string
541 for msg in ('foo', u'foo'):
542 self.check_same_msg(ExcWithOverriddenStr(msg=msg), msg)
543
544 # if __str__ returns a non-ascii unicode string str() should fail
545 # but unicode() should return the unicode string
546 e = ExcWithOverriddenStr(msg=u'f\xf6\xf6') # no args
547 self.assertRaises(UnicodeEncodeError, str, e)
548 self.assertEqual(unicode(e), u'f\xf6\xf6')
549
550 def test_1_arg(self):
551 """Check same msg for Exceptions with 1 arg"""
552 for arg in ('foo', u'foo'):
553 self.check_same_msg(Exception(arg), arg)
554
555 # if __str__ is not overridden and self.args[0] is a non-ascii unicode
556 # string, str() should try to return str(self.args[0]) and fail.
557 # unicode() should return unicode(self.args[0]) and succeed.
558 e = Exception(u'f\xf6\xf6')
559 self.assertRaises(UnicodeEncodeError, str, e)
560 self.assertEqual(unicode(e), u'f\xf6\xf6')
561
562 def test_1_arg_with_overridden___str__(self):
563 """Check same msg for exceptions with overridden __str__ and 1 arg"""
564 # when __str__ is overridden and __unicode__ is not implemented
565 # unicode(e) returns the same as unicode(e.__str__()).
566 for msg in ('foo', u'foo'):
567 self.check_same_msg(ExcWithOverriddenStr('arg', msg=msg), msg)
568
569 # if __str__ returns a non-ascii unicode string, str() should fail
570 # but unicode() should succeed.
571 e = ExcWithOverriddenStr('arg', msg=u'f\xf6\xf6') # 1 arg
572 self.assertRaises(UnicodeEncodeError, str, e)
573 self.assertEqual(unicode(e), u'f\xf6\xf6')
574
575 def test_many_args(self):
576 """Check same msg for Exceptions with many args"""
577 argslist = [
578 (3, 'foo'),
579 (1, u'foo', 'bar'),
580 (4, u'f\xf6\xf6', u'bar', 'baz')
581 ]
582 # both str() and unicode() should return a repr() of the args
583 for args in argslist:
584 self.check_same_msg(Exception(*args), repr(args))
585
586 def test_many_args_with_overridden___str__(self):
587 """Check same msg for exceptions with overridden __str__ and many args"""
588 # if __str__ returns an ascii string / ascii unicode string
589 # both str() and unicode() should succeed
590 for msg in ('foo', u'foo'):
591 e = ExcWithOverriddenStr('arg1', u'arg2', u'f\xf6\xf6', msg=msg)
592 self.check_same_msg(e, msg)
593
594 # if __str__ returns a non-ascii unicode string, str() should fail
595 # but unicode() should succeed
596 e = ExcWithOverriddenStr('arg1', u'f\xf6\xf6', u'arg3', # 3 args
597 msg=u'f\xf6\xf6')
598 self.assertRaises(UnicodeEncodeError, str, e)
599 self.assertEqual(unicode(e), u'f\xf6\xf6')
600
601 @cpython_only
602 def test_exception_with_doc(self):
603 import _testcapi
604 doc2 = "This is a test docstring."
605 doc4 = "This is another test docstring."
606
607 self.assertRaises(SystemError, _testcapi.make_exception_with_doc,
608 "error1")
609
610 # test basic usage of PyErr_NewException
611 error1 = _testcapi.make_exception_with_doc("_testcapi.error1")
612 self.assertIs(type(error1), type)
613 self.assertTrue(issubclass(error1, Exception))
614 self.assertIsNone(error1.__doc__)
615
616 # test with given docstring
617 error2 = _testcapi.make_exception_with_doc("_testcapi.error2", doc2)
618 self.assertEqual(error2.__doc__, doc2)
619
620 # test with explicit base (without docstring)
621 error3 = _testcapi.make_exception_with_doc("_testcapi.error3",
622 base=error2)
623 self.assertTrue(issubclass(error3, error2))
624
625 # test with explicit base tuple
626 class C(object):
627 pass
628 error4 = _testcapi.make_exception_with_doc("_testcapi.error4", doc4,
629 (error3, C))
630 self.assertTrue(issubclass(error4, error3))
631 self.assertTrue(issubclass(error4, C))
632 self.assertEqual(error4.__doc__, doc4)
633
634 # test with explicit dictionary
635 error5 = _testcapi.make_exception_with_doc("_testcapi.error5", "",
636 error4, {'a': 1})
637 self.assertTrue(issubclass(error5, error4))
638 self.assertEqual(error5.a, 1)
639 self.assertEqual(error5.__doc__, "")
640
641
642def test_main():
643 run_unittest(ExceptionTests, TestSameStrAndUnicodeMsg)
644
645if __name__ == '__main__':
646 test_main()
Note: See TracBrowser for help on using the repository browser.