skip to navigation
skip to content

pytest-doctest-custom 1.0.0

A py.test plugin for customizing string representations of doctest results.

Development
Last release
PyPI status

Tested on CPython 2.6+/3.2+, PyPy (2, 4 and 5), PyPy3 (2 and 5), PyPy-STM 2.5.1 and Jython 2.7.0, using py.test 2.1+ (2.8.5+ for the CI service; 2.2.4+ for Jython).

What does it do?

Change the display hook used by doctest to render the object representations.

For a given code with doctests, you can run:

py.test --doctest-modules --doctest-repr=IPython.lib.pretty:pretty

That will run the doctest examples as usual, but the results won’t be printed by calling a __repr__ method directly, but by calling the given function with the resulting value as its single parameter.

To do that, it just needs a representation formatting callable that given an object, returns a string with its representation. It should be passed as the --doctest-repr command line option addressed as module:object, with dots for nested modules/objects. For built-ins like the ascii function, you can just remove the module: prefix.

You can also use a printer callable that always returns None but writes its result to some stream/file. In this case you should use this package stdout_proxy:

# mymodule.py
from pytest_doctest_custom import stdout_proxy
from pprint import PrettyPrinter
pp = PrettyPrinter(width=72, stream=stdout_proxy).pprint

So you can run:

py.test --doctest-modules --doctest-repr=mymodule:pp

Common representation formatters/printers

Be careful with the default “printers”, you should always use the formatting methods/functions instead of printing ones, as printer objects commonly assigns themselves to sys.stdout on initialization and the doctest runner collects printed data by shortly mocking such stream. This package temporarily changes the sys output/error streams while it finds the addressed callable, but that’s not enough if the module had already been imported (like conftest.py). When possible, use a representation formatter callable or be explicit about the output stream for the printer callable (it should be pytest_doctest_custom.stdout_proxy).

  • IPython “pretty” module (for output, without the “Out[#]:” prefix)

To use this one, you need to have IPython installed on the testing environment (e.g. including ipython in the tox deps list). A possible tox.ini file for running toctests on a project would be:

[tox]
envlist = py{35,34,27}

[testenv]
deps = ipython
commands = py.test {posargs}

[pytest]
addopts = --doctest-modules
          --doctest-glob=test_*.rst
          --doctest-repr=IPython.lib.pretty:pretty
          --ignore setup.py

You can customize its parameters such as the max_width and max_seq_length by creating a custom function for your needs, e.g. by adding this to the conftest.py module and calling py.test with --doctest-repr=conftest:doctest_pretty:

# conftest.py
from IPython.lib.pretty import pretty
def doctest_pretty(value):
    return pretty(value, max_width=72)

This pretty printer sorts sets, frozensets and dicts (by keys), breaks lines with fixed indentation, and has a consistent set/frozenset printing result for testing on both Python 2 and 3 (CPython 2.7 and 3.3+). But it’s not a Python standard library, such printer needs IPython as a requirement for running tests, which comes with much more stuff, not just the pretty printer. In CPython 2.6/3.2 you need to ensure that the IPython version is compatible (e.g. with deps = ipython<2 in your tox.ini).

In PyPy that representation printer shows any dict as a dictproxy (tested with IPython 5.0.0, PyPy 5.3.1) because they’re all the same and the dict printer gets replaced, so a hack is required to ensure a common behavior between CPython and PyPy. You can create a pytest_configure hook in the very same conftest.py either to monkeypatch to types.DictProxyType a dict derivative like type("dictproxy", (dict,), {}) reloading the IPython.lib.pretty module afterwards, or to rebuild the IPython.lib.pretty dict representation printer by assigning back its _dict_pprinter_factory("{", "}", dict) to its _type_pprinters[dict]. The same can be said about PyPy3, and its v2.4.0 is a Python 3.2, therefore it requires ipython<2.

IPython isn’t compatible with Jython.

  • Python “pprint” module (Standard Library)

You can use the pprint.pformat function directly with --doctest-repr=ppretty:pformat. You shouldn’t directly use the pprint method from pprint.PrettyPrinter objects unless the stream was properly set to stdout_proxy.

To customize its parameters such as width and indent, you can put a PrettyPrinter object in your code, for example:

# conftest.py
import pprint
doctest_pp = pprint.PrettyPrinter(width=72)

To run py.test with the pformat attribute of that PrettyPrinter instance, giving with --doctest-repr=conftest:doctest_pp.pformat shall be enough.

The standard library pretty printer sorts dicts (by keys), breaks lines with a custom indentation size, but several containers have a result that depends on the Python version (e.g. empty set as "set()" in Python 2.6 and 3 but as set([]) in Python 2.7, single item set as {item} in Python 3 but as set([item]) in Python 2). On the other hand, this is a Python standard library, there’s no extra requirement for tests, and behaves in PyPy/PyPy3 and Jython as it does in CPython.

Installing

You can either use pip:

pip install pytest-doctest-custom

Or setup.py directly:

python setup.py install

Copyright (C) 2016 Danilo de Jesus da Silva Bellini

 
File Type Py Version Uploaded on Size
pytest-doctest-custom-1.0.0.tar.gz (md5) Source 2016-07-25 13KB
pytest-doctest-custom-1.0.0.zip (md5) Source 2016-07-25 22KB
pytest_doctest_custom-1.0.0-py2.py3-none-any.whl (md5) Python Wheel 3.5 2016-07-25 9KB