|GithubActions| |CircleCI| |Appveyor| |Codecov| |Pypi| |PypiDownloads| |ReadTheDocs|
.. The large version wont work because github strips rst image rescaling.
.. image:: https://i.imgur.com/u0tYYxM.png
:height: 100px
:align: left
Xdoctest - Execute doctests. A Python package for executing tests in
documentation strings!
What is a `doctest <https://en.wikipedia.org/wiki/Doctest>`__?
It is example code you write in a docstring!
What is a `docstring <https://en.wikipedia.org/wiki/Docstring>`__?
Its a string you use as a comment! They get attached to Python functions and
classes as metadata. They are often used to auto-generate documentation.
Why is it cool?
Because you can write tests while you code!
Tests are good. Documentation is good. Examples are good. Doctests have low
boilerplate, you write them in the same file you write your code. It often can
help you write the function. Write down how to construct minimal demo inputs
(it helps to have tools to create these) in your file. Copy that code into
IPython/Jupyter, and play with your implementation. Copy your finished code
into the body. Write down how to call the function with the demo inputs. If you
feel inclined, check that the result matches an expected result (while asserts
and checks are nice, a test that just shows how to run the code is better than
no test at all).
.. code:: python
def an_algorithm(data, config):
"""
Example:
>>> data = '([()[]])[{}([[]])]'
>>> config = {'outer': sum, 'inner': ord}
>>> an_algorithm(data, config)
1411
"""
# I wrote this function by first finding some interesting demodata
# then I wrote the body in IPython and copied it back in.
# Now I can re-use this test code I wrote in development as a test!
# Covered Code is much easier to debug (we have a MWE)!
result = config['outer'](map(config['inner'], data))
return result
The problem? How do you run the code in your doctest?
Xdoctest finds and executes your doctests for you.
Just run ``xdoctest <path-to-my-module>``.
It plugs into pytest to make it easy to run on a CI. Install and run
``pytest --xdoctest``.
The ``xdoctest`` package is a re-write of Python's builtin ``doctest``
module. It replaces the old regex-based parser with a new
abstract-syntax-tree based parser (using Python's ``ast`` module). The
goal is to make doctests easier to write, simpler to configure, and
encourage the pattern of test driven development.
+------------------+----------------------------------------------+
| Read the docs | https://xdoctest.readthedocs.io |
+------------------+----------------------------------------------+
| Github | https://github.com/Erotemic/xdoctest |
+------------------+----------------------------------------------+
| Pypi | https://pypi.org/project/xdoctest |
+------------------+----------------------------------------------+
| PyCon 2020 | `Youtube Video`_ and `Google Slides`_ |
+------------------+----------------------------------------------+
.. _Youtube Video: https://www.youtube.com/watch?v=CUjCqOw_oFk
.. _Google Slides: https://docs.google.com/presentation/d/1563XL-n7534QmktrkLSjVqX36z5uhjUFrPw8wIO6z1c
Quick Start
-----------
Installation: from pypi
^^^^^^^^^^^^^^^^^^^^^^^
Xdoctest is distributed on pypi as a universal wheel and can be pip installed on
Python 3.8+ (Python 2.7 and 3.4 / 3.5 support was removed in Version 1.1.0, 3.6 / 3.7 support was removed in Version 1.2.0).
Installations are tested on CPython and PyPy implementations.
::
pip install xdoctest
Distributions on pypi are signed with a GPG public key: ``D297D757``. If you
care enough to check the gpg signature (hopefully pip will just do this in the
future), you should also verify this agrees with the contents of
``dev/public_gpg_key``.
Usage: run your doctests
^^^^^^^^^^^^^^^^^^^^^^^^
After installing, the fastest way to run all doctests in your project
is:
::
python -m xdoctest /path/to/your/pkg-or-module.py
or if your module has been pip-installed / is in the PYTHONPATH run
::
python -m xdoctest yourmodname
Getting Started
---------------
There are two ways to use ``xdoctest``: via ``pytest`` or via the native
interface. The native interface is less opaque and implicit, but its
purpose is to run doctests. The other option is to use the widely used
``pytest`` package. This allows you to run both unit tests and doctests
with the same command and has many other advantages.
It is recommended to use ``pytest`` for automatic testing (e.g. in your
CI scripts), but for debugging it may be easier to use the native
interface.
Check if xdoctest will work on your package
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can quickly check if ``xdoctest`` will work on your package
out-of-the box by installing it via pip and running
``python -m xdoctest <pkg> all``, where ``<pkg>`` is the path to your
python package / module (or its name if it is installed in your
``PYTHONPATH``).
For example with you might test if ``xdoctest`` works on ``networkx`` or
``sklearn`` as such: ``python -m xdoctest networkx all`` /
``python -m xdoctest sklearn all``.
Using the pytest interface
^^^^^^^^^^^^^^^^^^^^^^^^^^
When ``pytest`` is run, ``xdoctest`` is automatically discovered, but is
disabled by default. This is because ``xdoctest`` needs to replace the builtin
``doctest`` plugin.
To enable this plugin, run ``pytest`` with ``--xdoctest`` or ``--xdoc``.
This can either be specified on the command line or added to your
``addopts`` options in the ``[pytest]`` section of your ``pytest.ini``
or ``tox.ini``.
To run a specific doctest, ``xdoctest`` sets up ``pytest`` node names
for these doctests using the following pattern:
``<path/to/file.py>::<callname>:<num>``. For example a doctest for a
function might look like this ``mymod.py::funcname:0``, and a class
method might look like this: ``mymod.py::ClassName::method:0``
Using the native interface.
^^^^^^^^^^^^^^^^^^^^^^^^^^^
In addition to the ``pytest`` plugin, xdoctest has a native doctest runner.
You can use the ``xdoctest`` command line tool that is installed with the
package and point it a module directory or a particular file.
You can also make it such that invoking your module as ``__main__`` invokes the
xdoctest native runner using the using the ``xdoctest.doctest_module(path)``
method, which can be placed in the ``__main__`` section of any module as such:
.. code:: python
if __name__ == '__main__':
import xdoctest
xdoctest.doctest_module(__file__)
This sets up the ability to invoke the ``xdoctest`` command line
interface. ``python -m <modname> <command>``.
However, it is typically prefered to just use the ``xdoctest`` executable and
pass it the path to your file, or the name of an installed module. In this case
it is invoked like ``xdoctest -m <modname> <command>``.
Using either of these methods you can natively invoke xdoctest on a module or
package, which exposes the command line interface. Both of these expose the
command line interface, allowing you to pass a command to xdoctest.
- If ``<command>`` is ``all``, then each enabled doctest in the module
is executed: ``python -m <modname> all``
- If ``<command>`` is ``list``, then the names of each enabled doctest
is listed.
- If ``<command>`` is ``dump``, then all doctests are converted into a format
suitable for unit testing, and dumped to stdout (new in 0.4.0).
- If ``<command>`` is a ``callname`` (name of a function or a class and
method), then that specific doctest is executed:
``python -m <modname> <callname>``. Note: you can execute disabled
doctests or functions without any arguments (zero-args) this way.
For example if you created a module ``mymod.py`` with the following
code:
.. code:: python
def func1():
"""
Example:
>>> assert func1() == 1
"""
return 1
def func2(a):
"""
Example:
>>> assert func2(1) == 2
>>> assert func2(2) == 3
"""
return a + 1
You could
* Use the command ``xdoctest -m mymod list`` to list the names of all functions with doctests
* Use the command ``xdoctest -m mymod all`` to run all functions with doctests
* Use the command ``xdoctest -m mymod func1`` to run only func1's doctest
* Use the command ``xdoctest -m mymod func2`` to run only func2's doctest
Passing ``--help`` to either way of invoking the native runner will result in
something similar to the following that outlines what other options are
available:
.. code::
usage: xdoctest [-h] [--version] [-m MODNAME] [-c COMMAND] [--style {auto,google,freeform}] [--analysis {auto,static,dynamic}] [--durations DURATIONS] [--time]
[--colored COLORED] [--nocolor] [--offset] [--report {none,cdiff,ndiff,udiff,only_first_failure}] [--options OPTIONS] [--global-exec GLOBAL_EXEC]
[--verbose VERBOSE] [--quiet] [--silent]
[arg ...]
Xdoctest 1.0.1 - on Python - 3.9.9 (main, Jun 10 2022, 17:45:11)
[GCC 11.2.0] - discover and run doctests within a python package
positional arguments:
arg Ignored if optional arguments are specified, otherwise: Defaults --modname to arg.pop(0). Defaults --command to arg.pop(0). (default: None)
optional arguments:
-h, --help show this help message and exit
--version Display version info and quit (default: False)
-m MODNAME, --modname MODNAME
Module name or path. If specified positional modules are ignored (default: None)
-c COMMAND, --command COMMAND
A doctest name or a command (list|all|<callname>). Defaults to all (default: None)
--style {auto,google,freeform}
Choose the style of doctests that will be parsed (default: auto)
--analysis {auto,static,dynamic}
How doctests are collected (default: auto)
--durations DURATIONS
Specify execution times for slowest N tests.N=0 will show times for all tests (default: None)
--time Same as if durations=0 (default: False)
--colored COLORED Enable or disable ANSI coloration in stdout (default: True)
--nocolor Disable ANSI coloration in stdout
--offset If True formatted source linenumbers will agree with their location in the source file. Otherwise they will be relative to the doctest itself. (default:
False)
--report {none,cdiff,ndiff,udiff,only_first_failure}
Choose another output format for diffs on xdoctest failure (default: udiff)
--options OPTIONS Default directive flags for doctests (default: None)
--global-exec GLOBAL_EXEC
Custom Python code to execute before every test (default: None)
--verbose VERBOSE Verbosity level. 0 is silent, 1 prints out test names, 2 additionally prints test stdout, 3 additionally prints test source (default: 3)
--quiet sets verbosity to 1
--silent sets verbosity to 0
Zero-args runner
^^^^^^^^^^^^^^^^
The native interface has a "zero-args" mode in the
``xdoctest`` runner. This allows you to run functions in your modules
via the command line as long as they take no arguments. The purpose is
to create a quick entry point to functions in your code (because
``xdoctest`` is taking the space in the ``__main__`` block).
For example, you might create a module ``mymod.py`` with the following
code:
.. code:: python
def myfunc():
print('hello world')
if __name__ == '__main__':
import xdoctest
xdoctest.doctest_module(__file__)
Even though ``myfunc`` has no doctest it can still be run using the
command ``python -m mymod myfunc``.
Note, even though "zero-arg" functions can be run via this interface
they are not run by ``python -m mymod all``, nor are they listed by
``python -m mymod list``.
However, if you are doing this often, you may be better served by `fire
<https://github.com/google/python-fire>`__.
Enhancements
------------
The main enhancements ``xdoctest`` offers over ``doctest`` are:
1. All lines in the doctest can now be prefixed with ``>>>``. There is
no need for the developer to differentiate between ``PS1`` and
``PS2`` lines. However, old-style doctests where ``PS2`` lines are
prefixed with ``...`` are still valid.
2. Additionally, the multi-line strings don't require any prefix (but
its ok if they do have either prefix).
3. Tests are executed in blocks, rather than line-by-line, thus
comment-based directives (e.g. ``# doctest: +SKIP``) can now applied
to an entire block (by placing it one the line above), in addition to having
it just apply to a single line (by placing it in-line at the end).
4. Tests without a "want" statement will ignore any stdout / final
evaluated value. This makes it easy to use simple assert statements
to perform checks in code that might write to stdout.
5. If your test has a "want" statement and ends with both a value and
stdout, both are checked, and the test will pass if either matches.
6. Ouptut from multiple sequential print statements can now be checked by
a single "got" statement. (new in 0.4.0).
7. Examples can include `async code at the top level <https://xdoctest.readthedocs.io/en/latest/manual/async_doctest.html>`__.
See code in ``dev/_compare/demo_enhancements.py`` for a demo that illustrates
several of these enhancements. This demo shows cases where ``xdoctest`` works
but ``doctest`` fails. As of version 0.9.1, there are no known syntax backwards
incompatability. Please submit an issue if you can find any backwards
incompatible cases.
Examples
--------
Here is an example demonstrating the new relaxed (and
backwards-compatible) syntax:
.. code:: python
def func():
"""
# Old way
>>> def func():
... print('The old regex-based parser required specific formatting')
>>> func()
The old regex-based parser required specific formatting
# New way
>>> def func():
>>> print('The new ast-based parser lets you prefix all lines with >>>')
>>> func()
The new ast-based parser lets you prefix all lines with >>>
"""
.. code:: python
def func():
"""
# Old way
>>> print('''
... It would be nice if we didnt have to deal with prefixes
... in multiline strings.
... '''.strip())
It would be nice if we didnt have to deal with prefixes
in multiline strings.
# New way
>>> print('''
Multiline can now be written without prefixes.
Editing them is much more natural.
'''.strip())
Multiline can now be written without prefixes.
Editing them is much more natural.
# This is ok too
>>> print('''
>>> Just prefix everything with >>> and the doctest should work
>>> '''.strip())
Just prefix everything with >>> and the doctest should work
"""
Xdoctest Parsing Style
----------------------
There are currently two main doctest parsing styles: ``google`` and
``freeform``, as well as a third style: ``auto``, which is a hybrid.
The parsing style can be set via the ``--style`` command line argument in the
Xdoctest CLI, or via the ``--xdoctest-style`` if using pytest.
Setting ``--style=google`` (or ``--xdoctest-style=google`` in pytest) enables
google-style parsing.
A `Google-style <https://sphinxcontrib-napoleon.readthedocs.io>`__ doctest is
expected to exist in Google "docblock" with an ``Example:`` or ``Doctest:``
tag. All code in this block is parsed out as a single doctest.
Setting ``--style=freeform`` (or ``--xdoctest-style=freeform`` in pytest) enables
freeform-style parsing.
A freeform style doctest is any contiguous block of lines prefixed by ``>>>``.
This is the original parsing style of the builtin doctest module. Each block is
listed as its own test.
By default Xdoctest sets ``--style=auto`` (or ``--xdoctest-style=auto`` in
pytest) which will pull all google-style blocks out as single doctests, while
still all other ``>>>`` prefixed code out as a freeform doctest.
Notes On Got/Want Tests
-----------------------
The new got/want tester is very permissive by default; it ignores
differences in whitespace, tries to normalize for python 2/3
Unicode/bytes differences, ANSI formatting, and it uses the old doctest
ELLIPSIS fuzzy matcher by default. If the "got" text matches the "want"
text at any point, the test passes.
Currently, this permissiveness is not highly configurable as it was in
the original doctest module. It is an open question as to whether or not
this module should support that level of configuration. If the test
requires a high degree of specificity in the got/want checker, it may
just be better to use an ``assert`` statement.
Backwards Compatibility
-----------------------
There are no known syntax incompatibilities with original doctests. This is
based on running doctests on real life examples in ``boltons``, ``ubelt``,
``networkx``, ``pytorch``, and on a set of extensive testing suite. Please
raise an issue or submit a merge/pull request if you find any incompatibility.
Despite full syntax backwards compatibility, there some runtime
incompatibilities by design. Specifically, Xdoctest enables a different set of
default directives, such that the "got"/"want" checker is more permissive.
Thus, a test that fails in ``doctest`` based on a "got"/"want" check, may pass
in ``xdoctest``. For this reason it is recommended that you rely on coded
``assert``-statements for system-critical code. This also makes it much easier
to transform your ``xdoctest`` into a ``unittest`` when you realize your
doctests are getting too long.
One Last Example
----------------
XDoctest is a good demonstration of itself. After pip installing xdoctest, try
running xdoctest on xdoctest.
.. code:: bash
xdoctest xdoctest
If you would like a slightly less verbose output, try
.. code:: bash
xdoctest xdoctest --verbose=1
# or
xdoctest xdoctest --verbose=0
You could also consider running xdoctests tests through pytest:
.. code:: bash
pytest $(python -c 'import xdoctest, pathlib; print(pathlib.Path(xdoctest.__file__).parent)') --xdoctest
If you would like a slightly more verbose output, try
.. code:: bash
pytest -s --verbose --xdoctest-verbose=3 --xdoctest $(python -c 'import xdoctest, pathlib; print(pathlib.Path(xdoctest.__file__).parent)')
If you ran these commands, the myriad of characters that flew across your
screen are lots more examples of what you can do with doctests.
.. |CircleCI| image:: https://circleci.com/gh/Erotemic/xdoctest.svg?style=svg
:target: https://circleci.com/gh/Erotemic/xdoctest
.. |Travis| image:: https://img.shields.io/travis/Erotemic/xdoctest/main.svg?label=Travis%20CI
:target: https://travis-ci.org/Erotemic/xdoctest
.. |Appveyor| image:: https://ci.appveyor.com/api/projects/status/github/Erotemic/xdoctest?branch=main&svg=True
:target: https://ci.appveyor.com/project/Erotemic/xdoctest/branch/main
.. |Codecov| image:: https://codecov.io/github/Erotemic/xdoctest/badge.svg?branch=main&service=github
:target: https://codecov.io/github/Erotemic/xdoctest?branch=main
.. |Pypi| image:: https://img.shields.io/pypi/v/xdoctest.svg
:target: https://pypi.python.org/pypi/xdoctest
.. |PypiDownloads| image:: https://img.shields.io/pypi/dm/xdoctest.svg
:target: https://pypistats.org/packages/xdoctest
.. |CondaDownloads| image:: https://anaconda.org/conda-forge/xdoctest/badges/downloads.svg
:target: https://anaconda.org/conda-forge/xdoctest
.. |ReadTheDocs| image:: https://readthedocs.org/projects/xdoctest/badge/?version=latest
:target: https://xdoctest.readthedocs.io
.. |GithubActions| image:: https://github.com/Erotemic/xdoctest/actions/workflows/tests.yml/badge.svg?branch=main
:target: https://github.com/Erotemic/xdoctest/actions?query=branch%3Amain
Raw data
{
"_id": null,
"home_page": "https://github.com/Erotemic/xdoctest",
"name": "xdoctest",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "xdoctest, doctest, test, docstr, pytest",
"author": "Jon Crall",
"author_email": "erotemic@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/e9/a5/7f6dfdaf3a221e16ff79281d2a3c3e4b58989c92de8964a317feb1e6cbb5/xdoctest-1.2.0.tar.gz",
"platform": null,
"description": "|GithubActions| |CircleCI| |Appveyor| |Codecov| |Pypi| |PypiDownloads| |ReadTheDocs|\n\n\n.. The large version wont work because github strips rst image rescaling.\n.. image:: https://i.imgur.com/u0tYYxM.png\n :height: 100px\n :align: left\n\n\nXdoctest - Execute doctests. A Python package for executing tests in\ndocumentation strings!\n\nWhat is a `doctest <https://en.wikipedia.org/wiki/Doctest>`__?\nIt is example code you write in a docstring!\nWhat is a `docstring <https://en.wikipedia.org/wiki/Docstring>`__?\nIts a string you use as a comment! They get attached to Python functions and\nclasses as metadata. They are often used to auto-generate documentation.\nWhy is it cool?\nBecause you can write tests while you code!\n\nTests are good. Documentation is good. Examples are good. Doctests have low\nboilerplate, you write them in the same file you write your code. It often can\nhelp you write the function. Write down how to construct minimal demo inputs\n(it helps to have tools to create these) in your file. Copy that code into\nIPython/Jupyter, and play with your implementation. Copy your finished code\ninto the body. Write down how to call the function with the demo inputs. If you\nfeel inclined, check that the result matches an expected result (while asserts\nand checks are nice, a test that just shows how to run the code is better than\nno test at all).\n\n.. code:: python\n\n\n def an_algorithm(data, config):\n \"\"\"\n Example:\n >>> data = '([()[]])[{}([[]])]'\n >>> config = {'outer': sum, 'inner': ord}\n >>> an_algorithm(data, config)\n 1411\n \"\"\"\n # I wrote this function by first finding some interesting demodata\n # then I wrote the body in IPython and copied it back in.\n # Now I can re-use this test code I wrote in development as a test!\n # Covered Code is much easier to debug (we have a MWE)!\n result = config['outer'](map(config['inner'], data))\n return result\n\n\nThe problem? How do you run the code in your doctest?\n\n\nXdoctest finds and executes your doctests for you.\nJust run ``xdoctest <path-to-my-module>``.\nIt plugs into pytest to make it easy to run on a CI. Install and run\n``pytest --xdoctest``.\n\n\nThe ``xdoctest`` package is a re-write of Python's builtin ``doctest``\nmodule. It replaces the old regex-based parser with a new\nabstract-syntax-tree based parser (using Python's ``ast`` module). The\ngoal is to make doctests easier to write, simpler to configure, and\nencourage the pattern of test driven development.\n\n\n+------------------+----------------------------------------------+\n| Read the docs | https://xdoctest.readthedocs.io |\n+------------------+----------------------------------------------+\n| Github | https://github.com/Erotemic/xdoctest |\n+------------------+----------------------------------------------+\n| Pypi | https://pypi.org/project/xdoctest |\n+------------------+----------------------------------------------+\n| PyCon 2020 | `Youtube Video`_ and `Google Slides`_ |\n+------------------+----------------------------------------------+\n\n.. _Youtube Video: https://www.youtube.com/watch?v=CUjCqOw_oFk\n.. _Google Slides: https://docs.google.com/presentation/d/1563XL-n7534QmktrkLSjVqX36z5uhjUFrPw8wIO6z1c\n\n\nQuick Start\n-----------\n\nInstallation: from pypi\n^^^^^^^^^^^^^^^^^^^^^^^\n\nXdoctest is distributed on pypi as a universal wheel and can be pip installed on\nPython 3.8+ (Python 2.7 and 3.4 / 3.5 support was removed in Version 1.1.0, 3.6 / 3.7 support was removed in Version 1.2.0).\nInstallations are tested on CPython and PyPy implementations.\n\n::\n\n pip install xdoctest\n\n\nDistributions on pypi are signed with a GPG public key: ``D297D757``. If you\ncare enough to check the gpg signature (hopefully pip will just do this in the\nfuture), you should also verify this agrees with the contents of\n``dev/public_gpg_key``.\n\n\nUsage: run your doctests\n^^^^^^^^^^^^^^^^^^^^^^^^\n\n\nAfter installing, the fastest way to run all doctests in your project\nis:\n\n::\n\n python -m xdoctest /path/to/your/pkg-or-module.py\n\nor if your module has been pip-installed / is in the PYTHONPATH run\n\n::\n\n python -m xdoctest yourmodname\n\nGetting Started\n---------------\n\nThere are two ways to use ``xdoctest``: via ``pytest`` or via the native\ninterface. The native interface is less opaque and implicit, but its\npurpose is to run doctests. The other option is to use the widely used\n``pytest`` package. This allows you to run both unit tests and doctests\nwith the same command and has many other advantages.\n\nIt is recommended to use ``pytest`` for automatic testing (e.g. in your\nCI scripts), but for debugging it may be easier to use the native\ninterface.\n\nCheck if xdoctest will work on your package\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nYou can quickly check if ``xdoctest`` will work on your package\nout-of-the box by installing it via pip and running\n``python -m xdoctest <pkg> all``, where ``<pkg>`` is the path to your\npython package / module (or its name if it is installed in your\n``PYTHONPATH``).\n\nFor example with you might test if ``xdoctest`` works on ``networkx`` or\n``sklearn`` as such: ``python -m xdoctest networkx all`` /\n``python -m xdoctest sklearn all``.\n\nUsing the pytest interface\n^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nWhen ``pytest`` is run, ``xdoctest`` is automatically discovered, but is\ndisabled by default. This is because ``xdoctest`` needs to replace the builtin\n``doctest`` plugin.\n\nTo enable this plugin, run ``pytest`` with ``--xdoctest`` or ``--xdoc``.\nThis can either be specified on the command line or added to your\n``addopts`` options in the ``[pytest]`` section of your ``pytest.ini``\nor ``tox.ini``.\n\nTo run a specific doctest, ``xdoctest`` sets up ``pytest`` node names\nfor these doctests using the following pattern:\n``<path/to/file.py>::<callname>:<num>``. For example a doctest for a\nfunction might look like this ``mymod.py::funcname:0``, and a class\nmethod might look like this: ``mymod.py::ClassName::method:0``\n\nUsing the native interface.\n^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIn addition to the ``pytest`` plugin, xdoctest has a native doctest runner.\nYou can use the ``xdoctest`` command line tool that is installed with the\npackage and point it a module directory or a particular file.\n\nYou can also make it such that invoking your module as ``__main__`` invokes the\nxdoctest native runner using the using the ``xdoctest.doctest_module(path)``\nmethod, which can be placed in the ``__main__`` section of any module as such:\n\n.. code:: python\n\n if __name__ == '__main__':\n import xdoctest\n xdoctest.doctest_module(__file__)\n\nThis sets up the ability to invoke the ``xdoctest`` command line\ninterface. ``python -m <modname> <command>``.\n\nHowever, it is typically prefered to just use the ``xdoctest`` executable and\npass it the path to your file, or the name of an installed module. In this case\nit is invoked like ``xdoctest -m <modname> <command>``.\n\nUsing either of these methods you can natively invoke xdoctest on a module or\npackage, which exposes the command line interface. Both of these expose the\ncommand line interface, allowing you to pass a command to xdoctest.\n\n- If ``<command>`` is ``all``, then each enabled doctest in the module\n is executed: ``python -m <modname> all``\n\n- If ``<command>`` is ``list``, then the names of each enabled doctest\n is listed.\n\n- If ``<command>`` is ``dump``, then all doctests are converted into a format\n suitable for unit testing, and dumped to stdout (new in 0.4.0).\n\n- If ``<command>`` is a ``callname`` (name of a function or a class and\n method), then that specific doctest is executed:\n ``python -m <modname> <callname>``. Note: you can execute disabled\n doctests or functions without any arguments (zero-args) this way.\n\nFor example if you created a module ``mymod.py`` with the following\ncode:\n\n.. code:: python\n\n\n def func1():\n \"\"\"\n Example:\n >>> assert func1() == 1\n \"\"\"\n return 1\n\n def func2(a):\n \"\"\"\n Example:\n >>> assert func2(1) == 2\n >>> assert func2(2) == 3\n \"\"\"\n return a + 1\n\nYou could\n\n* Use the command ``xdoctest -m mymod list`` to list the names of all functions with doctests\n* Use the command ``xdoctest -m mymod all`` to run all functions with doctests\n* Use the command ``xdoctest -m mymod func1`` to run only func1's doctest\n* Use the command ``xdoctest -m mymod func2`` to run only func2's doctest\n\n\nPassing ``--help`` to either way of invoking the native runner will result in\nsomething similar to the following that outlines what other options are\navailable:\n\n.. code::\n\n usage: xdoctest [-h] [--version] [-m MODNAME] [-c COMMAND] [--style {auto,google,freeform}] [--analysis {auto,static,dynamic}] [--durations DURATIONS] [--time]\n [--colored COLORED] [--nocolor] [--offset] [--report {none,cdiff,ndiff,udiff,only_first_failure}] [--options OPTIONS] [--global-exec GLOBAL_EXEC]\n [--verbose VERBOSE] [--quiet] [--silent]\n [arg ...]\n\n Xdoctest 1.0.1 - on Python - 3.9.9 (main, Jun 10 2022, 17:45:11)\n [GCC 11.2.0] - discover and run doctests within a python package\n\n positional arguments:\n arg Ignored if optional arguments are specified, otherwise: Defaults --modname to arg.pop(0). Defaults --command to arg.pop(0). (default: None)\n\n optional arguments:\n -h, --help show this help message and exit\n --version Display version info and quit (default: False)\n -m MODNAME, --modname MODNAME\n Module name or path. If specified positional modules are ignored (default: None)\n -c COMMAND, --command COMMAND\n A doctest name or a command (list|all|<callname>). Defaults to all (default: None)\n --style {auto,google,freeform}\n Choose the style of doctests that will be parsed (default: auto)\n --analysis {auto,static,dynamic}\n How doctests are collected (default: auto)\n --durations DURATIONS\n Specify execution times for slowest N tests.N=0 will show times for all tests (default: None)\n --time Same as if durations=0 (default: False)\n --colored COLORED Enable or disable ANSI coloration in stdout (default: True)\n --nocolor Disable ANSI coloration in stdout\n --offset If True formatted source linenumbers will agree with their location in the source file. Otherwise they will be relative to the doctest itself. (default:\n False)\n --report {none,cdiff,ndiff,udiff,only_first_failure}\n Choose another output format for diffs on xdoctest failure (default: udiff)\n --options OPTIONS Default directive flags for doctests (default: None)\n --global-exec GLOBAL_EXEC\n Custom Python code to execute before every test (default: None)\n --verbose VERBOSE Verbosity level. 0 is silent, 1 prints out test names, 2 additionally prints test stdout, 3 additionally prints test source (default: 3)\n --quiet sets verbosity to 1\n --silent sets verbosity to 0\n\n\nZero-args runner\n^^^^^^^^^^^^^^^^\n\nThe native interface has a \"zero-args\" mode in the\n``xdoctest`` runner. This allows you to run functions in your modules\nvia the command line as long as they take no arguments. The purpose is\nto create a quick entry point to functions in your code (because\n``xdoctest`` is taking the space in the ``__main__`` block).\n\nFor example, you might create a module ``mymod.py`` with the following\ncode:\n\n.. code:: python\n\n def myfunc():\n print('hello world')\n\n if __name__ == '__main__':\n import xdoctest\n xdoctest.doctest_module(__file__)\n\nEven though ``myfunc`` has no doctest it can still be run using the\ncommand ``python -m mymod myfunc``.\n\nNote, even though \"zero-arg\" functions can be run via this interface\nthey are not run by ``python -m mymod all``, nor are they listed by\n``python -m mymod list``.\n\nHowever, if you are doing this often, you may be better served by `fire\n<https://github.com/google/python-fire>`__.\n\nEnhancements\n------------\n\nThe main enhancements ``xdoctest`` offers over ``doctest`` are:\n\n1. All lines in the doctest can now be prefixed with ``>>>``. There is\n no need for the developer to differentiate between ``PS1`` and\n ``PS2`` lines. However, old-style doctests where ``PS2`` lines are\n prefixed with ``...`` are still valid.\n2. Additionally, the multi-line strings don't require any prefix (but\n its ok if they do have either prefix).\n3. Tests are executed in blocks, rather than line-by-line, thus\n comment-based directives (e.g. ``# doctest: +SKIP``) can now applied\n to an entire block (by placing it one the line above), in addition to having\n it just apply to a single line (by placing it in-line at the end).\n4. Tests without a \"want\" statement will ignore any stdout / final\n evaluated value. This makes it easy to use simple assert statements\n to perform checks in code that might write to stdout.\n5. If your test has a \"want\" statement and ends with both a value and\n stdout, both are checked, and the test will pass if either matches.\n6. Ouptut from multiple sequential print statements can now be checked by\n a single \"got\" statement. (new in 0.4.0).\n7. Examples can include `async code at the top level <https://xdoctest.readthedocs.io/en/latest/manual/async_doctest.html>`__.\n\nSee code in ``dev/_compare/demo_enhancements.py`` for a demo that illustrates\nseveral of these enhancements. This demo shows cases where ``xdoctest`` works\nbut ``doctest`` fails. As of version 0.9.1, there are no known syntax backwards\nincompatability. Please submit an issue if you can find any backwards\nincompatible cases.\n\n\nExamples\n--------\n\nHere is an example demonstrating the new relaxed (and\nbackwards-compatible) syntax:\n\n.. code:: python\n\n def func():\n \"\"\"\n # Old way\n >>> def func():\n ... print('The old regex-based parser required specific formatting')\n >>> func()\n The old regex-based parser required specific formatting\n\n # New way\n >>> def func():\n >>> print('The new ast-based parser lets you prefix all lines with >>>')\n >>> func()\n The new ast-based parser lets you prefix all lines with >>>\n \"\"\"\n\n.. code:: python\n\n def func():\n \"\"\"\n # Old way\n >>> print('''\n ... It would be nice if we didnt have to deal with prefixes\n ... in multiline strings.\n ... '''.strip())\n It would be nice if we didnt have to deal with prefixes\n in multiline strings.\n\n # New way\n >>> print('''\n Multiline can now be written without prefixes.\n Editing them is much more natural.\n '''.strip())\n Multiline can now be written without prefixes.\n Editing them is much more natural.\n\n # This is ok too\n >>> print('''\n >>> Just prefix everything with >>> and the doctest should work\n >>> '''.strip())\n Just prefix everything with >>> and the doctest should work\n\n \"\"\"\n\nXdoctest Parsing Style\n----------------------\n\nThere are currently two main doctest parsing styles: ``google`` and\n``freeform``, as well as a third style: ``auto``, which is a hybrid.\n\nThe parsing style can be set via the ``--style`` command line argument in the\nXdoctest CLI, or via the ``--xdoctest-style`` if using pytest.\n\n\nSetting ``--style=google`` (or ``--xdoctest-style=google`` in pytest) enables\ngoogle-style parsing.\nA `Google-style <https://sphinxcontrib-napoleon.readthedocs.io>`__ doctest is\nexpected to exist in Google \"docblock\" with an ``Example:`` or ``Doctest:``\ntag. All code in this block is parsed out as a single doctest.\n\nSetting ``--style=freeform`` (or ``--xdoctest-style=freeform`` in pytest) enables\nfreeform-style parsing.\nA freeform style doctest is any contiguous block of lines prefixed by ``>>>``.\nThis is the original parsing style of the builtin doctest module. Each block is\nlisted as its own test.\n\nBy default Xdoctest sets ``--style=auto`` (or ``--xdoctest-style=auto`` in\npytest) which will pull all google-style blocks out as single doctests, while\nstill all other ``>>>`` prefixed code out as a freeform doctest.\n\n\nNotes On Got/Want Tests\n-----------------------\n\nThe new got/want tester is very permissive by default; it ignores\ndifferences in whitespace, tries to normalize for python 2/3\nUnicode/bytes differences, ANSI formatting, and it uses the old doctest\nELLIPSIS fuzzy matcher by default. If the \"got\" text matches the \"want\"\ntext at any point, the test passes.\n\nCurrently, this permissiveness is not highly configurable as it was in\nthe original doctest module. It is an open question as to whether or not\nthis module should support that level of configuration. If the test\nrequires a high degree of specificity in the got/want checker, it may\njust be better to use an ``assert`` statement.\n\nBackwards Compatibility\n-----------------------\nThere are no known syntax incompatibilities with original doctests. This is\nbased on running doctests on real life examples in ``boltons``, ``ubelt``,\n``networkx``, ``pytorch``, and on a set of extensive testing suite. Please\nraise an issue or submit a merge/pull request if you find any incompatibility.\n\nDespite full syntax backwards compatibility, there some runtime\nincompatibilities by design. Specifically, Xdoctest enables a different set of\ndefault directives, such that the \"got\"/\"want\" checker is more permissive.\nThus, a test that fails in ``doctest`` based on a \"got\"/\"want\" check, may pass\nin ``xdoctest``. For this reason it is recommended that you rely on coded\n``assert``-statements for system-critical code. This also makes it much easier\nto transform your ``xdoctest`` into a ``unittest`` when you realize your\ndoctests are getting too long.\n\n\nOne Last Example\n----------------\n\nXDoctest is a good demonstration of itself. After pip installing xdoctest, try\nrunning xdoctest on xdoctest.\n\n.. code:: bash\n\n xdoctest xdoctest\n\nIf you would like a slightly less verbose output, try\n\n.. code:: bash\n\n xdoctest xdoctest --verbose=1\n\n # or\n\n xdoctest xdoctest --verbose=0\n\n\nYou could also consider running xdoctests tests through pytest:\n\n\n.. code:: bash\n\n pytest $(python -c 'import xdoctest, pathlib; print(pathlib.Path(xdoctest.__file__).parent)') --xdoctest\n\n\nIf you would like a slightly more verbose output, try\n\n.. code:: bash\n\n pytest -s --verbose --xdoctest-verbose=3 --xdoctest $(python -c 'import xdoctest, pathlib; print(pathlib.Path(xdoctest.__file__).parent)')\n\n\nIf you ran these commands, the myriad of characters that flew across your\nscreen are lots more examples of what you can do with doctests.\n\n\n.. |CircleCI| image:: https://circleci.com/gh/Erotemic/xdoctest.svg?style=svg\n :target: https://circleci.com/gh/Erotemic/xdoctest\n.. |Travis| image:: https://img.shields.io/travis/Erotemic/xdoctest/main.svg?label=Travis%20CI\n :target: https://travis-ci.org/Erotemic/xdoctest\n.. |Appveyor| image:: https://ci.appveyor.com/api/projects/status/github/Erotemic/xdoctest?branch=main&svg=True\n :target: https://ci.appveyor.com/project/Erotemic/xdoctest/branch/main\n.. |Codecov| image:: https://codecov.io/github/Erotemic/xdoctest/badge.svg?branch=main&service=github\n :target: https://codecov.io/github/Erotemic/xdoctest?branch=main\n.. |Pypi| image:: https://img.shields.io/pypi/v/xdoctest.svg\n :target: https://pypi.python.org/pypi/xdoctest\n.. |PypiDownloads| image:: https://img.shields.io/pypi/dm/xdoctest.svg\n :target: https://pypistats.org/packages/xdoctest\n.. |CondaDownloads| image:: https://anaconda.org/conda-forge/xdoctest/badges/downloads.svg\n :target: https://anaconda.org/conda-forge/xdoctest\n.. |ReadTheDocs| image:: https://readthedocs.org/projects/xdoctest/badge/?version=latest\n :target: https://xdoctest.readthedocs.io\n.. |GithubActions| image:: https://github.com/Erotemic/xdoctest/actions/workflows/tests.yml/badge.svg?branch=main\n :target: https://github.com/Erotemic/xdoctest/actions?query=branch%3Amain\n",
"bugtrack_url": null,
"license": "Apache 2",
"summary": "A rewrite of the builtin doctest module",
"version": "1.2.0",
"project_urls": {
"Homepage": "https://github.com/Erotemic/xdoctest"
},
"split_keywords": [
"xdoctest",
" doctest",
" test",
" docstr",
" pytest"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "58b8e4722f5e5f592a665cc8e55a334ea721c359f09574e6b987dc551a1e1f4c",
"md5": "57872d8aea4d4a8532af787fa25f39bf",
"sha256": "0f1ecf5939a687bd1fc8deefbff1743c65419cce26dff908f8b84c93fbe486bc"
},
"downloads": -1,
"filename": "xdoctest-1.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "57872d8aea4d4a8532af787fa25f39bf",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 151194,
"upload_time": "2024-08-20T13:48:18",
"upload_time_iso_8601": "2024-08-20T13:48:18.674189Z",
"url": "https://files.pythonhosted.org/packages/58/b8/e4722f5e5f592a665cc8e55a334ea721c359f09574e6b987dc551a1e1f4c/xdoctest-1.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e9a57f6dfdaf3a221e16ff79281d2a3c3e4b58989c92de8964a317feb1e6cbb5",
"md5": "1189d825c32dd10393a730f055ed720e",
"sha256": "d8cfca6d8991e488d33f756e600d35b9fdf5efd5c3a249d644efcbbbd2ed5863"
},
"downloads": -1,
"filename": "xdoctest-1.2.0.tar.gz",
"has_sig": false,
"md5_digest": "1189d825c32dd10393a730f055ed720e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 204804,
"upload_time": "2024-08-20T13:48:21",
"upload_time_iso_8601": "2024-08-20T13:48:21.076979Z",
"url": "https://files.pythonhosted.org/packages/e9/a5/7f6dfdaf3a221e16ff79281d2a3c3e4b58989c92de8964a317feb1e6cbb5/xdoctest-1.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-20 13:48:21",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Erotemic",
"github_project": "xdoctest",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"circle": true,
"requirements": [],
"tox": true,
"lcname": "xdoctest"
}