]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #19138: doctest's IGNORE_EXCEPTION_DETAIL now allows no detail at all.
authorTim Peters <tim@python.org>
Wed, 4 Dec 2013 03:02:05 +0000 (21:02 -0600)
committerTim Peters <tim@python.org>
Wed, 4 Dec 2013 03:02:05 +0000 (21:02 -0600)
Lib/doctest.py
Lib/test/test_doctest.py
Misc/NEWS

index ee4e0687844ad6e8f079d7c08a51e83b293e0db7..fcfcbb037b7b900111a5773cb0549b4eb2210c29 100644 (file)
@@ -318,6 +318,32 @@ def _comment_line(line):
     else:
         return '#'
 
+def _strip_exception_details(msg):
+    # Support for IGNORE_EXCEPTION_DETAIL.
+    # Get rid of everything except the exception name; in particular, drop
+    # the possibly dotted module path (if any) and the exception message (if
+    # any).  We assume that a colon is never part of a dotted name, or of an
+    # exception name.
+    # E.g., given
+    #    "foo.bar.MyError: la di da"
+    # return "MyError"
+    # Or for "abc.def" or "abc.def:\n" return "def".
+
+    start, end = 0, len(msg)
+    # The exception name must appear on the first line.
+    i = msg.find("\n")
+    if i >= 0:
+        end = i
+    # retain up to the first colon (if any)
+    i = msg.find(':', 0, end)
+    if i >= 0:
+        end = i
+    # retain just the exception name
+    i = msg.rfind('.', 0, end)
+    if i >= 0:
+        start = i+1
+    return msg[start: end]
+
 class _OutputRedirectingPdb(pdb.Pdb):
     """
     A specialized version of the python debugger that redirects stdout
@@ -1325,10 +1351,9 @@ class DocTestRunner:
 
                 # Another chance if they didn't care about the detail.
                 elif self.optionflags & IGNORE_EXCEPTION_DETAIL:
-                    m1 = re.match(r'(?:[^:]*\.)?([^:]*:)', example.exc_msg)
-                    m2 = re.match(r'(?:[^:]*\.)?([^:]*:)', exc_msg)
-                    if m1 and m2 and check(m1.group(1), m2.group(1),
-                                           self.optionflags):
+                    if check(_strip_exception_details(example.exc_msg),
+                             _strip_exception_details(exc_msg),
+                             self.optionflags):
                         outcome = SUCCESS
 
             # Report the outcome.
index 5b53ca8e02fd1f97321112f769e8e40b25310034..56193e87b1c9d446c6895b23cea0e1b55510c22c 100644 (file)
@@ -1054,6 +1054,33 @@ But IGNORE_EXCEPTION_DETAIL does not allow a mismatch in the exception type:
         ValueError: message
     TestResults(failed=1, attempted=1)
 
+If the exception does not have a message, you can still use
+IGNORE_EXCEPTION_DETAIL to normalize the modules between Python 2 and 3:
+
+    >>> def f(x):
+    ...     r'''
+    ...     >>> from http.client import HTTPException
+    ...     >>> raise HTTPException() #doctest: +IGNORE_EXCEPTION_DETAIL
+    ...     Traceback (most recent call last):
+    ...     foo.bar.HTTPException
+    ...     '''
+    >>> test = doctest.DocTestFinder().find(f)[0]
+    >>> doctest.DocTestRunner(verbose=False).run(test)
+    TestResults(failed=0, attempted=2)
+
+Note that a trailing colon doesn't matter either:
+
+    >>> def f(x):
+    ...     r'''
+    ...     >>> from http.client import HTTPException
+    ...     >>> raise HTTPException() #doctest: +IGNORE_EXCEPTION_DETAIL
+    ...     Traceback (most recent call last):
+    ...     foo.bar.HTTPException:
+    ...     '''
+    >>> test = doctest.DocTestFinder().find(f)[0]
+    >>> doctest.DocTestRunner(verbose=False).run(test)
+    TestResults(failed=0, attempted=2)
+
 If an exception is raised but not expected, then it is reported as an
 unexpected exception:
 
index 45f09b1e0b729509a3a0a2aea755d5811b9fe147..d767b2c2aba1912f2827da60051c29117a001af3 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #19138: doctest's IGNORE_EXCEPTION_DETAIL now allows a match when
+  no exception detail exists (no colon following the exception's name, or
+  a colon does follow but no text follows the colon).
+
 - Issue #19827: On UNIX, setblocking() and settimeout() methods of
   socket.socket can now avoid a second syscall if the ioctl() function can be
   used, or if the non-blocking flag of the socket is unchanged.