Python doctest: Skip entire block?
Asked Answered
L

6

25

I've got a Python module with docstrings in class methods, and a real-world example in the module docstring. The distinction is that the method-docstrings have been carefully crafted to be utterly repeatable tests, while the real-world example is just a copy'n'paste of the history from a Linux shell - which happened to invoke the python interpreter.

E.g.

"""
Real-world example:

# python2.5
Python 2.5 (release25-maint, Jul 20 2008, 20:47:25)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from packagename import module
>>> module.show_real_world_usage()
'Hello world!'
"""

class SomeClass(object):
    def someMethod(self):
        """
        >>> 1 == 1
        True
        """

I want to run the doctest in SomeClass.someMethod, but not in the module's docstrings.

Doctest's +SKIP directive only works per line, which would mean adding 10s of lines to my real-world example. Ugly!

Is there a way to make doctest skip an entire block? A bit like <!-- ... --> in HTML?

Landgrave answered 27/11, 2009 at 14:17 Comment(0)
L
6

My solution has been to trim the the 3-character >>> and ... leaders where I want doctest to skip over them, making them 2-characters.

So

"""
>>> from packagename import module
>>> module.show_real_world_usage()
'Hello world!'
"""

has become

"""
>> from packagename import module
>> module.show_real_world_usage()
'Hello world!'
"""

Epydoc doesn't display this as nicely as it does doctests, but I can live with this. A skip-until-further-notice directive in doctest would be welcome though.

Landgrave answered 27/11, 2009 at 16:0 Comment(3)
A workaround regarding the display can be found here: https://mcmap.net/q/529838/-python-doctest-skip-entire-blockDewberry
The examples cannot be copy-pasted into an IPython REPL and work, afterwards.Monopode
this won't play nice with searches. No doubt other workflows tooOstrich
B
27

Wrap the example in a function and then skip the function call:

"""
>>> def example():
...    from packagename import module
...    module.show_real_world_usage()
...
>>> example() # doctest: +SKIP
'Hello world!'
"""
Bedevil answered 1/10, 2011 at 19:9 Comment(0)
L
6

My solution has been to trim the the 3-character >>> and ... leaders where I want doctest to skip over them, making them 2-characters.

So

"""
>>> from packagename import module
>>> module.show_real_world_usage()
'Hello world!'
"""

has become

"""
>> from packagename import module
>> module.show_real_world_usage()
'Hello world!'
"""

Epydoc doesn't display this as nicely as it does doctests, but I can live with this. A skip-until-further-notice directive in doctest would be welcome though.

Landgrave answered 27/11, 2009 at 16:0 Comment(3)
A workaround regarding the display can be found here: https://mcmap.net/q/529838/-python-doctest-skip-entire-blockDewberry
The examples cannot be copy-pasted into an IPython REPL and work, afterwards.Monopode
this won't play nice with searches. No doubt other workflows tooOstrich
S
2

If it's not an actual doctest by any means, you can just assign the value to a variable. For example,

example_usage = """
Real-world example:

# python2.5
...
"""

will cause that "test" to not be evaluated.

It might be better to use __example_usage__ (or something else surrounded by double-underscores) so that it's clear that's a "magic" variable and not a variable to be used within the context of the script.

Stunning answered 27/11, 2009 at 14:28 Comment(3)
Neat, but then it's also invisible to help() and epydoc.Landgrave
I'm not sure about help(), but you can just add a new field in epydoc: epydoc.sourceforge.net/epydoc.html#adding-new-fieldsStunning
Dunder names should be reserved for system-defined names.. I would make it a simple private instead: _example_usageAccede
D
2

A small workaround building upon RobM's answer preserves the display/formatting by starting the example with a >>> like that:

""" 
>>>
>> from packagename import module 
>> module.show_real_world_usage() 
'Hello world!' 
"""
Dewberry answered 5/3, 2019 at 11:55 Comment(0)
B
2

I went for the # doctest: +SKIP on every line

def doc_test_test():
    """Doc tests
    
    Examples:
        
        >>> do_something1() # doctest: +SKIP
        >>> do_something2() # doctest: +SKIP
        >>> do_something3() # doctest: +SKIP
    """
    pass
Barbi answered 24/3, 2022 at 14:5 Comment(0)
I
1

with xdoctest you can use this >>> # doctest: +SKIP as first line:

def some_function():
    """
    Some documentation
    
    Examples:
        
        >>> # doctest: +SKIP
        >>> do_something() 
        >>> do_something_else()
        >>> and_do_this()
    """

unfortunately doctest itself crashes (and sphinx prints that as >>> instead of completely ignoring it).

Illume answered 4/10, 2022 at 12:25 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.