From bf0400abe91ff2bbe3061d596441f082ee4f10eb Mon Sep 17 00:00:00 2001
From: Tim Peters <tim.peters@gmail.com>
Date: Mon, 5 Jun 2006 01:43:03 +0000
Subject: Remove doctest.testmod's deprecated (in 2.4) `isprivate` argument.  A
 lot of hair went into supporting that!

---
 Doc/lib/libdoctest.tex   | 15 +++------
 Lib/doctest.py           | 85 +++++-------------------------------------------
 Lib/test/test_doctest.py | 57 +++++---------------------------
 Misc/NEWS                |  3 ++
 4 files changed, 26 insertions(+), 134 deletions(-)

diff --git a/Doc/lib/libdoctest.tex b/Doc/lib/libdoctest.tex
index f9a97fa..957ecf4 100644
--- a/Doc/lib/libdoctest.tex
+++ b/Doc/lib/libdoctest.tex
@@ -952,7 +952,7 @@ sections \ref{doctest-simple-testmod} and
 
 \begin{funcdesc}{testmod}{\optional{m}\optional{, name}\optional{,
                           globs}\optional{, verbose}\optional{,
-                          isprivate}\optional{, report}\optional{,
+                          report}\optional{,
                           optionflags}\optional{, extraglobs}\optional{,
                           raise_on_error}\optional{, exclude_empty}}
 
@@ -990,19 +990,14 @@ sections \ref{doctest-simple-testmod} and
   for function \function{testfile()} above, except that \var{globs}
   defaults to \code{\var{m}.__dict__}.
 
-  Optional argument \var{isprivate} specifies a function used to
-  determine whether a name is private.  The default function treats
-  all names as public.  \var{isprivate} can be set to
-  \code{doctest.is_private} to skip over names that are
-  private according to Python's underscore naming convention.
-  \deprecated{2.4}{\var{isprivate} was a stupid idea -- don't use it.
-  If you need to skip tests based on name, filter the list returned by
-  \code{DocTestFinder.find()} instead.}
-
   \versionchanged[The parameter \var{optionflags} was added]{2.3}
 
   \versionchanged[The parameters \var{extraglobs}, \var{raise_on_error}
                   and \var{exclude_empty} were added]{2.4}
+
+  \versionchanged[The optional argument \var{isprivate}, deprecated
+                  in 2.4, was removed]{2.5}
+
 \end{funcdesc}
 
 There's also a function to run the doctests associated with a single object.
diff --git a/Lib/doctest.py b/Lib/doctest.py
index d549163..47b3aae 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -63,7 +63,6 @@ __all__ = [
     'REPORT_ONLY_FIRST_FAILURE',
     'REPORTING_FLAGS',
     # 1. Utility Functions
-    'is_private',
     # 2. Example & DocTest
     'Example',
     'DocTest',
@@ -101,11 +100,6 @@ import unittest, difflib, pdb, tempfile
 import warnings
 from StringIO import StringIO
 
-# Don't whine about the deprecated is_private function in this
-# module's tests.
-warnings.filterwarnings("ignore", "is_private", DeprecationWarning,
-                        __name__, 0)
-
 # There are 4 basic classes:
 #  - Example: a <source, want> pair, plus an intra-docstring line number.
 #  - DocTest: a collection of examples, parsed from a docstring, plus
@@ -178,35 +172,6 @@ ELLIPSIS_MARKER = '...'
 ## 1. Utility Functions
 ######################################################################
 
-def is_private(prefix, base):
-    """prefix, base -> true iff name prefix + "." + base is "private".
-
-    Prefix may be an empty string, and base does not contain a period.
-    Prefix is ignored (although functions you write conforming to this
-    protocol may make use of it).
-    Return true iff base begins with an (at least one) underscore, but
-    does not both begin and end with (at least) two underscores.
-
-    >>> is_private("a.b", "my_func")
-    False
-    >>> is_private("____", "_my_func")
-    True
-    >>> is_private("someclass", "__init__")
-    False
-    >>> is_private("sometypo", "__init_")
-    True
-    >>> is_private("x.y.z", "_")
-    True
-    >>> is_private("_x.y.z", "__")
-    False
-    >>> is_private("", "")  # senseless but consistent
-    False
-    """
-    warnings.warn("is_private is deprecated; it wasn't useful; "
-                  "examine DocTestFinder.find() lists instead",
-                  DeprecationWarning, stacklevel=2)
-    return base[:1] == "_" and not base[:2] == "__" == base[-2:]
-
 def _extract_future_flags(globs):
     """
     Return the compiler-flags associated with the future features that
@@ -759,7 +724,7 @@ class DocTestFinder:
     """
 
     def __init__(self, verbose=False, parser=DocTestParser(),
-                 recurse=True, _namefilter=None, exclude_empty=True):
+                 recurse=True, exclude_empty=True):
         """
         Create a new doctest finder.
 
@@ -779,12 +744,8 @@ class DocTestFinder:
         self._verbose = verbose
         self._recurse = recurse
         self._exclude_empty = exclude_empty
-        # _namefilter is undocumented, and exists only for temporary backward-
-        # compatibility support of testmod's deprecated isprivate mess.
-        self._namefilter = _namefilter
 
-    def find(self, obj, name=None, module=None, globs=None,
-             extraglobs=None):
+    def find(self, obj, name=None, module=None, globs=None, extraglobs=None):
         """
         Return a list of the DocTests that are defined by the given
         object's docstring, or by any of its contained objects'
@@ -862,13 +823,6 @@ class DocTestFinder:
         self._find(tests, obj, name, module, source_lines, globs, {})
         return tests
 
-    def _filter(self, obj, prefix, base):
-        """
-        Return true if the given object should not be examined.
-        """
-        return (self._namefilter is not None and
-                self._namefilter(prefix, base))
-
     def _from_module(self, module, object):
         """
         Return true if the given object is defined in the given
@@ -910,9 +864,6 @@ class DocTestFinder:
         # Look for tests in a module's contained objects.
         if inspect.ismodule(obj) and self._recurse:
             for valname, val in obj.__dict__.items():
-                # Check if this contained object should be ignored.
-                if self._filter(val, name, valname):
-                    continue
                 valname = '%s.%s' % (name, valname)
                 # Recurse to functions & classes.
                 if ((inspect.isfunction(val) or inspect.isclass(val)) and
@@ -941,9 +892,6 @@ class DocTestFinder:
         # Look for tests in a class's contained objects.
         if inspect.isclass(obj) and self._recurse:
             for valname, val in obj.__dict__.items():
-                # Check if this contained object should be ignored.
-                if self._filter(val, name, valname):
-                    continue
                 # Special handling for staticmethod/classmethod.
                 if isinstance(val, staticmethod):
                     val = getattr(obj, valname)
@@ -1751,17 +1699,16 @@ class DebugRunner(DocTestRunner):
 # class, updated by testmod.
 master = None
 
-def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
+def testmod(m=None, name=None, globs=None, verbose=None,
             report=True, optionflags=0, extraglobs=None,
             raise_on_error=False, exclude_empty=False):
-    """m=None, name=None, globs=None, verbose=None, isprivate=None,
-       report=True, optionflags=0, extraglobs=None, raise_on_error=False,
+    """m=None, name=None, globs=None, verbose=None, report=True,
+       optionflags=0, extraglobs=None, raise_on_error=False,
        exclude_empty=False
 
     Test examples in docstrings in functions and classes reachable
     from module m (or the current module if m is not supplied), starting
-    with m.__doc__.  Unless isprivate is specified, private names
-    are not skipped.
+    with m.__doc__.
 
     Also test examples reachable from dict m.__test__ if it exists and is
     not None.  m.__test__ maps names to functions, classes and strings;
@@ -1810,13 +1757,6 @@ def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
     first unexpected exception or failure. This allows failures to be
     post-mortem debugged.
 
-    Deprecated in Python 2.4:
-    Optional keyword arg "isprivate" specifies a function used to
-    determine whether a name is private.  The default function is
-    treat all functions as public.  Optionally, "isprivate" can be
-    set to doctest.is_private to skip over functions marked as private
-    using the underscore naming convention; see its docs for details.
-
     Advanced tomfoolery:  testmod runs methods of a local instance of
     class doctest.Tester, then merges the results into (or creates)
     global Tester instance doctest.master.  Methods of doctest.master
@@ -1827,11 +1767,6 @@ def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
     """
     global master
 
-    if isprivate is not None:
-        warnings.warn("the isprivate argument is deprecated; "
-                      "examine DocTestFinder.find() lists instead",
-                      DeprecationWarning)
-
     # If no module was given, then use __main__.
     if m is None:
         # DWA - m will still be None if this wasn't invoked from the command
@@ -1848,7 +1783,7 @@ def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
         name = m.__name__
 
     # Find, parse, and run all tests in the given module.
-    finder = DocTestFinder(_namefilter=isprivate, exclude_empty=exclude_empty)
+    finder = DocTestFinder(exclude_empty=exclude_empty)
 
     if raise_on_error:
         runner = DebugRunner(verbose=verbose, optionflags=optionflags)
@@ -2021,8 +1956,7 @@ def run_docstring_examples(f, globs, verbose=False, name="NoName",
 # actually used in any way.
 
 class Tester:
-    def __init__(self, mod=None, globs=None, verbose=None,
-                 isprivate=None, optionflags=0):
+    def __init__(self, mod=None, globs=None, verbose=None, optionflags=0):
 
         warnings.warn("class Tester is deprecated; "
                       "use class doctest.DocTestRunner instead",
@@ -2037,9 +1971,8 @@ class Tester:
         self.globs = globs
 
         self.verbose = verbose
-        self.isprivate = isprivate
         self.optionflags = optionflags
-        self.testfinder = DocTestFinder(_namefilter=isprivate)
+        self.testfinder = DocTestFinder()
         self.testrunner = DocTestRunner(verbose=verbose,
                                         optionflags=optionflags)
 
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
index 92d2d74..01f7acd 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -512,15 +512,11 @@ will only be generated for it once:
     >>> tests[1].name.split('.')[-1] in ['f', 'g']
     True
 
-Filter Functions
-~~~~~~~~~~~~~~~~
-A filter function can be used to restrict which objects get examined,
-but this is temporary, undocumented internal support for testmod's
-deprecated isprivate gimmick.
-
-    >>> def namefilter(prefix, base):
-    ...     return base.startswith('a_')
-    >>> tests = doctest.DocTestFinder(_namefilter=namefilter).find(SampleClass)
+Empty Tests
+~~~~~~~~~~~
+By default, an object with no doctests doesn't create any tests:
+
+    >>> tests = doctest.DocTestFinder().find(SampleClass)
     >>> tests.sort()
     >>> for t in tests:
     ...     print '%2s  %s' % (len(t.examples), t.name)
@@ -528,6 +524,9 @@ deprecated isprivate gimmick.
      3  SampleClass.NestedClass
      1  SampleClass.NestedClass.__init__
      1  SampleClass.__init__
+     2  SampleClass.a_classmethod
+     1  SampleClass.a_property
+     1  SampleClass.a_staticmethod
      1  SampleClass.double
      1  SampleClass.get
 
@@ -536,8 +535,7 @@ tells it to include (empty) tests for objects with no doctests.  This feature
 is really to support backward compatibility in what doctest.master.summarize()
 displays.
 
-    >>> tests = doctest.DocTestFinder(_namefilter=namefilter,
-    ...                                exclude_empty=False).find(SampleClass)
+    >>> tests = doctest.DocTestFinder(exclude_empty=False).find(SampleClass)
     >>> tests.sort()
     >>> for t in tests:
     ...     print '%2s  %s' % (len(t.examples), t.name)
@@ -547,35 +545,12 @@ displays.
      0  SampleClass.NestedClass.get
      0  SampleClass.NestedClass.square
      1  SampleClass.__init__
-     1  SampleClass.double
-     1  SampleClass.get
-
-If a given object is filtered out, then none of the objects that it
-contains will be added either:
-
-    >>> def namefilter(prefix, base):
-    ...     return base == 'NestedClass'
-    >>> tests = doctest.DocTestFinder(_namefilter=namefilter).find(SampleClass)
-    >>> tests.sort()
-    >>> for t in tests:
-    ...     print '%2s  %s' % (len(t.examples), t.name)
-     3  SampleClass
-     1  SampleClass.__init__
      2  SampleClass.a_classmethod
      1  SampleClass.a_property
      1  SampleClass.a_staticmethod
      1  SampleClass.double
      1  SampleClass.get
 
-The filter function apply to contained objects, and *not* to the
-object explicitly passed to DocTestFinder:
-
-    >>> def namefilter(prefix, base):
-    ...     return base == 'SampleClass'
-    >>> tests = doctest.DocTestFinder(_namefilter=namefilter).find(SampleClass)
-    >>> len(tests)
-    9
-
 Turning off Recursion
 ~~~~~~~~~~~~~~~~~~~~~
 DocTestFinder can be told not to look for tests in contained objects
@@ -1913,20 +1888,6 @@ def test_DocTestSuite():
        modified the test globals, which are a copy of the
        sample_doctest module dictionary.  The test globals are
        automatically cleared for us after a test.
-
-       Finally, you can provide an alternate test finder.  Here we'll
-       use a custom test_finder to to run just the test named bar.
-       However, the test in the module docstring, and the two tests
-       in the module __test__ dict, aren't filtered, so we actually
-       run three tests besides bar's.  The filtering mechanisms are
-       poorly conceived, and will go away someday.
-
-         >>> finder = doctest.DocTestFinder(
-         ...    _namefilter=lambda prefix, base: base!='bar')
-         >>> suite = doctest.DocTestSuite('test.sample_doctest',
-         ...                              test_finder=finder)
-         >>> suite.run(unittest.TestResult())
-         <unittest.TestResult run=4 errors=0 failures=1>
        """
 
 def test_DocFileSuite():
diff --git a/Misc/NEWS b/Misc/NEWS
index f5a225f..3c692f2 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -106,6 +106,9 @@ Extension Modules
 Library
 -------
 
+- The optional ``is_private`` argument to ``doctest.testmod()``, deprecated
+  in 2.4, was removed.
+
 - Patch #1359618: Speed up charmap encoder by using a trie structure
   for lookup.
 
-- 
cgit v0.12

