@@ -200,6 +200,7 @@ def _test():
200200 'DebugRunner' ,
201201 # 6. Test Functions
202202 'testmod' ,
203+ 'testfile' ,
203204 'run_docstring_examples' ,
204205 # 7. Tester
205206 'Tester' ,
@@ -478,6 +479,30 @@ def trace_dispatch(self, *args):
478479 # Restore stdout.
479480 sys .stdout = save_stdout
480481
482+ def _module_relative_path (module , path ):
483+ if not inspect .ismodule (module ):
484+ raise TypeError , 'Expected a module: %r' % module
485+ if path .startswith ('/' ):
486+ raise ValueError , 'Module-relative files may not have absolute paths'
487+
488+ # Find the base directory for the path.
489+ if hasattr (module , '__file__' ):
490+ # A normal module/package
491+ basedir = os .path .split (module .__file__ )[0 ]
492+ elif module .__name__ == '__main__' :
493+ # An interactive session.
494+ if len (sys .argv )> 0 and sys .argv [0 ] != '' :
495+ basedir = os .path .split (sys .argv [0 ])[0 ]
496+ else :
497+ basedir = os .curdir
498+ else :
499+ # A module w/o __file__ (this includes builtins)
500+ raise ValueError ("Can't resolve paths relative to the module " +
501+ module + " (it has no __file__)" )
502+
503+ # Combine the base directory and the path.
504+ return os .path .join (basedir , * (path .split ('/' )))
505+
481506######################################################################
482507## 2. Example & DocTest
483508######################################################################
@@ -1881,6 +1906,7 @@ def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
18811906 DONT_ACCEPT_BLANKLINE
18821907 NORMALIZE_WHITESPACE
18831908 ELLIPSIS
1909+ IGNORE_EXCEPTION_DETAIL
18841910 REPORT_UDIFF
18851911 REPORT_CDIFF
18861912 REPORT_NDIFF
@@ -1896,9 +1922,7 @@ def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
18961922 treat all functions as public. Optionally, "isprivate" can be
18971923 set to doctest.is_private to skip over functions marked as private
18981924 using the underscore naming convention; see its docs for details.
1899- """
19001925
1901- """ [XX] This is no longer true:
19021926 Advanced tomfoolery: testmod runs methods of a local instance of
19031927 class doctest.Tester, then merges the results into (or creates)
19041928 global Tester instance doctest.master. Methods of doctest.master
@@ -1950,6 +1974,121 @@ class doctest.Tester, then merges the results into (or creates)
19501974
19511975 return runner .failures , runner .tries
19521976
1977+ def testfile (filename , module_relative = True , name = None , package = None ,
1978+ globs = None , verbose = None , report = True , optionflags = 0 ,
1979+ extraglobs = None , raise_on_error = False ):
1980+ """
1981+ Test examples in the given file. Return (#failures, #tests).
1982+
1983+ Optional keyword arg "module_relative" specifies how filenames
1984+ should be interpreted:
1985+
1986+ - If "module_relative" is True (the default), then "filename"
1987+ specifies a module-relative path. By default, this path is
1988+ relative to the calling module's directory; but if the
1989+ "package" argument is specified, then it is relative to that
1990+ package. To ensure os-independence, "filename" should use
1991+ "/" characters to separate path segments, and should not
1992+ be an absolute path (i.e., it may not begin with "/").
1993+
1994+ - If "module_relative" is False, then "filename" specifies an
1995+ os-specific path. The path may be absolute or relative (to
1996+ the current working directory).
1997+
1998+ Optional keyword arg "name" gives the name of the file; by default
1999+ use the file's name.
2000+
2001+ Optional keyword argument "package" is a Python package or the
2002+ name of a Python package whose directory should be used as the
2003+ base directory for a module relative filename. If no package is
2004+ specified, then the calling module's directory is used as the base
2005+ directory for module relative filenames. It is an error to
2006+ specify "package" if "module_relative" is False.
2007+
2008+ Optional keyword arg "globs" gives a dict to be used as the globals
2009+ when executing examples; by default, use {}. A copy of this dict
2010+ is actually used for each docstring, so that each docstring's
2011+ examples start with a clean slate.
2012+
2013+ Optional keyword arg "extraglobs" gives a dictionary that should be
2014+ merged into the globals that are used to execute examples. By
2015+ default, no extra globals are used.
2016+
2017+ Optional keyword arg "verbose" prints lots of stuff if true, prints
2018+ only failures if false; by default, it's true iff "-v" is in sys.argv.
2019+
2020+ Optional keyword arg "report" prints a summary at the end when true,
2021+ else prints nothing at the end. In verbose mode, the summary is
2022+ detailed, else very brief (in fact, empty if all tests passed).
2023+
2024+ Optional keyword arg "optionflags" or's together module constants,
2025+ and defaults to 0. Possible values (see the docs for details):
2026+
2027+ DONT_ACCEPT_TRUE_FOR_1
2028+ DONT_ACCEPT_BLANKLINE
2029+ NORMALIZE_WHITESPACE
2030+ ELLIPSIS
2031+ IGNORE_EXCEPTION_DETAIL
2032+ REPORT_UDIFF
2033+ REPORT_CDIFF
2034+ REPORT_NDIFF
2035+ REPORT_ONLY_FIRST_FAILURE
2036+
2037+ Optional keyword arg "raise_on_error" raises an exception on the
2038+ first unexpected exception or failure. This allows failures to be
2039+ post-mortem debugged.
2040+
2041+ Advanced tomfoolery: testmod runs methods of a local instance of
2042+ class doctest.Tester, then merges the results into (or creates)
2043+ global Tester instance doctest.master. Methods of doctest.master
2044+ can be called directly too, if you want to do something unusual.
2045+ Passing report=0 to testmod is especially useful then, to delay
2046+ displaying a summary. Invoke doctest.master.summarize(verbose)
2047+ when you're done fiddling.
2048+ """
2049+ global master
2050+
2051+ if package and not module_relative :
2052+ raise ValueError ("Package may only be specified for module-"
2053+ "relative paths." )
2054+
2055+ # Relativize the path
2056+ if module_relative :
2057+ package = _normalize_module (package )
2058+ filename = _module_relative_path (package , filename )
2059+
2060+ # If no name was given, then use the file's name.
2061+ if name is None :
2062+ name = os .path .split (filename )[- 1 ]
2063+
2064+ # Assemble the globals.
2065+ if globs is None :
2066+ globs = {}
2067+ else :
2068+ globs = globs .copy ()
2069+ if extraglobs is not None :
2070+ globs .update (extraglobs )
2071+
2072+ if raise_on_error :
2073+ runner = DebugRunner (verbose = verbose , optionflags = optionflags )
2074+ else :
2075+ runner = DocTestRunner (verbose = verbose , optionflags = optionflags )
2076+
2077+ # Read the file, convert it to a test, and run it.
2078+ s = open (filename ).read ()
2079+ test = DocTestParser ().get_doctest (s , globs , name , filename , 0 )
2080+ runner .run (test )
2081+
2082+ if report :
2083+ runner .summarize ()
2084+
2085+ if master is None :
2086+ master = runner
2087+ else :
2088+ master .merge (runner )
2089+
2090+ return runner .failures , runner .tries
2091+
19532092def run_docstring_examples (f , globs , verbose = False , name = "NoName" ,
19542093 compileflags = None , optionflags = 0 ):
19552094 """
@@ -2311,52 +2450,59 @@ def format_failure(self, err):
23112450 % (self ._dt_test .name , self ._dt_test .filename , err )
23122451 )
23132452
2314- def DocFileTest (path , package = None , globs = None , ** options ):
2315- name = path .split ('/' )[- 1 ]
2453+ def DocFileTest (path , module_relative = True , package = None ,
2454+ globs = None , ** options ):
2455+ if globs is None :
2456+ globs = {}
23162457
2317- # Interpret relative paths as relative to the given package's
2318- # directory (or the current module, if no package is specified).
2319- if not os .path .isabs (path ):
2458+ if package and not module_relative :
2459+ raise ValueError ("Package may only be specified for module-"
2460+ "relative paths." )
2461+
2462+ # Relativize the path.
2463+ if module_relative :
23202464 package = _normalize_module (package )
2321- if hasattr (package , '__file__' ):
2322- # A normal package/module.
2323- dir = os .path .split (package .__file__ )[0 ]
2324- path = os .path .join (dir , * (path .split ('/' )))
2325- elif package .__name__ == '__main__' :
2326- # An interactive session.
2327- if sys .argv [0 ] != '' :
2328- dir = os .path .split (sys .argv [0 ])[0 ]
2329- path = os .path .join (dir , * (path .split ('/' )))
2330- else :
2331- # A module w/o __file__ (this includes builtins)
2332- raise ValueError ("Can't resolve paths relative to " +
2333- "the module %s (it has" % package +
2334- "no __file__)" )
2465+ path = _module_relative_path (package , path )
23352466
2336- doc = open (path ).read ()
2467+ # Find the file and read it.
2468+ name = os .path .split (path )[- 1 ]
23372469
2338- if globs is None :
2339- globs = {}
2470+ doc = open (path ).read ()
23402471
2472+ # Convert it to a test, and wrap it in a DocFileCase.
23412473 test = DocTestParser ().get_doctest (doc , globs , name , path , 0 )
2342-
23432474 return DocFileCase (test , ** options )
23442475
23452476def DocFileSuite (* paths , ** kw ):
2346- """Creates a suite of doctest files.
2347-
2348- One or more text file paths are given as strings. These should
2349- use "/" characters to separate path segments. Paths are relative
2350- to the directory of the calling module, or relative to the package
2351- passed as a keyword argument.
2477+ """A unittest suite for one or more doctest files.
2478+
2479+ The path to each doctest file is given as a string; the
2480+ interpretation of that string depends on the keyword argument
2481+ "module_relative".
23522482
23532483 A number of options may be provided as keyword arguments:
23542484
2485+ module_relative
2486+ If "module_relative" is True, then the given file paths are
2487+ interpreted as os-independent module-relative paths. By
2488+ default, these paths are relative to the calling module's
2489+ directory; but if the "package" argument is specified, then
2490+ they are relative to that package. To ensure os-independence,
2491+ "filename" should use "/" characters to separate path
2492+ segments, and may not be an absolute path (i.e., it may not
2493+ begin with "/").
2494+
2495+ If "module_relative" is False, then the given file paths are
2496+ interpreted as os-specific paths. These paths may be absolute
2497+ or relative (to the current working directory).
2498+
23552499 package
2356- The name of a Python package. Text-file paths will be
2357- interpreted relative to the directory containing this package.
2358- The package may be supplied as a package object or as a dotted
2359- package name.
2500+ A Python package or the name of a Python package whose directory
2501+ should be used as the base directory for module relative paths.
2502+ If "package" is not specified, then the calling module's
2503+ directory is used as the base directory for module relative
2504+ filenames. It is an error to specify "package" if
2505+ "module_relative" is False.
23602506
23612507 setUp
23622508 The name of a set-up function. This is called before running the
@@ -2375,14 +2521,14 @@ def DocFileSuite(*paths, **kw):
23752521
23762522 optionflags
23772523 A set of doctest option flags expressed as an integer.
2378-
23792524 """
23802525 suite = unittest .TestSuite ()
23812526
23822527 # We do this here so that _normalize_module is called at the right
23832528 # level. If it were called in DocFileTest, then this function
23842529 # would be the caller and we might guess the package incorrectly.
2385- kw ['package' ] = _normalize_module (kw .get ('package' ))
2530+ if kw .get ('module_relative' , True ):
2531+ kw ['package' ] = _normalize_module (kw .get ('package' ))
23862532
23872533 for path in paths :
23882534 suite .addTest (DocFileTest (path , ** kw ))
0 commit comments