]> granicus.if.org Git - python/commitdiff
Only recognize the expected output as an exception if it *starts* with
authorEdward Loper <edloper@gradient.cis.upenn.edu>
Wed, 25 Aug 2004 23:07:03 +0000 (23:07 +0000)
committerEdward Loper <edloper@gradient.cis.upenn.edu>
Wed, 25 Aug 2004 23:07:03 +0000 (23:07 +0000)
a traceback message.  I.e., examples that raise exceptions may no
longer generate pre-exception output.  This restores the behavior of
doctest in python 2.3.  The ability to check pre-exception output is
being removed because it makes the documentation simpler; and because
there are very few use cases for it.

Doc/lib/libdoctest.tex
Lib/doctest.py
Lib/test/test_doctest.py

index 0741aa0bfae4195e70bff920cf81d7bb72f49099..895182137636dc6d89efeec372c837ee76b29479 100644 (file)
@@ -235,57 +235,57 @@ Traceback (most recent call last):
 ValueError: list.remove(x): x not in list
 \end{verbatim}
 
-That doctest succeeds if, and only if, \exception{ValueError} is raised,
-with the \samp{list.remove(x): x not in list} detail as shown.
+That doctest succeeds if \exception{ValueError} is raised, with the
+\samp{list.remove(x): x not in list} detail as shown.\footnote{The
+  doctest also succeeds if it prints the exact text of the traceback
+  message; otherwise, it fails.}
 
-The expected output for an exception is divided into four parts.
-First, an example may produce some normal output before an exception
-is raised, although that's unusual.  The "normal output" is taken to
-be everything until the first "Traceback" line, and is usually an
-empty string.  Next, the traceback line must be one of these two, and
-indented the same as the first line in the example:
+The expected output for an exception must start with a traceback
+header, which may be either of the following two lines, indented the
+same as the first line of the example:
 
 \begin{verbatim}
 Traceback (most recent call last):
 Traceback (innermost last):
 \end{verbatim}
 
-The most interesting part is the last part:  the line(s) starting with the
-exception type and detail.  This is usually the last line of a traceback,
-but can extend across any number of lines.  After the "Traceback" line,
-doctest simply ignores everything until the first line indented the same as
-the first line of the example, \emph{and} starting with an alphanumeric
-character.  This example illustrates the complexities that are possible:
+The traceback header is followed by an optional traceback stack, whose
+contents are ignored by doctest.  Each line of the traceback stack
+must be indented further than the first line of the example, \emph{or}
+start with a non-alphanumeric character.  Typically, the traceback
+stack is either omitted or copied verbatim from an interactive
+session.
+
+The traceback stack is followed by the most interesting part: the
+line(s) containing the exception type and detail.  This is usually the
+last line of a traceback, but can extend across multiple lines if the
+exception has a multi-line detail, as illustrated in the following
+example:
 
 \begin{verbatim}
->>> print 1, 2; raise ValueError('printed 1\nand 2\n  but not 3')
-1 2
+>>> raise ValueError('multi\n   line\ndetail')
 Traceback (most recent call last):
-... indented the same, but doesn't start with an alphanumeric
-  not indented the same, so ignored too
-  File "/Python23/lib/doctest.py", line 442, in _run_examples_inner
-    compileflags, 1) in globs
-  File "<string>", line 1, in ?   # and all these are ignored
-ValueError: printed 1
-and 2
-  but not 3
+  File "<stdin>", line 1, in ?
+ValueError: multi
+    line
+detail
 \end{verbatim}
 
-The first (\samp{1 2}) and last three (starting with
-\exception{ValueError}) lines are compared, and the rest are ignored.
+The last three (starting with \exception{ValueError}) lines are
+compared against the exception's type and detail, and the rest are
+ignored.
 
-Best practice is to omit the ``File'' lines, unless they add
+Best practice is to omit the traceback stack, unless it adds
 significant documentation value to the example.  So the example above
 is probably better as:
 
 \begin{verbatim}
->>> print 1, 2; raise ValueError('printed 1\nand 2\n  but not 3')
-1 2
+>>> raise ValueError('multi\n   line\ndetail')
 Traceback (most recent call last):
-   ...
-ValueError: printed 1
-and 2
-  but not 3
+    ...
+ValueError: multi
+    line
+detail
 \end{verbatim}
 
 Note the tracebacks are treated very specially.  In particular, in the
@@ -293,11 +293,6 @@ rewritten example, the use of \samp{...} is independent of doctest's
 \constant{ELLIPSIS} option.  The ellipsis in that example could
 be left out, or could just as well be three (or three hundred) commas.
 
-\versionchanged[The abilities to check both normal output and an
-                exception in a single example, and to have a multi-line
-                exception detail, were added]{2.4}
-
-
 \subsection{Option Flags and Directives\label{doctest-options}}
 
 A number of option flags control various aspects of doctest's comparison
@@ -634,7 +629,7 @@ Backslashes in a raw docstring: m\n
 \end{verbatim}
 
   Otherwise, the backslash will be interpreted as part of the string.
-  E.g., the "\textbackslash" above would be interpreted as a newline
+  E.g., the "{\textbackslash}" above would be interpreted as a newline
   character.  Alternatively, you can double each backslash in the
   doctest version (and not use a raw string):
 
index 43f21b2e1c6c02915f2f9f2d073d3525f658dd66..01f7cb32367cece45b4bb60e1202dd74f73ecdea 100644 (file)
@@ -1281,15 +1281,14 @@ class DocTestRunner:
 
     # A regular expression for handling `want` strings that contain
     # expected exceptions.  It divides `want` into three pieces:
-    #    - the pre-exception output (`want`)
     #    - the traceback header line (`hdr`)
+    #    - the traceback stack (`stack`)
     #    - the exception message (`msg`), as generated by
     #      traceback.format_exception_only()
     # `msg` may have multiple lines.  We assume/require that the
     # exception message is the first non-indented line starting with a word
     # character following the traceback header line.
     _EXCEPTION_RE = re.compile(r"""
-        (?P<want> .*?)   # suck up everything until traceback header
         # Grab the traceback header.  Different versions of Python have
         # said different things on the first traceback line.
         ^(?P<hdr> Traceback\ \(
@@ -1297,9 +1296,9 @@ class DocTestRunner:
             |   innermost\ last
             ) \) :
         )
-        \s* $  # toss trailing whitespace on traceback header
-        .*?    # don't blink:  absorb stuff until a line *starts* with \w
-        ^ (?P<msg> \w+ .*)
+        \s* $                # toss trailing whitespace on the header.
+        (?P<stack> .*?)      # don't blink: absorb stuff until...
+        ^ (?P<msg> \w+ .*)   #     a line *starts* with alphanum.
         """, re.VERBOSE | re.MULTILINE | re.DOTALL)
 
     def __run(self, test, compileflags, out):
@@ -1374,13 +1373,10 @@ class DocTestRunner:
                                                      exc_info)
                     failures += 1
                 else:
-                    e_want, e_msg = m.group('want', 'msg')
-                    # The test passes iff the pre-exception output and
-                    # the exception description match the values given
-                    # in `want`.
-                    if (self._checker.check_output(e_want, got,
-                                                   self.optionflags) and
-                        self._checker.check_output(e_msg, exc_msg,
+                    # The test passes iff the expected exception
+                    # message (`m.group('msg')`) matches the actual
+                    # exception message (`exc_msg`).
+                    if (self._checker.check_output(m.group('msg'), exc_msg,
                                                    self.optionflags)):
                         self.report_success(out, test, example,
                                        got + _exception_traceback(exc_info))
index d5e9ef50d45aa1f30f4239a8b12777d848cdecf6..5d0cf90be5a07ee91bbb9888de51a84b66153fae 100644 (file)
@@ -623,8 +623,10 @@ replaced with any other string:
     >>> doctest.DocTestRunner(verbose=False).run(test)
     (0, 2)
 
-An example may generate output before it raises an exception; if it
-does, then the output must match the expected output:
+An example may not generate output before it raises an exception; if
+it does, then the traceback message will not be recognized as
+signaling an expected exception, so the example will be reported as an
+unexpected exception:
 
     >>> def f(x):
     ...     '''
@@ -636,7 +638,15 @@ does, then the output must match the expected output:
     ...     '''
     >>> test = doctest.DocTestFinder().find(f)[0]
     >>> doctest.DocTestRunner(verbose=False).run(test)
-    (0, 2)
+    ... # doctest: +ELLIPSIS
+    **********************************************************************
+    Line 3, in f
+    Failed example:
+        print 'pre-exception output', x/0
+    Exception raised:
+        ...
+        ZeroDivisionError: integer division or modulo by zero
+    (1, 2)
 
 Exception messages may contain newlines: