@@ -101,15 +101,14 @@ def _test():
101101import re
102102import sys
103103import traceback
104+ import types
104105import unittest
105106from io import StringIO , IncrementalNewlineDecoder
106107from collections import namedtuple
107108import _colorize # Used in doctests
108109from _colorize import ANSIColors , can_colorize
109110
110111
111- __unittest = True
112-
113112class TestResults (namedtuple ('TestResults' , 'failed attempted' )):
114113 def __new__ (cls , failed , attempted , * , skipped = 0 ):
115114 results = super ().__new__ (cls , failed , attempted )
@@ -387,7 +386,7 @@ def __init__(self, out):
387386 self .__out = out
388387 self .__debugger_used = False
389388 # do not play signal games in the pdb
390- pdb . Pdb . __init__ (self , stdout = out , nosigint = True )
389+ super (). __init__ (stdout = out , nosigint = True )
391390 # still use input() to get user input
392391 self .use_rawinput = 1
393392
@@ -1280,6 +1279,11 @@ def __init__(self, checker=None, verbose=None, optionflags=0):
12801279 # Reporting methods
12811280 #/////////////////////////////////////////////////////////////////
12821281
1282+ def report_skip (self , out , test , example ):
1283+ """
1284+ Report that the given example was skipped.
1285+ """
1286+
12831287 def report_start (self , out , test , example ):
12841288 """
12851289 Report that the test runner is about to process the given
@@ -1377,6 +1381,8 @@ def __run(self, test, compileflags, out):
13771381
13781382 # If 'SKIP' is set, then skip this example.
13791383 if self .optionflags & SKIP :
1384+ if not quiet :
1385+ self .report_skip (out , test , example )
13801386 skips += 1
13811387 continue
13821388
@@ -2275,12 +2281,63 @@ def set_unittest_reportflags(flags):
22752281 return old
22762282
22772283
2284+ class _DocTestCaseRunner (DocTestRunner ):
2285+
2286+ def __init__ (self , * args , test_case , test_result , ** kwargs ):
2287+ super ().__init__ (* args , ** kwargs )
2288+ self ._test_case = test_case
2289+ self ._test_result = test_result
2290+ self ._examplenum = 0
2291+
2292+ def _subTest (self ):
2293+ subtest = unittest .case ._SubTest (self ._test_case , str (self ._examplenum ), {})
2294+ self ._examplenum += 1
2295+ return subtest
2296+
2297+ def report_skip (self , out , test , example ):
2298+ unittest .case ._addSkip (self ._test_result , self ._subTest (), '' )
2299+
2300+ def report_success (self , out , test , example , got ):
2301+ self ._test_result .addSubTest (self ._test_case , self ._subTest (), None )
2302+
2303+ def report_unexpected_exception (self , out , test , example , exc_info ):
2304+ tb = self ._add_traceback (exc_info [2 ], test , example )
2305+ exc_info = (* exc_info [:2 ], tb )
2306+ self ._test_result .addSubTest (self ._test_case , self ._subTest (), exc_info )
2307+
2308+ def report_failure (self , out , test , example , got ):
2309+ msg = ('Failed example:\n ' + _indent (example .source ) +
2310+ self ._checker .output_difference (example , got , self .optionflags ).rstrip ('\n ' ))
2311+ exc = self ._test_case .failureException (msg )
2312+ tb = self ._add_traceback (None , test , example )
2313+ exc_info = (type (exc ), exc , tb )
2314+ self ._test_result .addSubTest (self ._test_case , self ._subTest (), exc_info )
2315+
2316+ def _add_traceback (self , traceback , test , example ):
2317+ if test .lineno is None or example .lineno is None :
2318+ lineno = None
2319+ else :
2320+ lineno = test .lineno + example .lineno + 1
2321+ return types .SimpleNamespace (
2322+ tb_frame = types .SimpleNamespace (
2323+ f_globals = test .globs ,
2324+ f_code = types .SimpleNamespace (
2325+ co_filename = test .filename ,
2326+ co_name = test .name ,
2327+ ),
2328+ ),
2329+ tb_next = traceback ,
2330+ tb_lasti = - 1 ,
2331+ tb_lineno = lineno ,
2332+ )
2333+
2334+
22782335class DocTestCase (unittest .TestCase ):
22792336
22802337 def __init__ (self , test , optionflags = 0 , setUp = None , tearDown = None ,
22812338 checker = None ):
22822339
2283- unittest . TestCase . __init__ (self )
2340+ super (). __init__ ()
22842341 self ._dt_optionflags = optionflags
22852342 self ._dt_checker = checker
22862343 self ._dt_test = test
@@ -2304,30 +2361,28 @@ def tearDown(self):
23042361 test .globs .clear ()
23052362 test .globs .update (self ._dt_globs )
23062363
2364+ def run (self , result = None ):
2365+ self ._test_result = result
2366+ return super ().run (result )
2367+
23072368 def runTest (self ):
23082369 test = self ._dt_test
2309- old = sys .stdout
2310- new = StringIO ()
23112370 optionflags = self ._dt_optionflags
2371+ result = self ._test_result
23122372
23132373 if not (optionflags & REPORTING_FLAGS ):
23142374 # The option flags don't include any reporting flags,
23152375 # so add the default reporting flags
23162376 optionflags |= _unittest_reportflags
2377+ if getattr (result , 'failfast' , False ):
2378+ optionflags |= FAIL_FAST
23172379
2318- runner = DocTestRunner (optionflags = optionflags ,
2319- checker = self ._dt_checker , verbose = False )
2320-
2321- try :
2322- runner .DIVIDER = "-" * 70
2323- results = runner .run (test , out = new .write , clear_globs = False )
2324- if results .skipped == results .attempted :
2325- raise unittest .SkipTest ("all examples were skipped" )
2326- finally :
2327- sys .stdout = old
2328-
2329- if results .failed :
2330- raise self .failureException (self .format_failure (new .getvalue ().rstrip ('\n ' )))
2380+ runner = _DocTestCaseRunner (optionflags = optionflags ,
2381+ checker = self ._dt_checker , verbose = False ,
2382+ test_case = self , test_result = result )
2383+ results = runner .run (test , clear_globs = False )
2384+ if results .skipped == results .attempted :
2385+ raise unittest .SkipTest ("all examples were skipped" )
23312386
23322387 def format_failure (self , err ):
23332388 test = self ._dt_test
@@ -2442,7 +2497,7 @@ def shortDescription(self):
24422497class SkipDocTestCase (DocTestCase ):
24432498 def __init__ (self , module ):
24442499 self .module = module
2445- DocTestCase .__init__ (self , None )
2500+ super () .__init__ (None )
24462501
24472502 def setUp (self ):
24482503 self .skipTest ("DocTestSuite will not work with -O2 and above" )
0 commit comments