| 1 |
# This is a slightly modified version of the doctest.py that shipped with Python 2.4 |
|---|
| 2 |
# It incorporates changes that have been submitted the the Python ticket tracker |
|---|
| 3 |
# as ticket #1521051. These changes allow for a DoctestRunner and Doctest base |
|---|
| 4 |
# class to be specified when constructing a DoctestSuite. |
|---|
| 5 |
|
|---|
| 6 |
# Module doctest. |
|---|
| 7 |
# Released to the public domain 16-Jan-2001, by Tim Peters (tim@python.org). |
|---|
| 8 |
# Major enhancements and refactoring by: |
|---|
| 9 |
# Jim Fulton |
|---|
| 10 |
# Edward Loper |
|---|
| 11 |
|
|---|
| 12 |
# Provided as-is; use at your own risk; no warranty; no promises; enjoy! |
|---|
| 13 |
|
|---|
| 14 |
r"""Module doctest -- a framework for running examples in docstrings. |
|---|
| 15 |
|
|---|
| 16 |
In simplest use, end each module M to be tested with: |
|---|
| 17 |
|
|---|
| 18 |
def _test(): |
|---|
| 19 |
import doctest |
|---|
| 20 |
doctest.testmod() |
|---|
| 21 |
|
|---|
| 22 |
if __name__ == "__main__": |
|---|
| 23 |
_test() |
|---|
| 24 |
|
|---|
| 25 |
Then running the module as a script will cause the examples in the |
|---|
| 26 |
docstrings to get executed and verified: |
|---|
| 27 |
|
|---|
| 28 |
python M.py |
|---|
| 29 |
|
|---|
| 30 |
This won't display anything unless an example fails, in which case the |
|---|
| 31 |
failing example(s) and the cause(s) of the failure(s) are printed to stdout |
|---|
| 32 |
(why not stderr? because stderr is a lame hack <0.2 wink>), and the final |
|---|
| 33 |
line of output is "Test failed.". |
|---|
| 34 |
|
|---|
| 35 |
Run it with the -v switch instead: |
|---|
| 36 |
|
|---|
| 37 |
python M.py -v |
|---|
| 38 |
|
|---|
| 39 |
and a detailed report of all examples tried is printed to stdout, along |
|---|
| 40 |
with assorted summaries at the end. |
|---|
| 41 |
|
|---|
| 42 |
You can force verbose mode by passing "verbose=True" to testmod, or prohibit |
|---|
| 43 |
it by passing "verbose=False". In either of those cases, sys.argv is not |
|---|
| 44 |
examined by testmod. |
|---|
| 45 |
|
|---|
| 46 |
There are a variety of other ways to run doctests, including integration |
|---|
| 47 |
with the unittest framework, and support for running non-Python text |
|---|
| 48 |
files containing doctests. There are also many ways to override parts |
|---|
| 49 |
of doctest's default behaviors. See the Library Reference Manual for |
|---|
| 50 |
details. |
|---|
| 51 |
""" |
|---|
| 52 |
|
|---|
| 53 |
__docformat__ = 'reStructuredText en' |
|---|
| 54 |
|
|---|
| 55 |
__all__ = [ |
|---|
| 56 |
# 0, Option Flags |
|---|
| 57 |
'register_optionflag', |
|---|
| 58 |
'DONT_ACCEPT_TRUE_FOR_1', |
|---|
| 59 |
'DONT_ACCEPT_BLANKLINE', |
|---|
| 60 |
'NORMALIZE_WHITESPACE', |
|---|
| 61 |
'ELLIPSIS', |
|---|
| 62 |
'IGNORE_EXCEPTION_DETAIL', |
|---|
| 63 |
'COMPARISON_FLAGS', |
|---|
| 64 |
'REPORT_UDIFF', |
|---|
| 65 |
'REPORT_CDIFF', |
|---|
| 66 |
'REPORT_NDIFF', |
|---|
| 67 |
'REPORT_ONLY_FIRST_FAILURE', |
|---|
| 68 |
'REPORTING_FLAGS', |
|---|
| 69 |
# 1. Utility Functions |
|---|
| 70 |
'is_private', |
|---|
| 71 |
# 2. Example & DocTest |
|---|
| 72 |
'Example', |
|---|
| 73 |
'DocTest', |
|---|
| 74 |
# 3. Doctest Parser |
|---|
| 75 |
'DocTestParser', |
|---|
| 76 |
# 4. Doctest Finder |
|---|
| 77 |
'DocTestFinder', |
|---|
| 78 |
# 5. Doctest Runner |
|---|
| 79 |
'DocTestRunner', |
|---|
| 80 |
'OutputChecker', |
|---|
| 81 |
'DocTestFailure', |
|---|
| 82 |
'UnexpectedException', |
|---|
| 83 |
'DebugRunner', |
|---|
| 84 |
# 6. Test Functions |
|---|
| 85 |
'testmod', |
|---|
| 86 |
'testfile', |
|---|
| 87 |
'run_docstring_examples', |
|---|
| 88 |
# 7. Tester |
|---|
| 89 |
'Tester', |
|---|
| 90 |
# 8. Unittest Support |
|---|
| 91 |
'DocTestSuite', |
|---|
| 92 |
'DocFileSuite', |
|---|
| 93 |
'set_unittest_reportflags', |
|---|
| 94 |
# 9. Debugging Support |
|---|
| 95 |
'script_from_examples', |
|---|
| 96 |
'testsource', |
|---|
| 97 |
'debug_src', |
|---|
| 98 |
'debug', |
|---|
| 99 |
] |
|---|
| 100 |
|
|---|
| 101 |
import __future__ |
|---|
| 102 |
|
|---|
| 103 |
import sys, traceback, inspect, linecache, os, re |
|---|
| 104 |
import unittest, difflib, pdb, tempfile |
|---|
| 105 |
import warnings |
|---|
| 106 |
from StringIO import StringIO |
|---|
| 107 |
|
|---|
| 108 |
if sys.platform.startswith('java'): |
|---|
| 109 |
# On Jython, isclass() reports some modules as classes. Patch it. |
|---|
| 110 |
def patch_isclass(isclass): |
|---|
| 111 |
def patched_isclass(obj): |
|---|
| 112 |
return isclass(obj) and hasattr(obj, '__module__') |
|---|
| 113 |
return patched_isclass |
|---|
| 114 |
inspect.isclass = patch_isclass(inspect.isclass) |
|---|
| 115 |
|
|---|
| 116 |
# Don't whine about the deprecated is_private function in this |
|---|
| 117 |
# module's tests. |
|---|
| 118 |
warnings.filterwarnings("ignore", "is_private", DeprecationWarning, |
|---|
| 119 |
__name__, 0) |
|---|
| 120 |
|
|---|
| 121 |
# There are 4 basic classes: |
|---|
| 122 |
# - Example: a <source, want> pair, plus an intra-docstring line number. |
|---|
| 123 |
# - DocTest: a collection of examples, parsed from a docstring, plus |
|---|
| 124 |
# info about where the docstring came from (name, filename, lineno). |
|---|
| 125 |
# - DocTestFinder: extracts DocTests from a given object's docstring and |
|---|
| 126 |
# its contained objects' docstrings. |
|---|
| 127 |
# - DocTestRunner: runs DocTest cases, and accumulates statistics. |
|---|
| 128 |
# |
|---|
| 129 |
# So the basic picture is: |
|---|
| 130 |
# |
|---|
| 131 |
# list of: |
|---|
| 132 |
# +------+ +---------+ +-------+ |
|---|
| 133 |
# |object| --DocTestFinder-> | DocTest | --DocTestRunner-> |results| |
|---|
| 134 |
# +------+ +---------+ +-------+ |
|---|
| 135 |
# | Example | |
|---|
| 136 |
# | ... | |
|---|
| 137 |
# | Example | |
|---|
| 138 |
# +---------+ |
|---|
| 139 |
|
|---|
| 140 |
# Option constants. |
|---|
| 141 |
|
|---|
| 142 |
OPTIONFLAGS_BY_NAME = {} |
|---|
| 143 |
def register_optionflag(name): |
|---|
| 144 |
flag = 1 << len(OPTIONFLAGS_BY_NAME) |
|---|
| 145 |
OPTIONFLAGS_BY_NAME[name] = flag |
|---|
| 146 |
return flag |
|---|
| 147 |
|
|---|
| 148 |
DONT_ACCEPT_TRUE_FOR_1 = register_optionflag('DONT_ACCEPT_TRUE_FOR_1') |
|---|
| 149 |
DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE') |
|---|
| 150 |
NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE') |
|---|
| 151 |
ELLIPSIS = register_optionflag('ELLIPSIS') |
|---|
| 152 |
IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL') |
|---|
| 153 |
|
|---|
| 154 |
COMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 | |
|---|
| 155 |
DONT_ACCEPT_BLANKLINE | |
|---|
| 156 |
NORMALIZE_WHITESPACE | |
|---|
| 157 |
ELLIPSIS | |
|---|
| 158 |
IGNORE_EXCEPTION_DETAIL) |
|---|
| 159 |
|
|---|
| 160 |
REPORT_UDIFF = register_optionflag('REPORT_UDIFF') |
|---|
| 161 |
REPORT_CDIFF = register_optionflag('REPORT_CDIFF') |
|---|
| 162 |
REPORT_NDIFF = register_optionflag('REPORT_NDIFF') |
|---|
| 163 |
REPORT_ONLY_FIRST_FAILURE = register_optionflag('REPORT_ONLY_FIRST_FAILURE') |
|---|
| 164 |
|
|---|
| 165 |
REPORTING_FLAGS = (REPORT_UDIFF | |
|---|
| 166 |
REPORT_CDIFF | |
|---|
| 167 |
REPORT_NDIFF | |
|---|
| 168 |
REPORT_ONLY_FIRST_FAILURE) |
|---|
| 169 |
|
|---|
| 170 |
# Special string markers for use in `want` strings: |
|---|
| 171 |
BLANKLINE_MARKER = '<BLANKLINE>' |
|---|
| 172 |
ELLIPSIS_MARKER = '...' |
|---|
| 173 |
|
|---|
| 174 |
###################################################################### |
|---|
| 175 |
## Table of Contents |
|---|
| 176 |
###################################################################### |
|---|
| 177 |
# 1. Utility Functions |
|---|
| 178 |
# 2. Example & DocTest -- store test cases |
|---|
| 179 |
# 3. DocTest Parser -- extracts examples from strings |
|---|
| 180 |
# 4. DocTest Finder -- extracts test cases from objects |
|---|
| 181 |
# 5. DocTest Runner -- runs test cases |
|---|
| 182 |
# 6. Test Functions -- convenient wrappers for testing |
|---|
| 183 |
# 7. Tester Class -- for backwards compatibility |
|---|
| 184 |
# 8. Unittest Support |
|---|
| 185 |
# 9. Debugging Support |
|---|
| 186 |
# 10. Example Usage |
|---|
| 187 |
|
|---|
| 188 |
###################################################################### |
|---|
| 189 |
## 1. Utility Functions |
|---|
| 190 |
###################################################################### |
|---|
| 191 |
|
|---|
| 192 |
def is_private(prefix, base): |
|---|
| 193 |
"""prefix, base -> true iff name prefix + "." + base is "private". |
|---|
| 194 |
|
|---|
| 195 |
Prefix may be an empty string, and base does not contain a period. |
|---|
| 196 |
Prefix is ignored (although functions you write conforming to this |
|---|
| 197 |
protocol may make use of it). |
|---|
| 198 |
Return true iff base begins with an (at least one) underscore, but |
|---|
| 199 |
does not both begin and end with (at least) two underscores. |
|---|
| 200 |
|
|---|
| 201 |
>>> is_private("a.b", "my_func") |
|---|
| 202 |
False |
|---|
| 203 |
>>> is_private("____", "_my_func") |
|---|
| 204 |
True |
|---|
| 205 |
>>> is_private("someclass", "__init__") |
|---|
| 206 |
False |
|---|
| 207 |
>>> is_private("sometypo", "__init_") |
|---|
| 208 |
True |
|---|
| 209 |
>>> is_private("x.y.z", "_") |
|---|
| 210 |
True |
|---|
| 211 |
>>> is_private("_x.y.z", "__") |
|---|
| 212 |
False |
|---|
| 213 |
>>> is_private("", "") # senseless but consistent |
|---|
| 214 |
False |
|---|
| 215 |
""" |
|---|
| 216 |
warnings.warn("is_private is deprecated; it wasn't useful; " |
|---|
| 217 |
"examine DocTestFinder.find() lists instead", |
|---|
| 218 |
DeprecationWarning, stacklevel=2) |
|---|
| 219 |
return base[:1] == "_" and not base[:2] == "__" == base[-2:] |
|---|
| 220 |
|
|---|
| 221 |
def _extract_future_flags(globs): |
|---|
| 222 |
""" |
|---|
| 223 |
Return the compiler-flags associated with the future features that |
|---|
| 224 |
have been imported into the given namespace (globs). |
|---|
| 225 |
""" |
|---|
| 226 |
flags = 0 |
|---|
| 227 |
for fname in __future__.all_feature_names: |
|---|
| 228 |
feature = globs.get(fname, None) |
|---|
| 229 |
if feature is getattr(__future__, fname): |
|---|
| 230 |
flags |= feature.compiler_flag |
|---|
| 231 |
return flags |
|---|
| 232 |
|
|---|
| 233 |
def _normalize_module(module, depth=2): |
|---|
| 234 |
""" |
|---|
| 235 |
Return the module specified by `module`. In particular: |
|---|
| 236 |
- If `module` is a module, then return module. |
|---|
| 237 |
- If `module` is a string, then import and return the |
|---|
| 238 |
module with that name. |
|---|
| 239 |
- If `module` is None, then return the calling module. |
|---|
| 240 |
The calling module is assumed to be the module of |
|---|
| 241 |
the stack frame at the given depth in the call stack. |
|---|
| 242 |
""" |
|---|
| 243 |
if inspect.ismodule(module): |
|---|
| 244 |
return module |
|---|
| 245 |
elif isinstance(module, (str, unicode)): |
|---|
| 246 |
return __import__(module, globals(), locals(), ["*"]) |
|---|
| 247 |
elif module is None: |
|---|
| 248 |
return sys.modules[sys._getframe(depth).f_globals['__name__']] |
|---|
| 249 |
else: |
|---|
| 250 |
raise TypeError("Expected a module, string, or None") |
|---|
| 251 |
|
|---|
| 252 |
def _indent(s, indent=4): |
|---|
| 253 |
""" |
|---|
| 254 |
Add the given number of space characters to the beginning every |
|---|
| 255 |
non-blank line in `s`, and return the result. |
|---|
| 256 |
""" |
|---|
| 257 |
# This regexp matches the start of non-blank lines: |
|---|
| 258 |
return re.sub('(?m)^(?!$)', indent*' ', s) |
|---|
| 259 |
|
|---|
| 260 |
def _exception_traceback(exc_info): |
|---|
| 261 |
""" |
|---|
| 262 |
Return a string containing a traceback message for the given |
|---|
| 263 |
exc_info tuple (as returned by sys.exc_info()). |
|---|
| 264 |
""" |
|---|
| 265 |
# Get a traceback message. |
|---|
| 266 |
excout = StringIO() |
|---|
| 267 |
exc_type, exc_val, exc_tb = exc_info |
|---|
| 268 |
traceback.print_exception(exc_type, exc_val, exc_tb, file=excout) |
|---|
| 269 |
return excout.getvalue() |
|---|
| 270 |
|
|---|
| 271 |
# Override some StringIO methods. |
|---|
| 272 |
class _SpoofOut(StringIO): |
|---|
| 273 |
def getvalue(self): |
|---|
| 274 |
result = StringIO.getvalue(self) |
|---|
| 275 |
# If anything at all was written, make sure there's a trailing |
|---|
| 276 |
# newline. There's no way for the expected output to indicate |
|---|
| 277 |
# that a trailing newline is missing. |
|---|
| 278 |
if result and not result.endswith("\n"): |
|---|
| 279 |
result += "\n" |
|---|
| 280 |
# Prevent softspace from screwing up the next test case, in |
|---|
| 281 |
# case they used print with a trailing comma in an example. |
|---|
| 282 |
if hasattr(self, "softspace"): |
|---|
| 283 |
del self.softspace |
|---|
| 284 |
return result |
|---|
| 285 |
|
|---|
| 286 |
def truncate(self, size=None): |
|---|
| 287 |
StringIO.truncate(self, size) |
|---|
| 288 |
if hasattr(self, "softspace"): |
|---|
| 289 |
del self.softspace |
|---|
| 290 |
|
|---|
| 291 |
# Worst-case linear-time ellipsis matching. |
|---|
| 292 |
def _ellipsis_match(want, got): |
|---|
| 293 |
""" |
|---|
| 294 |
Essentially the only subtle case: |
|---|
| 295 |
>>> _ellipsis_match('aa...aa', 'aaa') |
|---|
| 296 |
False |
|---|
| 297 |
""" |
|---|
| 298 |
if ELLIPSIS_MARKER not in want: |
|---|
| 299 |
return want == got |
|---|
| 300 |
|
|---|
| 301 |
# Find "the real" strings. |
|---|
| 302 |
ws = want.split(ELLIPSIS_MARKER) |
|---|
| 303 |
assert len(ws) >= 2 |
|---|
| 304 |
|
|---|
| 305 |
# Deal with exact matches possibly needed at one or both ends. |
|---|
| 306 |
startpos, endpos = 0, len(got) |
|---|
| 307 |
w = ws[0] |
|---|
| 308 |
if w: # starts with exact match |
|---|
| 309 |
if got.startswith(w): |
|---|
| 310 |
startpos = len(w) |
|---|
| 311 |
del ws[0] |
|---|
| 312 |
else: |
|---|
| 313 |
return False |
|---|
| 314 |
w = ws[-1] |
|---|
| 315 |
if w: # ends with exact match |
|---|
| 316 |
if got.endswith(w): |
|---|
| 317 |
endpos -= len(w) |
|---|
| 318 |
del ws[-1] |
|---|
| 319 |
else: |
|---|
| 320 |
return False |
|---|
| 321 |
|
|---|
| 322 |
if startpos > endpos: |
|---|
| 323 |
# Exact end matches required more characters than we have, as in |
|---|
| 324 |
# _ellipsis_match('aa...aa', 'aaa') |
|---|
| 325 |
return False |
|---|
| 326 |
|
|---|
| 327 |
# For the rest, we only need to find the leftmost non-overlapping |
|---|
| 328 |
# match for each piece. If there's no overall match that way alone, |
|---|
| 329 |
# there's no overall match period. |
|---|
| 330 |
for w in ws: |
|---|
| 331 |
# w may be '' at times, if there are consecutive ellipses, or |
|---|
| 332 |
# due to an ellipsis at the start or end of `want`. That's OK. |
|---|
| 333 |
# Search for an empty string succeeds, and doesn't change startpos. |
|---|
| 334 |
startpos = got.find(w, startpos, endpos) |
|---|
| 335 |
if startpos < 0: |
|---|
| 336 |
return False |
|---|
| 337 |
startpos += len(w) |
|---|
| 338 |
|
|---|
| 339 |
return True |
|---|
| 340 |
|
|---|
| 341 |
def _comment_line(line): |
|---|
| 342 |
"Return a commented form of the given line" |
|---|
| 343 |
line = line.rstrip() |
|---|
| 344 |
if line: |
|---|
| 345 |
return '# '+line |
|---|
| 346 |
else: |
|---|
| 347 |
return '#' |
|---|
| 348 |
|
|---|
| 349 |
class _OutputRedirectingPdb(pdb.Pdb): |
|---|
| 350 |
""" |
|---|
| 351 |
A specialized version of the python debugger that redirects stdout |
|---|
| 352 |
to a given stream when interacting with the user. Stdout is *not* |
|---|
| 353 |
redirected when traced code is executed. |
|---|
| 354 |
""" |
|---|
| 355 |
def __init__(self, out): |
|---|
| 356 |
self.__out = out |
|---|
| 357 |
self.__debugger_used = False |
|---|
| 358 |
pdb.Pdb.__init__(self) |
|---|
| 359 |
|
|---|
| 360 |
def set_trace(self): |
|---|
| 361 |
self.__debugger_used = True |
|---|
| 362 |
pdb.Pdb.set_trace(self) |
|---|
| 363 |
|
|---|
| 364 |
def set_continue(self): |
|---|
| 365 |
# Calling set_continue unconditionally would break unit test coverage |
|---|
| 366 |
# reporting, as Bdb.set_continue calls sys.settrace(None). |
|---|
| 367 |
if self.__debugger_used: |
|---|
| 368 |
pdb.Pdb.set_continue(self) |
|---|
| 369 |
|
|---|
| 370 |
def trace_dispatch(self, *args): |
|---|
| 371 |
# Redirect stdout to the given stream. |
|---|
| 372 |
save_stdout = sys.stdout |
|---|
| 373 |
sys.stdout = self.__out |
|---|
| 374 |
# Call Pdb's trace dispatch method. |
|---|
| 375 |
try: |
|---|
| 376 |
return pdb.Pdb.trace_dispatch(self, *args) |
|---|
| 377 |
finally: |
|---|
| 378 |
sys.stdout = save_stdout |
|---|
| 379 |
|
|---|
| 380 |
# [XX] Normalize with respect to os.path.pardir? |
|---|
| 381 |
def _module_relative_path(module, path): |
|---|
| 382 |
if not inspect.ismodule(module): |
|---|
| 383 |
raise TypeError, 'Expected a module: %r' % module |
|---|
| 384 |
if path.startswith('/'): |
|---|
| 385 |
raise ValueError, 'Module-relative files may not have absolute paths' |
|---|
| 386 |
|
|---|
| 387 |
# Find the base directory for the path. |
|---|
| 388 |
if hasattr(module, '__file__'): |
|---|
| 389 |
# A normal module/package |
|---|
| 390 |
basedir = os.path.split(module.__file__)[0] |
|---|
| 391 |
elif module.__name__ == '__main__': |
|---|
| 392 |
# An interactive session. |
|---|
| 393 |
if len(sys.argv)>0 and sys.argv[0] != '': |
|---|
| 394 |
basedir = os.path.split(sys.argv[0])[0] |
|---|
| 395 |
else: |
|---|
| 396 |
basedir = os.curdir |
|---|
| 397 |
else: |
|---|
| 398 |
# A module w/o __file__ (this includes builtins) |
|---|
| 399 |
raise ValueError("Can't resolve paths relative to the module " + |
|---|
| 400 |
module + " (it has no __file__)") |
|---|
| 401 |
|
|---|
| 402 |
# Combine the base directory and the path. |
|---|
| 403 |
return os.path.join(basedir, *(path.split('/'))) |
|---|
| 404 |
|
|---|
| 405 |
###################################################################### |
|---|
| 406 |
## 2. Example & DocTest |
|---|
| 407 |
###################################################################### |
|---|
| 408 |
## - An "example" is a <source, want> pair, where "source" is a |
|---|
| 409 |
## fragment of source code, and "want" is the expected output for |
|---|
| 410 |
## "source." The Example class also includes information about |
|---|
| 411 |
## where the example was extracted from. |
|---|
| 412 |
## |
|---|
| 413 |
## - A "doctest" is a collection of examples, typically extracted from |
|---|
| 414 |
## a string (such as an object's docstring). The DocTest class also |
|---|
| 415 |
## includes information about where the string was extracted from. |
|---|
| 416 |
|
|---|
| 417 |
class Example: |
|---|
| 418 |
""" |
|---|
| 419 |
A single doctest example, consisting of source code and expected |
|---|
| 420 |
output. `Example` defines the following attributes: |
|---|
| 421 |
|
|---|
| 422 |
- source: A single Python statement, always ending with a newline. |
|---|
| 423 |
The constructor adds a newline if needed. |
|---|
| 424 |
|
|---|
| 425 |
- want: The expected output from running the source code (either |
|---|
| 426 |
from stdout, or a traceback in case of exception). `want` ends |
|---|
| 427 |
with a newline unless it's empty, in which case it's an empty |
|---|
| 428 |
string. The constructor adds a newline if needed. |
|---|
| 429 |
|
|---|
| 430 |
- exc_msg: The exception message generated by the example, if |
|---|
| 431 |
the example is expected to generate an exception; or `None` if |
|---|
| 432 |
it is not expected to generate an exception. This exception |
|---|
| 433 |
message is compared against the return value of |
|---|
| 434 |
`traceback.format_exception_only()`. `exc_msg` ends with a |
|---|
| 435 |
newline unless it's `None`. The constructor adds a newline |
|---|
| 436 |
if needed. |
|---|
| 437 |
|
|---|
| 438 |
- lineno: The line number within the DocTest string containing |
|---|
| 439 |
this Example where the Example begins. This line number is |
|---|
| 440 |
zero-based, with respect to the beginning of the DocTest. |
|---|
| 441 |
|
|---|
| 442 |
- indent: The example's indentation in the DocTest string. |
|---|
| 443 |
I.e., the number of space characters that preceed the |
|---|
| 444 |
example's first prompt. |
|---|
| 445 |
|
|---|
| 446 |
- options: A dictionary mapping from option flags to True or |
|---|
| 447 |
False, which is used to override default options for this |
|---|
| 448 |
example. Any option flags not contained in this dictionary |
|---|
| 449 |
are left at their default value (as specified by the |
|---|
| 450 |
DocTestRunner's optionflags). By default, no options are set. |
|---|
| 451 |
""" |
|---|
| 452 |
def __init__(self, source, want, exc_msg=None, lineno=0, indent=0, |
|---|
| 453 |
options=None): |
|---|
| 454 |
# Normalize inputs. |
|---|
| 455 |
if not source.endswith('\n'): |
|---|
| 456 |
source += '\n' |
|---|
| 457 |
if want and not want.endswith('\n'): |
|---|
| 458 |
want += '\n' |
|---|
| 459 |
if exc_msg is not None and not exc_msg.endswith('\n'): |
|---|
| 460 |
exc_msg += '\n' |
|---|
| 461 |
# Store properties. |
|---|
| 462 |
self.source = source |
|---|
| 463 |
self.want = want |
|---|
| 464 |
self.lineno = lineno |
|---|
| 465 |
self.indent = indent |
|---|
| 466 |
if options is None: options = {} |
|---|
| 467 |
self.options = options |
|---|
| 468 |
self.exc_msg = exc_msg |
|---|
| 469 |
|
|---|
| 470 |
class DocTest: |
|---|
| 471 |
""" |
|---|
| 472 |
A collection of doctest examples that should be run in a single |
|---|
| 473 |
namespace. Each `DocTest` defines the following attributes: |
|---|
| 474 |
|
|---|
| 475 |
- examples: the list of examples. |
|---|
| 476 |
|
|---|
| 477 |
- globs: The namespace (aka globals) that the examples should |
|---|
| 478 |
be run in. |
|---|
| 479 |
|
|---|
| 480 |
- name: A name identifying the DocTest (typically, the name of |
|---|
| 481 |
the object whose docstring this DocTest was extracted from). |
|---|
| 482 |
|
|---|
| 483 |
- filename: The name of the file that this DocTest was extracted |
|---|
| 484 |
from, or `None` if the filename is unknown. |
|---|
| 485 |
|
|---|
| 486 |
- lineno: The line number within filename where this DocTest |
|---|
| 487 |
begins, or `None` if the line number is unavailable. This |
|---|
| 488 |
line number is zero-based, with respect to the beginning of |
|---|
| 489 |
the file. |
|---|
| 490 |
|
|---|
| 491 |
- docstring: The string that the examples were extracted from, |
|---|
| 492 |
or `None` if the string is unavailable. |
|---|
| 493 |
""" |
|---|
| 494 |
def __init__(self, examples, globs, name, filename, lineno, docstring): |
|---|
| 495 |
""" |
|---|
| 496 |
Create a new DocTest containing the given examples. The |
|---|
| 497 |
DocTest's globals are initialized with a copy of `globs`. |
|---|
| 498 |
""" |
|---|
| 499 |
assert not isinstance(examples, basestring), \ |
|---|
| 500 |
"DocTest no longer accepts str; use DocTestParser instead" |
|---|
| 501 |
self.examples = examples |
|---|
| 502 |
self.docstring = docstring |
|---|
| 503 |
self.globs = globs.copy() |
|---|
| 504 |
self.name = name |
|---|
| 505 |
self.filename = filename |
|---|
| 506 |
self.lineno = lineno |
|---|
| 507 |
|
|---|
| 508 |
def __repr__(self): |
|---|
| 509 |
if len(self.examples) == 0: |
|---|
| 510 |
examples = 'no examples' |
|---|
| 511 |
elif len(self.examples) == 1: |
|---|
| 512 |
examples = '1 example' |
|---|
| 513 |
else: |
|---|
| 514 |
examples = '%d examples' % len(self.examples) |
|---|
| 515 |
return ('<DocTest %s from %s:%s (%s)>' % |
|---|
| 516 |
(self.name, self.filename, self.lineno, examples)) |
|---|
| 517 |
|
|---|
| 518 |
|
|---|
| 519 |
# This lets us sort tests by name: |
|---|
| 520 |
def __cmp__(self, other): |
|---|
| 521 |
if not isinstance(other, DocTest): |
|---|
| 522 |
return -1 |
|---|
| 523 |
return cmp((self.name, self.filename, self.lineno, id(self)), |
|---|
| 524 |
(other.name, other.filename, other.lineno, id(other))) |
|---|
| 525 |
|
|---|
| 526 |
###################################################################### |
|---|
| 527 |
## 3. DocTestParser |
|---|
| 528 |
###################################################################### |
|---|
| 529 |
|
|---|
| 530 |
class DocTestParser: |
|---|
| 531 |
""" |
|---|
| 532 |
A class used to parse strings containing doctest examples. |
|---|
| 533 |
""" |
|---|
| 534 |
# This regular expression is used to find doctest examples in a |
|---|
| 535 |
# string. It defines three groups: `source` is the source code |
|---|
| 536 |
# (including leading indentation and prompts); `indent` is the |
|---|
| 537 |
# indentation of the first (PS1) line of the source code; and |
|---|
| 538 |
# `want` is the expected output (including leading indentation). |
|---|
| 539 |
_EXAMPLE_RE = re.compile(r''' |
|---|
| 540 |
# Source consists of a PS1 line followed by zero or more PS2 lines. |
|---|
| 541 |
(?P<source> |
|---|
| 542 |
(?:^(?P<indent> [ ]*) >>> .*) # PS1 line |
|---|
| 543 |
(?:\n [ ]* \.\.\. .*)*) # PS2 lines |
|---|
| 544 |
\n? |
|---|
| 545 |
# Want consists of any non-blank lines that do not start with PS1. |
|---|
| 546 |
(?P<want> (?:(?![ ]*$) # Not a blank line |
|---|
| 547 |
(?![ ]*>>>) # Not a line starting with PS1 |
|---|
| 548 |
.*$\n? # But any other line |
|---|
| 549 |
)*) |
|---|
| 550 |
''', re.MULTILINE | re.VERBOSE) |
|---|
| 551 |
|
|---|
| 552 |
# A regular expression for handling `want` strings that contain |
|---|
| 553 |
# expected exceptions. It divides `want` into three pieces: |
|---|
| 554 |
# - the traceback header line (`hdr`) |
|---|
| 555 |
# - the traceback stack (`stack`) |
|---|
| 556 |
# - the exception message (`msg`), as generated by |
|---|
| 557 |
# traceback.format_exception_only() |
|---|
| 558 |
# `msg` may have multiple lines. We assume/require that the |
|---|
| 559 |
# exception message is the first non-indented line starting with a word |
|---|
| 560 |
# character following the traceback header line. |
|---|
| 561 |
_EXCEPTION_RE = re.compile(r""" |
|---|
| 562 |
# Grab the traceback header. Different versions of Python have |
|---|
| 563 |
# said different things on the first traceback line. |
|---|
| 564 |
^(?P<hdr> Traceback\ \( |
|---|
| 565 |
(?: most\ recent\ call\ last |
|---|
| 566 |
| innermost\ last |
|---|
| 567 |
) \) : |
|---|
| 568 |
) |
|---|
| 569 |
\s* $ # toss trailing whitespace on the header. |
|---|
| 570 |
(?P<stack> .*?) # don't blink: absorb stuff until... |
|---|
| 571 |
^ (?P<msg> \w+ .*) # a line *starts* with alphanum. |
|---|
| 572 |
""", re.VERBOSE | re.MULTILINE | re.DOTALL) |
|---|
| 573 |
|
|---|
| 574 |
# A callable returning a true value iff its argument is a blank line |
|---|
| 575 |
# or contains a single comment. |
|---|
| 576 |
_IS_BLANK_OR_COMMENT = re.compile(r'^[ ]*(#.*)?$').match |
|---|
| 577 |
|
|---|
| 578 |
def parse(self, string, name='<string>'): |
|---|
| 579 |
""" |
|---|
| 580 |
Divide the given string into examples and intervening text, |
|---|
| 581 |
and return them as a list of alternating Examples and strings. |
|---|
| 582 |
Line numbers for the Examples are 0-based. The optional |
|---|
| 583 |
argument `name` is a name identifying this string, and is only |
|---|
| 584 |
used for error messages. |
|---|
| 585 |
""" |
|---|
| 586 |
string = string.expandtabs() |
|---|
| 587 |
# If all lines begin with the same indentation, then strip it. |
|---|
| 588 |
min_indent = self._min_indent(string) |
|---|
| 589 |
if min_indent > 0: |
|---|
| 590 |
string = '\n'.join([l[min_indent:] for l in string.split('\n')]) |
|---|
| 591 |
|
|---|
| 592 |
output = [] |
|---|
| 593 |
charno, lineno = 0, 0 |
|---|
| 594 |
# Find all doctest examples in the string: |
|---|
| 595 |
for m in self._EXAMPLE_RE.finditer(string): |
|---|
| 596 |
# Add the pre-example text to `output`. |
|---|
| 597 |
output.append(string[charno:m.start()]) |
|---|
| 598 |
# Update lineno (lines before this example) |
|---|
| 599 |
lineno += string.count('\n', charno, m.start()) |
|---|
| 600 |
# Extract info from the regexp match. |
|---|
| 601 |
(source, options, want, exc_msg) = \ |
|---|
| 602 |
self._parse_example(m, name, lineno) |
|---|
| 603 |
# Create an Example, and add it to the list. |
|---|
| 604 |
if not self._IS_BLANK_OR_COMMENT(source): |
|---|
| 605 |
output.append( Example(source, want, exc_msg, |
|---|
| 606 |
lineno=lineno, |
|---|
| 607 |
indent=min_indent+len(m.group('indent')), |
|---|
| 608 |
options=options) ) |
|---|
| 609 |
# Update lineno (lines inside this example) |
|---|
| 610 |
lineno += string.count('\n', m.start(), m.end()) |
|---|
| 611 |
# Update charno. |
|---|
| 612 |
charno = m.end() |
|---|
| 613 |
# Add any remaining post-example text to `output`. |
|---|
| 614 |
output.append(string[charno:]) |
|---|
| 615 |
return output |
|---|
| 616 |
|
|---|
| 617 |
def get_doctest(self, string, globs, name, filename, lineno): |
|---|
| 618 |
""" |
|---|
| 619 |
Extract all doctest examples from the given string, and |
|---|
| 620 |
collect them into a `DocTest` object. |
|---|
| 621 |
|
|---|
| 622 |
`globs`, `name`, `filename`, and `lineno` are attributes for |
|---|
| 623 |
the new `DocTest` object. See the documentation for `DocTest` |
|---|
| 624 |
for more information. |
|---|
| 625 |
""" |
|---|
| 626 |
return DocTest(self.get_examples(string, name), globs, |
|---|
| 627 |
name, filename, lineno, string) |
|---|
| 628 |
|
|---|
| 629 |
def get_examples(self, string, name='<string>'): |
|---|
| 630 |
""" |
|---|
| 631 |
Extract all doctest examples from the given string, and return |
|---|
| 632 |
them as a list of `Example` objects. Line numbers are |
|---|
| 633 |
0-based, because it's most common in doctests that nothing |
|---|
| 634 |
interesting appears on the same line as opening triple-quote, |
|---|
| 635 |
and so the first interesting line is called \"line 1\" then. |
|---|
| 636 |
|
|---|
| 637 |
The optional argument `name` is a name identifying this |
|---|
| 638 |
string, and is only used for error messages. |
|---|
| 639 |
""" |
|---|
| 640 |
return [x for x in self.parse(string, name) |
|---|
| 641 |
if isinstance(x, Example)] |
|---|
| 642 |
|
|---|
| 643 |
def _parse_example(self, m, name, lineno): |
|---|
| 644 |
""" |
|---|
| 645 |
Given a regular expression match from `_EXAMPLE_RE` (`m`), |
|---|
| 646 |
return a pair `(source, want)`, where `source` is the matched |
|---|
| 647 |
example's source code (with prompts and indentation stripped); |
|---|
| 648 |
and `want` is the example's expected output (with indentation |
|---|
| 649 |
stripped). |
|---|
| 650 |
|
|---|
| 651 |
`name` is the string's name, and `lineno` is the line number |
|---|
| 652 |
where the example starts; both are used for error messages. |
|---|
| 653 |
""" |
|---|
| 654 |
# Get the example's indentation level. |
|---|
| 655 |
indent = len(m.group('indent')) |
|---|
| 656 |
|
|---|
| 657 |
|---|