3

The docs don't seem to be very clear on how to address the following ...

def test():
    """
    >>> import doctest
    >>> doctest.ELLIPSIS_MARKER = '<ignore>'
    >>> import pandas as pd
    >>> raise pd.errors.InvalidIndexError # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
    Traceback (most recent call last):
     <ignore>
    <ignore>InvalidIndexError
    """

import doctest
doctest.run_docstring_examples(test, globals())

This will work fine but is not addressing the wildcard at the front of <ignore>InvalidIndexError

def test():
    """
    >>> import doctest
    >>> doctest.ELLIPSIS_MARKER = '<ignore>'
    >>> import pandas as pd
    >>> raise pd.errors.InvalidIndexError # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
    Traceback (most recent call last):
     <ignore>
    pandas.errors.InvalidIndexError
    """

import doctest
doctest.run_docstring_examples(test, globals())

Note pandas version is 1.1.3

References

Alexander McFarlane
  • 10,643
  • 9
  • 59
  • 100
  • I'm getting `AttributeError: module 'pandas.errors' has no attribute 'InvalidIndexError'`. Maybe it would be better if you used an example from the stdlib. – wjandrea Feb 21 '21 at 22:51
  • you're importing `pandas as pd`, but naming it `pandas.errors.InvalidIndexError`. Shouldn't that be `pd.errors.InvalidIndexError`? – Adam Smith Feb 21 '21 at 23:03
  • @wjandrea I listed my pandas version. The whole point is to pick up errors from non std lib as they have the full module path when raised. I want to wild card the exception irrespective of the module it was declared in @ adam - not in this example, it lists the full module path – Alexander McFarlane Feb 22 '21 at 11:42

1 Answers1

2

doctest requires exceptions to look a certain way. From the docs:

Each line of the traceback stack (if present) must be indented further than the first line of the example, or start with a non-alphanumeric character. The first line following the traceback header indented the same and starting with an alphanumeric is taken to be the start of the exception detail.

(added bold)

This means if you make the ELLIPSIS_MARKER start with an alphanumeric, it'll work properly. Here's an example using re.error:

def test():
    """
    >>> import doctest
    >>> doctest.ELLIPSIS_MARKER = 'MODULE.'
    >>> import re
    >>> raise re.error(None) # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    MODULE.error: None
    """
  • By the way:

    Note that tracebacks are treated very specially. In particular, in the rewritten example, the use of ... is independent of doctest's ELLIPSIS option. The ellipsis in that example could be left out, or could just as well be three (or three hundred) commas or digits, or an indented transcript of a Monty Python skit.

For context, here's an example with no exception that uses two ellipses:

def test():
    r"""
    >>> print('foo\nbar\nbaz') # doctest: +ELLIPSIS
    foo
    ...
    ...
    """

That said, IGNORE_EXCEPTION_DETAIL may be a better solution. (I just learned about it myself.)

When specified, an example that expects an exception passes if an exception of the expected type is raised, even if the exception detail does not match. For example, an example expecting ValueError: 42 will pass if the actual exception raised is ValueError: 3*14, but will fail, e.g., if TypeError is raised.

It will also ignore the module name used in Python 3 doctest reports.

(added bold)

For example:

def test():
    """
    >>> import re
    >>> raise re.error(None) # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
        ...
    error: foobar
    """

Note that both the exception module and exception details are ignored in this example. That's on purpose, to show a side-effect of this solution.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • *will also ignore the module name* - this may be sufficient for my use case. I am genuinely more interested in the abstract case of why ellipsis doesn't seem to work here though – Alexander McFarlane Feb 22 '21 at 11:37
  • @Alexander I figured it out! Check out the updated answer. – wjandrea Feb 22 '21 at 23:43
  • This is incredibly confusing! Thanks for that! Where did you find that traceback piece?! Is it buried in the docs? – Alexander McFarlane Feb 23 '21 at 08:17
  • @Alexander The quote "Note that tracebacks are treated very specially ..."? Yeah, it's in the docs, in [the section I linked](https://docs.python.org/3/library/doctest.html#what-about-exceptions). – wjandrea Feb 23 '21 at 17:22