Merged revisions 80578 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r80578 | nick.coghlan | 2010-04-29 00:29:06 +1000 (Thu, 29 Apr 2010) | 1 line

  Issue 7490: make IGNORE_EXCEPTION_DETAIL also ignore details of the module containing the exception under test (original patch by Lennart Regebro)
........
This commit is contained in:
Nick Coghlan 2010-06-12 13:42:46 +00:00
parent 0681785d09
commit 5e76e94fd4
5 changed files with 108 additions and 14 deletions

View File

@ -444,8 +444,9 @@ Some details you should read once, but won't need to remember:
with an alphanumeric is taken to be the start of the exception detail. Of
course this does the right thing for genuine tracebacks.
* When the :const:`IGNORE_EXCEPTION_DETAIL` doctest option is is specified,
everything following the leftmost colon is ignored.
* When the :const:`IGNORE_EXCEPTION_DETAIL` doctest option is specified,
everything following the leftmost colon and any module information in the
exception name is ignored.
* The interactive shell omits the traceback header line for some
:exc:`SyntaxError`\ s. But doctest uses the traceback header line to
@ -535,20 +536,38 @@ doctest decides whether actual output matches an example's expected output:
exception raised is ``ValueError: 3*14``, but will fail, e.g., if
:exc:`TypeError` is raised.
Note that a similar effect can be obtained using :const:`ELLIPSIS`, and
:const:`IGNORE_EXCEPTION_DETAIL` may go away when Python releases prior to 2.4
become uninteresting. Until then, :const:`IGNORE_EXCEPTION_DETAIL` is the only
clear way to write a doctest that doesn't care about the exception detail yet
continues to pass under Python releases prior to 2.4 (doctest directives appear
to be comments to them). For example, ::
It will also ignore the module name used in Python 3 doctest reports. Hence
both these variations will work regardless of whether the test is run under
Python 2.7 or Python 3.2 (or later versions):
>>> raise CustomError('message') #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
CustomError: message
>>> raise CustomError('message') #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
my_module.CustomError: message
Note that :const:`ELLIPSIS` can also be used to ignore the
details of the exception message, but such a test may still fail based
on whether or not the module details are printed as part of the
exception name. Using :const:`IGNORE_EXCEPTION_DETAIL` and the details
from Python 2.3 is also the only clear way to write a doctest that doesn't
care about the exception detail yet continues to pass under Python 2.3 or
earlier (those releases do not support doctest directives and ignore them
as irrelevant comments). For example, ::
>>> (1, 2)[3] = 'moo' #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: object doesn't support item assignment
passes under Python 2.4 and Python 2.3. The detail changed in 2.4, to say "does
not" instead of "doesn't".
passes under Python 2.3 and later Python versions, even though the detail
changed in Python 2.4 to say "does not" instead of "doesn't".
.. versionchanged:: 3.2
:const:`IGNORE_EXCEPTION_DETAIL` now also ignores any information
relating to the module containing the exception under test
.. data:: SKIP
@ -663,7 +682,6 @@ usually the only meaningful choice. However, option flags can also be passed to
functions that run doctests, establishing different defaults. In such cases,
disabling an option via ``-`` in a directive can be useful.
There's also a way to register new option flag names, although this isn't useful
unless you intend to extend :mod:`doctest` internals via subclassing:

View File

@ -1277,9 +1277,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(0), m2.group(0),
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):
outcome = SUCCESS

View File

@ -864,6 +864,77 @@ detail:
>>> doctest.DocTestRunner(verbose=False).run(test)
TestResults(failed=0, attempted=1)
IGNORE_EXCEPTION_DETAIL also ignores difference in exception formatting
between Python versions. For example, in Python 2.x, the module path of
the exception is not in the output, but this will fail under Python 3:
>>> def f(x):
... r'''
... >>> from http.client import HTTPException
... >>> raise HTTPException('message')
... Traceback (most recent call last):
... HTTPException: message
... '''
>>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test)
... # doctest: +ELLIPSIS
**********************************************************************
File ..., line 4, in f
Failed example:
raise HTTPException('message')
Expected:
Traceback (most recent call last):
HTTPException: message
Got:
Traceback (most recent call last):
...
http.client.HTTPException: message
TestResults(failed=1, attempted=2)
But in Python 3 the module path is included, and therefore a test must look
like the following test to succeed in Python 3. But that test will fail under
Python 2.
>>> def f(x):
... r'''
... >>> from http.client import HTTPException
... >>> raise HTTPException('message')
... Traceback (most recent call last):
... http.client.HTTPException: message
... '''
>>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test)
TestResults(failed=0, attempted=2)
However, with IGNORE_EXCEPTION_DETAIL, the module name of the exception
(or its unexpected absence) will be ignored:
>>> def f(x):
... r'''
... >>> from http.client import HTTPException
... >>> raise HTTPException('message') #doctest: +IGNORE_EXCEPTION_DETAIL
... Traceback (most recent call last):
... HTTPException: message
... '''
>>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test)
TestResults(failed=0, attempted=2)
The module path will be completely ignored, so two different module paths will
still pass if IGNORE_EXCEPTION_DETAIL is given. This is intentional, so it can
be used when exceptions have changed module.
>>> def f(x):
... r'''
... >>> from http.client import HTTPException
... >>> raise HTTPException('message') #doctest: +IGNORE_EXCEPTION_DETAIL
... Traceback (most recent call last):
... foo.bar.HTTPException: message
... '''
>>> test = doctest.DocTestFinder().find(f)[0]
>>> doctest.DocTestRunner(verbose=False).run(test)
TestResults(failed=0, attempted=2)
But IGNORE_EXCEPTION_DETAIL does not allow a mismatch in the exception type:
>>> def f(x):

View File

@ -638,6 +638,7 @@ Marc Recht
John Redford
Terry Reedy
Steve Reeves
Lennart Regebro
Ofir Reichenberg
Sean Reifschneider
Michael P. Reilly

View File

@ -12,6 +12,10 @@ What's New in Python 3.2 Alpha 1?
Core and Builtins
-----------------
- Issue #7490: to facilitate sharing of doctests between 2.x and 3.x test
suites, the IGNORE_EXCEPTION_DETAIL directive now also ignores the module
location of the raised exception.
- Issue #8969: On Windows, use mbcs codec in strict mode to encode and decode
filenames and enable os.fsencode().