[Python-checkins] CVS: python/dist/src/Lib doctest.py,1.17,1.18
Tim Peters
tim_one@users.sourceforge.net
Mon, 01 Oct 2001 20:53:43 -0700
Update of /cvsroot/python/python/dist/src/Lib
In directory usw-pr-cvs1:/tmp/cvs-serv5055/python/Lib
Modified Files:
doctest.py
Log Message:
SF patch [#466616] Exclude imported items from doctest,
from Tim Hochberg. Also mucho fiddling to change the way doctest
determines whether a thing is a function, module or class. Under 2.2,
this really requires the functions in inspect.py (e.g., types.ClassType
is close to meaningless now, if not outright misleading).
Index: doctest.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/doctest.py,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -d -r1.17 -r1.18
*** doctest.py 2001/08/18 00:05:50 1.17
--- doctest.py 2001/10/02 03:53:41 1.18
***************
*** 49,56 ****
+ f.__doc__ for all functions f in M.__dict__.values(), except those
! with private names.
+ C.__doc__ for all classes C in M.__dict__.values(), except those with
! private names.
+ If M.__test__ exists and "is true", it must be a dict, and
--- 49,56 ----
+ f.__doc__ for all functions f in M.__dict__.values(), except those
! with private names and those defined in other modules.
+ C.__doc__ for all classes C in M.__dict__.values(), except those with
! private names and those defined in other modules.
+ If M.__test__ exists and "is true", it must be a dict, and
***************
*** 76,101 ****
of a Tester instance).
- Warning: imports can cause trouble; e.g., if you do
-
- from XYZ import XYZclass
-
- then XYZclass is a name in M.__dict__ too, and doctest has no way to know
- that XYZclass wasn't *defined* in M. So it may try to execute the examples
- in XYZclass's docstring, and those in turn may require a different set of
- globals to work correctly. I prefer to do "import *"- friendly imports,
- a la
-
- import XYY
- _XYZclass = XYZ.XYZclass
- del XYZ
-
- or (Python 2.0)
-
- from XYZ import XYZclass as _XYZclass
-
- and then the leading underscore stops testmod from going nuts. You may
- prefer the method in the next section.
-
-
WHAT'S THE EXECUTION CONTEXT?
--- 76,79 ----
***************
*** 304,314 ****
import __future__
- import types
- _FunctionType = types.FunctionType
- _ClassType = types.ClassType
- _ModuleType = types.ModuleType
- _StringType = types.StringType
- del types
-
import re
PS1 = ">>>"
--- 282,285 ----
***************
*** 320,323 ****
--- 291,300 ----
del re
+ from types import StringTypes as _StringTypes
+
+ from inspect import isclass as _isclass
+ from inspect import isfunction as _isfunction
+ from inspect import ismodule as _ismodule
+
# Extract interactive examples from a string. Return a list of triples,
# (source, outcome, lineno). "source" is the source code, and ends
***************
*** 575,578 ****
--- 552,564 ----
return base[:1] == "_" and not base[:2] == "__" == base[-2:]
+ # Determine if a class of function was defined in the given module.
+
+ def _from_module(module, object):
+ if _isfunction(object):
+ return module.__dict__ is object.func_globals
+ if _isclass(object):
+ return module.__name__ == object.__module__
+ raise ValueError("object must be a class or function")
+
class Tester:
"""Class Tester -- runs docstring examples and accumulates stats.
***************
*** 591,597 ****
object.__name__) for logging. Return (#failures, #tries).
! rundict(d, name)
Search for examples in docstrings in all of d.values(); use name
! for logging. Return (#failures, #tries).
run__test__(d, name)
--- 577,584 ----
object.__name__) for logging. Return (#failures, #tries).
! rundict(d, name, module=None)
Search for examples in docstrings in all of d.values(); use name
! for logging. Exclude functions and classes not defined in module
! if specified. Return (#failures, #tries).
run__test__(d, name)
***************
*** 665,669 ****
if mod is None and globs is None:
raise TypeError("Tester.__init__: must specify mod or globs")
! if mod is not None and type(mod) is not _ModuleType:
raise TypeError("Tester.__init__: mod must be a module; " +
`mod`)
--- 652,656 ----
if mod is None and globs is None:
raise TypeError("Tester.__init__: must specify mod or globs")
! if mod is not None and not _ismodule(mod):
raise TypeError("Tester.__init__: mod must be a module; " +
`mod`)
***************
*** 760,764 ****
print f, "of", t, "examples failed in", name + ".__doc__"
self.__record_outcome(name, f, t)
! if type(object) is _ClassType:
f2, t2 = self.rundict(object.__dict__, name)
f = f + f2
--- 747,751 ----
print f, "of", t, "examples failed in", name + ".__doc__"
self.__record_outcome(name, f, t)
! if _isclass(object):
f2, t2 = self.rundict(object.__dict__, name)
f = f + f2
***************
*** 766,792 ****
return f, t
! def rundict(self, d, name):
"""
! d. name -> search for docstring examples in all of d.values().
For k, v in d.items() such that v is a function or class,
do self.rundoc(v, name + "." + k). Whether this includes
objects with private names depends on the constructor's
! "isprivate" argument.
Return aggregate (#failures, #examples).
! >>> def _f():
! ... '''>>> assert 1 == 1
! ... '''
! >>> def g():
... '''>>> assert 2 != 1
... '''
! >>> d = {"_f": _f, "g": g}
>>> t = Tester(globs={}, verbose=0)
! >>> t.rundict(d, "rundict_test") # _f is skipped
! (0, 1)
>>> t = Tester(globs={}, verbose=0, isprivate=lambda x,y: 0)
! >>> t.rundict(d, "rundict_test_pvt") # both are searched
! (0, 2)
"""
--- 753,809 ----
return f, t
! def rundict(self, d, name, module=None):
"""
! d, name, module=None -> search for docstring examples in d.values().
For k, v in d.items() such that v is a function or class,
do self.rundoc(v, name + "." + k). Whether this includes
objects with private names depends on the constructor's
! "isprivate" argument. If module is specified, functions and
! classes that are not defined in module are excluded.
Return aggregate (#failures, #examples).
! Build and populate two modules with sample functions to test that
! exclusion of external functions and classes works.
!
! >>> import new
! >>> m1 = new.module('_m1')
! >>> m2 = new.module('_m2')
! >>> test_data = \"""
! ... def f():
! ... '''>>> assert 1 == 1
! ... '''
! ... def g():
... '''>>> assert 2 != 1
... '''
! ... class H:
! ... '''>>> assert 2 > 1
! ... '''
! ... def bar(self):
! ... '''>>> assert 1 < 2
! ... '''
! ... \"""
! >>> exec test_data in m1.__dict__
! >>> exec test_data in m2.__dict__
!
! Tests that objects outside m1 are excluded:
!
! >>> d = {"_f": m1.f, "g": m1.g, "h": m1.H,
! ... "f2": m2.f, "g2": m2.g, "h2": m2.H}
>>> t = Tester(globs={}, verbose=0)
! >>> t.rundict(d, "rundict_test", m1) # _f, f2 and g2 and h2 skipped
! (0, 3)
!
! Again, but with a custom isprivate function allowing _f:
!
>>> t = Tester(globs={}, verbose=0, isprivate=lambda x,y: 0)
! >>> t.rundict(d, "rundict_test_pvt", m1) # Only f2, g2 and h2 skipped
! (0, 4)
!
! And once more, not excluding stuff outside m1:
!
! >>> t = Tester(globs={}, verbose=0, isprivate=lambda x,y: 0)
! >>> t.rundict(d, "rundict_test_pvt") # None are skipped.
! (0, 8)
"""
***************
*** 801,805 ****
for thisname in names:
value = d[thisname]
! if type(value) in (_FunctionType, _ClassType):
f2, t2 = self.__runone(value, name + "." + thisname)
f = f + f2
--- 818,824 ----
for thisname in names:
value = d[thisname]
! if _isfunction(value) or _isclass(value):
! if module and not _from_module(module, value):
! continue
f2, t2 = self.__runone(value, name + "." + thisname)
f = f + f2
***************
*** 826,832 ****
v = d[k]
thisname = prefix + k
! if type(v) is _StringType:
f, t = self.runstring(v, thisname)
! elif type(v) in (_FunctionType, _ClassType):
f, t = self.rundoc(v, thisname)
else:
--- 845,851 ----
v = d[k]
thisname = prefix + k
! if type(v) in _StringTypes:
f, t = self.runstring(v, thisname)
! elif _isfunction(v) or _isclass(v):
f, t = self.rundoc(v, thisname)
else:
***************
*** 1013,1017 ****
global master
! if type(m) is not _ModuleType:
raise TypeError("testmod: module required; " + `m`)
if name is None:
--- 1032,1036 ----
global master
! if not _ismodule(m):
raise TypeError("testmod: module required; " + `m`)
if name is None: