Attachment 'sagetest.py'

Download

   1 import inspect, doctest, unittest, re
   2 
   3 SAGE_DOCTEST_RANDOM    = doctest.register_optionflag('SAGE_DOCTEST_RANDOM')
   4 SAGE_DOCTEST_OPTIONAL  = doctest.register_optionflag('SAGE_DOCTEST_OPTIONAL')
   5 SAGE_DOCTEST_LONG_TIME = doctest.register_optionflag('SAGE_DOCTEST_LONG_TIME')
   6 
   7 def _in_comment_re(text):
   8     r"""
   9     Look for a comment marker followed by text, but not in a string.
  10     """
  11     return re.compile(r'''
  12         ^               # anchor to beginning of string
  13         (?P<LINE>.*?)   # anything
  14         (?P<COMMENT>
  15         \#              # up to first comment marker
  16         [^\'\"\n]*?     # not followed by a quote or a newline
  17         %s              # then text
  18         [^\'\"\n]*?     # not followed by a quote or a newline
  19         \n?             # include the newline in comment
  20         )
  21         $               # anchor the end of string
  22         ''' % re.escape(text), re.MULTILINE | re.VERBOSE | re.IGNORECASE)
  23 
  24 _32BIT_RE    = _in_comment_re('32-bit')
  25 _64BIT_RE    = _in_comment_re('64-bit')
  26 
  27 _RANDOM_RE    = _in_comment_re('random')
  28 _OPTIONAL_RE  = _in_comment_re('optional')
  29 _LONG_TIME_RE = _in_comment_re('long') # ('long time')
  30 
  31 _SAGE_PROMPT_RE = re.compile(r'''
  32 ^                                # anchor to the beginning of a line
  33 (?P<SPACES>\s*?)                  # whitespace, which we want to keep
  34 (?P<PROMPT>sage:|\.\.\.\.\.)      # sage: or ..... prompt
  35 ''', re.VERBOSE | re.MULTILINE)
  36 
  37 class SageOutputChecker(doctest.OutputChecker):
  38     r"""
  39     Check the output of examples, handling SAGE extensions.
  40 
  41     At this time, the only extension is to ignore output
  42     from tests marked SAGE_DOCTEST_RANDOM.
  43     """
  44     def check_output(self, want, got, optionflags):
  45         if optionflags & SAGE_DOCTEST_RANDOM:
  46             return True
  47         return doctest.OutputChecker.check_output(self, want, got, optionflags)
  48 
  49 class SageDocTestParser(doctest.DocTestParser):
  50     r"""
  51     A DocTestParser that handles SAGE doctesting extensions.
  52 
  53     The following comments in example source set optionflags:
  54     * '# random'    -- optionflag SAGE_DOCTEST_RANDOM
  55     * '# optional'  -- optionflag SAGE_DOCTEST_OPTIONAL
  56     * '# long time' -- optionflag SAGE_DOCTEST_LONG_TIME
  57 
  58     The optionflags are handled in SageDocTestRunner.
  59 
  60     The following comments in example output are stripped:
  61     * '# 32-bit'
  62     * '# 64-bit'
  63 
  64     By default, all 64-bit output is stripped entirely, and all
  65     32-bit comments are elided.
  66     """
  67 
  68     def __init__(self, arch_is_32bit=True):
  69         if arch_is_32bit:
  70             self._filter_want = self._filter_want_32bit_arch
  71         else:
  72             self._filter_want = self._filter_want_64bit_arch
  73         # DocTestParser has no __init__, so we don't call it
  74         # doctest.DocTestParser.__init__(self)
  75 
  76     def _replace_prompts(self, string):
  77         r"""Replace sage: and ..... prompts in string."""
  78 
  79         def _repl(x):
  80             if x.group('PROMPT').startswith('.'):
  81                 return x.group('SPACES') + '...'
  82             else:
  83                 return x.group('SPACES') + '>>>'
  84 
  85         return _SAGE_PROMPT_RE.sub(_repl, string)
  86     
  87     def parse(self, string, name='<string>'):
  88         r"""
  89         Divide the given string into examples and intervening text,
  90         and return them as a list of alternating Examples and strings.
  91         """
  92 
  93         # The following string replacement primes the pump: without
  94         # this, no tests will be recognized by the regular doctest.
  95         s = self._replace_prompts(string)
  96 
  97         # Divide the given string into examples and intervening text,
  98         # and return them as a list of alternating Examples and strings.
  99         alternating_list = doctest.DocTestParser.parse(self, s, name)
 100 
 101         # Now we markup the examples with the corresponding optionflags
 102         for e in alternating_list:
 103             if isinstance(e, doctest.Example):
 104                 self.markup(e)
 105 
 106         return alternating_list
 107 
 108     def _filter_want_32bit_arch(self, want):
 109         r"""Strip 64-bit output completely, and remove 32-bit comments."""
 110         ks = []
 111         ls = want.splitlines(True) # keep '\n'
 112         for l in ls:
 113             if _64BIT_RE.match(l) is not None:
 114                 continue
 115             l = _32BIT_RE.sub(lambda x: x.group('LINE'), l).rstrip()
 116             ks.append(l)
 117         return '\n'.join(ks)
 118 
 119     def _filter_want_64bit_arch(self, want):
 120         r"""Strip 32-bit output completely, and remove 64-bit comments."""
 121         ks = []
 122         ls = want.splitlines(True) # keep '\n'
 123         for l in ls:
 124             if _32BIT_RE.match(l) is not None:
 125                 continue
 126             l = _64BIT_RE.sub(lambda x: x.group('LINE'), l).rstrip()
 127             ks.append(l)
 128         return '\n'.join(ks)
 129         
 130     def _sage_options_dict(self, example):
 131         r"""Find SAGE extensions in example and return a dict of them."""
 132         options = {}
 133 
 134         res = _RANDOM_RE.match(example.source)
 135         if res is not None:
 136             options[SAGE_DOCTEST_RANDOM] = True
 137 
 138         res = _OPTIONAL_RE.match(example.source)
 139         if res is not None:
 140             options[SAGE_DOCTEST_OPTIONAL] = True
 141 
 142         res = _LONG_TIME_RE.match(example.source)
 143         if res is not None:
 144             options[SAGE_DOCTEST_LONG_TIME] = True
 145 
 146         return options
 147         
 148     def markup(self, example):
 149         r"""
 150         Markup a single example with SAGE doctesting extensions, in place.
 151         """        
 152         # Very important to preparse!
 153         import sage.misc.preparser
 154         example.source = sage.misc.preparser.preparse(example.source)
 155         if not example.source.endswith('\n'):
 156             example.source += '\n'
 157 
 158         # Now search for SAGE doctesting extensions and update options
 159         example.options.update(self._sage_options_dict(example))
 160 
 161         # Now handle 32-bit vs 64-bit output
 162         example.want = self._filter_want(example.want)
 163         # An empty string means 'Expected nothing', so don't make append
 164         # a newline: that would make it <BLANKLINE>.
 165         if example.want != '' and not example.want.endswith('\n'):
 166             example.want += '\n'
 167 
 168 class SageDocTestFinder(doctest.DocTestFinder):
 169     r"""
 170     Find test cases in SAGE source code.
 171     """
 172 
 173     def __init__(self, sage_optionflags=0, arch_is_32bit=True,
 174                  *args, **kwargs):
 175         r"""
 176         Create a new SAGE doctest finder.
 177         
 178         If SAGE_DOCTEST_LONG_TIME is set in sage_optionflags, test long
 179         running examples.
 180 
 181         If SAGE_DOCTEST_OPTIONAL is set in sage_optionflags, test
 182         optional examples.
 183         """
 184 
 185         self.sage_optionflags = sage_optionflags
 186         parser = SageDocTestParser(arch_is_32bit=arch_is_32bit)
 187         doctest.DocTestFinder.__init__(self, parser=parser, *args, **kwargs)
 188 
 189     def _from_module(self, module, object):
 190         """
 191         Return true if the given object is defined in the given
 192         module.
 193 
 194         Extends the default implementation to support Sagex extension code.
 195         """
 196 
 197         # I can't determine what module a method_descriptor belongs to.
 198         if inspect.ismethoddescriptor(object):
 199             return True
 200         return doctest.DocTestFinder._from_module(self, module, object)
 201 
 202     def _find(self, tests, obj, name, module, source_lines, globs, seen):
 203         """
 204         Find tests for the given object and any contained objects, and
 205         add them to `tests`.
 206 
 207         Extends the default implementation to handle Sagex extension code.
 208         """
 209 
 210         # Start with default search
 211         doctest.DocTestFinder._find(self, tests, obj, name, module, source_lines,
 212                                     globs, seen)
 213         
 214         # Look for tests in a module's contained Sagex objects.
 215         if inspect.ismodule(obj) and self._recurse:
 216             for valname, val in obj.__dict__.items():
 217                 valname = '%s.%s' % (name, valname)
 218                 # Recurse to extension routines
 219                 if (inspect.isroutine(val) and
 220                     self._from_module(module, val)):
 221                     self._find(tests, val, valname, module, source_lines,
 222                                globs, seen)
 223 
 224         # Look for tests in a class's contained Sagex objects.
 225         if inspect.isclass(obj) and self._recurse:
 226             for valname, val in obj.__dict__.items():
 227                 # Recurse to extension routines
 228                 if (inspect.isroutine(val) and
 229                       self._from_module(module, val)):
 230                     valname = '%s.%s' % (name, valname)
 231                     self._find(tests, val, valname, module, source_lines,
 232                                globs, seen)
 233         
 234 
 235     def find(self, *args, **kwargs):
 236         r"""
 237         Return a list of the DocTests that are defined by the given
 238         object's docstring, or by any of its contained objects'
 239         docstrings.
 240 
 241         Examples are removed if they are optional or run for a long time
 242         and the corresponding flags are not set in `self.sage_optionflags`.
 243         """
 244         
 245         test_optional  = self.sage_optionflags & SAGE_DOCTEST_OPTIONAL
 246         test_long_time = self.sage_optionflags & SAGE_DOCTEST_LONG_TIME
 247 
 248         tests = doctest.DocTestFinder.find(self, *args, **kwargs)
 249         # print tests
 250 
 251         # Maybe remove optional tests
 252         if not test_optional:
 253             for t in tests:
 254                 for e in t.examples:
 255                     if e.options.get(SAGE_DOCTEST_OPTIONAL, False):
 256                         e.options[doctest.SKIP] = True
 257 
 258         # Maybe remove long time tests
 259         if not test_long_time:
 260             for t in tests:
 261                 for e in t.examples:
 262                     if e.options.get(SAGE_DOCTEST_LONG_TIME, False):
 263                         e.options[doctest.SKIP] = True
 264 
 265                 # t.examples = [ e for e in t.examples if not e.options.get(SAGE_DOCTEST_LONG_TIME, False) ]
 266 
 267         return tests
 268 
 269 def _sagetest(obj=None, name=None, globs=None, verbose=None,
 270               report=True, optionflags=0, extraglobs=None,
 271               raise_on_error=False, exclude_empty=True,
 272               recurse_modules=True, arch_is_32bit=True,
 273               sage_optionflags=0):
 274     r"""
 275     Internal routine to test SAGE object `obj`.
 276     """
 277 
 278     # Find, parse, and run all tests in the given module.
 279     finder = SageDocTestFinder(sage_optionflags=sage_optionflags, exclude_empty=exclude_empty, recurse=True)
 280 
 281     if raise_on_error:
 282         runner = doctest.DebugRunner(checker=SageOutputChecker(),
 283                                      verbose=verbose, optionflags=optionflags)
 284     else:
 285         runner = doctest.DocTestRunner(checker=SageOutputChecker(),
 286                                        verbose=verbose, optionflags=optionflags)
 287 
 288 #     import inspect
 289 #     L = [(name, m)]
 290 #     if inspect.ismodule(m) and recurse_modules:
 291 #         L.extend(inspect.getmembers(m, inspect.ismodule))
 292 #     for (n, o) in L:
 293 #          print n # , o
 294 
 295     tests = finder.find(obj, name, globs=globs, extraglobs=extraglobs)
 296     non_empty_count = 0
 297     for test in tests:
 298         if len(test.examples) > 0:
 299             non_empty_count += 1
 300         runner.run(test)
 301 
 302     if report:
 303         runner.summarize()
 304 
 305     return (runner.failures, runner.tries, len(tests) - non_empty_count)
 306 
 307 #     return { 'examples failed': runner.failures,
 308 #              'examples run': runner.tries,
 309 #              'docstrings tested': len(tests),
 310 #              'docstrings with examples': non_empty_count
 311 #            }
 312 
 313 # def _sagetestfile(filename, module_relative=True, name=None, package=None,
 314 #                   globs=None, verbose=None, report=True, optionflags=0,
 315 #                   extraglobs=None, raise_on_error=False,
 316 #                   parser=SageDocTestParser(), encoding=None,
 317 #                   arch_is_32bit=True,
 318 #                   sage_optionflags=0):
 319 
 320 #     if package and not module_relative:
 321 #         raise ValueError("Package may only be specified for module-"
 322 #                          "relative paths.")
 323 
 324 #     # Relativize the path
 325 #     text, filename = doctest._load_testfile(filename, package, module_relative)
 326 
 327 #     # If no name was given, then use the file's name.
 328 #     if name is None:
 329 #         name = os.path.basename(filename)
 330 
 331 #     # Assemble the globals.
 332 #     if globs is None:
 333 #         globs = {}
 334 #     else:
 335 #         globs = globs.copy()
 336 #     if extraglobs is not None:
 337 #         globs.update(extraglobs)
 338 
 339 #     if raise_on_error:
 340 #         runner = doctest.DebugRunner(checker=SageOutputChecker(),
 341 #                              verbose=verbose, optionflags=optionflags)
 342 #     else:
 343 #         runner = doctest.DocTestRunner(checker=SageOutputChecker(),
 344 #                                        verbose=verbose, optionflags=optionflags)
 345 
 346 #     if encoding is not None:
 347 #         text = text.decode(encoding)
 348 
 349 #     # Read the file, convert it to a test, and run it.
 350 #     test = parser.get_doctest(text, globs, name, filename, 0)
 351 #     runner.run(test)
 352 
 353 #     if report:
 354 #         runner.summarize()
 355 
 356 #     return runner.failures, runner.tries    
 357 
 358 def sagetestfile(filename="",
 359                  arch_is_32bit=True,
 360                  sage_optionflags=0,
 361                  raise_on_error=False,
 362                  report=True,
 363                  ):
 364     r"""
 365     Test file `filename`, taking care of IPython hooks.
 366     """
 367 
 368     import sys
 369     hooks = (sys.displayhook, sys.excepthook)
 370     try:
 371         try:
 372             sys.displayhook = sys.__displayhook__
 373             sys.excepthook = sys.__excepthook__
 374         except:
 375             pass
 376 
 377         globs = {} ; exec "from sage.all_cmdline import *" in globs
 378         optionflags = doctest.ELLIPSIS | doctest.IGNORE_EXCEPTION_DETAIL | doctest.NORMALIZE_WHITESPACE
 379         
 380 #         return _sagetestfile(filename, module_relative=False, name=None,
 381 #                              package=None,
 382 #                              globs=globs, verbose=verbose, report=True,
 383 #                              optionflags=optionflags,
 384 #                              extraglobs=None, raise_on_error=raise_on_error,
 385 #                              parser=SageDocTestParser(), encoding=None,
 386 #                              arch_is_32bit=arch_is_32bit,
 387 #                              sage_optionflags=sage_optionflags)
 388 
 389         fglobals = {}
 390         flocals = {}
 391         exec "import %s as m; reload(m)" % filename in fglobals, flocals
 392 
 393         mod = flocals['m']
 394         if inspect.ismodule(mod):
 395             return _sagetest(mod, name=mod.__name__,
 396                              globs=globs,
 397                              extraglobs=mod.__dict__,
 398                              optionflags=optionflags,
 399                              sage_optionflags=sage_optionflags,
 400                              arch_is_32bit=arch_is_32bit,
 401                              report=report,
 402                              )
 403 
 404     finally:
 405         try:
 406             sys.displayhook = hooks[0]
 407             sys.excepthook  = hooks[1]
 408         except:
 409             pass
 410 
 411 def sagetest(obj=None, arch_is_32bit=True, sage_optionflags=0, **kwargs):
 412     r"""
 413     Test SAGE object `obj`, taking care of IPython hooks.
 414     """
 415 
 416     import sys
 417     hooks = (sys.displayhook, sys.excepthook)
 418     try:
 419         try:
 420             sys.displayhook = sys.__displayhook__
 421             sys.excepthook = sys.__excepthook__
 422         except:
 423             pass
 424 
 425         globs = {} ; exec "from sage.all_cmdline import *" in globs
 426         optionflags = doctest.ELLIPSIS | doctest.IGNORE_EXCEPTION_DETAIL | doctest.NORMALIZE_WHITESPACE
 427         return _sagetest(obj, name=str(obj), optionflags=optionflags,
 428                          globs=globs, arch_is_32bit=arch_is_32bit,
 429                          sage_optionflags=sage_optionflags,
 430                          **kwargs)
 431     finally:
 432         try:
 433             sys.displayhook = hooks[0]
 434             sys.excepthook  = hooks[1]
 435         except:
 436             pass
 437 
 438 # def SageDocFileSuite(*paths, **kw):
 439 #     print paths
 440 #     return doctest.DocFileSuite(*paths, **kw)
 441 
 442 def helper_func():
 443     r"""
 444     sage: def Integer(n):
 445     .....     return n
 446     sage: 2
 447     2 # 32-bit
 448     2 # 64-bit
 449 
 450     # sage: R.<x> = ['x'] # long time
 451     sage: def blah(z, x):
 452     .....     return 2
 453     sage: blah(2, x=None) # optional # long time
 454     2
 455 
 456     sage: 2 # random
 457     3
 458 
 459     sage: 2
 460     3
 461 
 462     sage: blah(2, x=None) # long time # optional
 463     2
 464 
 465     sage: 3 # long time
 466     3
 467 
 468     sage: 4 # optional
 469     4
 470     """
 471 
 472 def internal_tests():
 473     r'''
 474     Test a file:
 475         >>> sagetestfile(filename="test1", raise_on_error=False)
 476     
 477     # SAGE_DOCTEST_LONG_TIME | SAGE_DOCTEST_OPTIONAL
 478     Fix a bug:
 479         >>> fs = 0
 480         >>> D = {} ; exec "from sage.all_cmdline import *" in D
 481         
 482         >>> T = SageDocTestFinder(recurse=True, sage_optionflags=fs).find(sage.rings.rational, globs=D)
 483         >>> T = [ t for t in T if len(t.examples) > 0 ]
 484         >>> len(T)
 485 
 486         >>> sum([ len(t.examples) for t in T])
 487 
 488         >>> X = [ (t.name, len(t.examples)) for t in T ]
 489         >>> r = doctest.DocTestRunner(optionflags=doctest.NORMALIZE_WHITESPACE)
 490         >>> for t in T:
 491         ...     r.run(t)
 492         (0, ...)
 493         
 494 #         >>> for x in X:
 495 #         ...     print x
 496 
 497 #         >>> SageDocTestFinder(recurse=True).find(sage.rings.rational.Rational.__index__)
 498 #         >>> SageDocTestFinder(recurse=True).find(sage.rings.rational.Rational.list)
 499 #         >>> SageDocTestFinder(recurse=True).find(sage.rings.rational.Rational)
 500 #         >>> SageDocTestFinder(recurse=True).find(sage.rings.rational)
 501 
 502 #         >>> SageDocTestFinder(recurse=True).find(SageDocTestFinder)
 503     '''
 504 
 505 r'''
 506 
 507 #     Make some examples into a unittest suite:
 508 
 509 #         >>> doctest.DocFileSuite('sagetestnewadsf.py')
 510 #         >>> SageDocFileSuite('sagetestnewadsf.py')
 511 
 512     Find some examples:
 513 
 514         >>> f = SageDocTestFinder()
 515         >>> f.find(helper_func)
 516         [...(4 examples)>]
 517 
 518         >>> f.find(helper_func)
 519         [...(4 examples)>]
 520 
 521         >>> f.sage_optionflags = SAGE_DOCTEST_LONG_TIME
 522         >>> f.find(helper_func)
 523         [...(5 examples)>]
 524         
 525         >>> f.sage_optionflags = SAGE_DOCTEST_OPTIONAL
 526         >>> f.find(helper_func)
 527         [...(5 examples)>]
 528 
 529         >>> f.sage_optionflags = SAGE_DOCTEST_OPTIONAL | SAGE_DOCTEST_LONG_TIME
 530         >>> f.find(helper_func)
 531         [...(8 examples)>]
 532             
 533     Parse some examples:
 534 
 535         >>> p = SageDocTestParser()
 536         >>> es = p.parse("""
 537         ... sage: test()
 538         ... sage: R.<x> = Z['x'] # long time
 539         ... sage: time blah(2, x=None) # optional # long time
 540         ... sage: time blah(2, x=None) # long time # optional
 541         ... """)
 542         >>> for e in es:
 543         ...     if isinstance(e, doctest.Example):
 544         ...         print sorted(e.options.keys())
 545         ...         print e.source,
 546         []
 547         test()
 548         [4096]
 549         R = Z["x"] ; (x,) = R.gens()# long time
 550         [2048, 4096]
 551         time blah(Integer(2), x=None) # optional # long time
 552         [2048, 4096]
 553         time blah(Integer(2), x=None) # long time # optional
 554 
 555     Run some examples:
 556     
 557         >>> p = SageDocTestParser()
 558         >>> f = doctest.DocTestFinder(parser=p)
 559         >>> t = f.find(helper_func, globs=globals())[0]
 560         >>> r = doctest.DocTestRunner(checker=SageOutputChecker())
 561         >>> r.run(t)
 562         (0, 8)
 563 
 564 #     Check some text:
 565 #         >>> c = SageOutputChecker()
 566 #         >>> c.check_output('test', 'test', 0)
 567 #         >>> c.check_output('test', 'test2', 0)
 568 
 569 #         >>> r = SageDocTestRunner()
 570 #         >>> r._filter_examples(t.examples, {SAGE_DOCTEST_OPTIONAL : True})
 571 #         [...]
 572 #         >>> r._filter_examples(t.examples, {SAGE_DOCTEST_LONG_TIME: True})
 573 #         [...,...]
 574 #         >>> r.run(t)
 575 #         (0, ...)
 576 #         >>> r.run(t)
 577 #         (0, ...)
 578 
 579     Verify that prompt replacement is working as desired:
 580 
 581         >>> p._replace_prompts("""
 582         ... sage: blah
 583         ... sage blah sage: nuts
 584         ... sage: first part .....
 585         ... ..... second part
 586         ... ... test
 587         ...    sage: test
 588         ...    ..... blah
 589         ... """).strip()
 590         '>>> blah\nsage blah sage: nuts\n>>> first part .....\n... second part\n... test\n   >>> test\n   ... blah'        
 591 
 592     Verify that our regular expressions are reasonable:
 593     
 594         >>> _RANDOM_RE.findall("""
 595         ... blah # random
 596         ... 'blah # random''
 597         ... blah # random''
 598         ... blah # comp # rando m
 599         ... blah random #random
 600         ... random # RANDom
 601         ... test""")
 602         [('blah ', '# random'), ('blah random ', '#random'), ('random ', '# RANDom')]
 603 
 604         >>> _OPTIONAL_RE.findall("""
 605         ... blah # optional
 606         ... 'blah # optional'
 607         ... blah # OPTioNAL
 608         ... blah #optIONal''
 609         ... test""")
 610         [('blah ', '# optional'), ('blah ', '# OPTioNAL')]        
 611     
 612         >>> _LONG_TIME_RE.findall("""
 613         ... blah # long time
 614         ... 'blah # long time'
 615         ... blah # LONG time
 616         ... blah #LONG time''
 617         ... test""")
 618         [('blah ', '# long time'), ('blah ', '# LONG time')]
 619     ''' # Emacs syntax highlighting gets confused without this "
 620 
 621 def stable_sagetest(m=None, name=None, globs=None, verbose=None,
 622             report=True, optionflags=0, extraglobs=None,
 623             raise_on_error=False, exclude_empty=True,
 624             recurse_modules=True):
 625     r"""
 626     Internal testing routine, until the code stablizes.
 627     """
 628     # global master
 629 
 630     # If no module was given, then use __main__.
 631     if m is None:
 632         # DWA - m will still be None if this wasn't invoked from the command
 633         # line, in which case the following TypeError is about as good an error
 634         # as we should expect
 635         m = sys.modules.get('__main__')
 636 
 637     # Check that we were actually given a module.
 638     # if not inspect.ismodule(m):
 639     #    raise TypeError("testmod: module required; %r" % (m,))
 640 
 641     # If no name was given, then use the module's name.
 642     if name is None:
 643         name = m.__name__
 644 
 645     # Find, parse, and run all tests in the given module.
 646     parser = doctest.DocTestParser()
 647     finder = doctest.DocTestFinder(exclude_empty=exclude_empty, parser=parser, recurse=True)
 648 
 649     if raise_on_error:
 650         runner = doctest.DebugRunner(verbose=verbose, optionflags=optionflags)
 651     else:
 652         runner = doctest.DocTestRunner(verbose=verbose, optionflags=optionflags)
 653 
 654     import inspect
 655     L = [(name, m)]
 656     if inspect.ismodule(m) and recurse_modules:
 657         L.extend(inspect.getmembers(m, inspect.ismodule))
 658 
 659     for (n, o) in L:
 660         # print n # , o
 661         for test in finder.find(o, n, globs=globs, extraglobs=extraglobs):
 662             # for e in test.examples[0:5]:
 663             #    print sage.misc.preparser.preparse(e.source)
 664             # pass
 665             runner.run(test)
 666 
 667     if report:
 668         runner.summarize()
 669 
 670     # if doctest.master is None:
 671     doctest.master = runner
 672     # else:
 673     #    doctest.master.merge(runner)
 674 
 675     return runner.failures, runner.tries
 676     
 677 def stable_test(obj=None):
 678     import sys
 679     hooks = (sys.displayhook, sys.excepthook)
 680     try:
 681         try:
 682             sys.displayhook = sys.__displayhook__
 683             sys.excepthook = sys.__excepthook__
 684         except:
 685             pass
 686     
 687         print stable_sagetest(obj, name=str(obj)
 688                        , optionflags=doctest.ELLIPSIS
 689                        | doctest.IGNORE_EXCEPTION_DETAIL
 690                        | doctest.NORMALIZE_WHITESPACE,
 691                        globs=globals()
 692                        )
 693 
 694 #         X = doctest.DocTestSuite(module=sage.rings.rational,
 695 #                                  test_finder=SageDocTestFinder(),
 696 #                                  globs=globals(),
 697 #                                  optionflags = doctest.IGNORE_EXCEPTION_DETAIL | doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE)
 698 
 699 #         X = doctest.DocTestSuite(module=sage.rings.rational,
 700 #                                  test_finder=SageDocTestFinder(),
 701 #                                  globs=globals(),
 702 #                                  optionflags = doctest.IGNORE_EXCEPTION_DETAIL | doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE)
 703 
 704         
 705 #         # print [ [ e.source for e in t._dt_test.examples ] for t in X._tests ]
 706 #         runner = unittest.TextTestRunner()
 707 #         runner.run(X)
 708 
 709     finally:
 710         try:
 711             sys.displayhook = hooks[0]
 712             sys.excepthook  = hooks[1]
 713         except:
 714             pass
 715 
 716 if __name__ == '__main__':
 717     # stable_test(internal_tests)
 718     pass
 719 
 720 # class SageDocTestRunner(doctest.DocTestRunner):
 721 #     r"""
 722 #     Run test cases according to SAGE extensions.
 723 
 724 #     This means checking output with a SageOutputChecker, and
 725 #     skipping examples marked with SAGE_DOCTEST_OPTIONAL or
 726 #     SAGE_DOCTEST_LONG_TIME if those flags are not set.
 727 #     """
 728 
 729 #     def __init__(self, *args, **kwargs):
 730 #         checker = SageOutputChecker()
 731 #         return doctest.DocTestRunner.__init__(self, checker=checker, *args, **kwargs)
 732     
 733 #     def _filter_examples(self, examples, sage_options):
 734 #         r"""
 735 #         Filter examples we don't want from test.
 736 #         """
 737 #         if sage_options is None: sage_options = {}
 738 #         optional  = sage_options.get(SAGE_DOCTEST_OPTIONAL, False)
 739 #         long_time = sage_options.get(SAGE_DOCTEST_LONG_TIME, False)
 740 
 741 #         # Filter the examples we don't want
 742 #         L = []
 743 #         for e in examples:
 744 #             # print e.options.get(SAGE_DOCTEST_OPTIONAL, False), optional
 745             
 746 #             if e.options.get(SAGE_DOCTEST_OPTIONAL, False)  and not optional:
 747 #                 continue
 748 #             if e.options.get(SAGE_DOCTEST_LONG_TIME, False) and not long_time:
 749 #                 continue
 750 #             L.append(e)
 751 #         return L
 752 
 753 #     def run(self, test, compileflags=None, out=None, clear_globs=True, sage_options=None):
 754 #         r"""
 755 #         Run the examples in `test`, and display the results using the
 756 #         write function `out`.
 757 
 758 #         `sage_options` should be a hash containing SAGE_DOCTEST_* flags.
 759 #         If sage_options[SAGE_DOCTEST_OPTIONAL] is True, run tests marked optional.
 760 #         If sage_options[SAGE_DOCTEST_LONG_TIME] is True, run tests marked long time.
 761 #         """
 762 
 763 #         # Filter examples we don't want
 764 #         orig = test.examples
 765 #         test.examples = self._filter_examples(test.examples, sage_options)
 766 
 767 #         # Run remaining examples
 768 #         res = doctest.DocTestRunner.run(self, test, compileflags, out, clear_globs)
 769 
 770 #         # Replace examples we didn't run
 771 #         test.examples = orig
 772 
 773 #         return res

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.