Build and test your Python examples
Project description
Exemplary
A micro library for testing the Python examples in your documentation.
Installation
To install Exemplary, use pip:
pip install exemplary
Exemplary requires Python 3.6 or later.
Note: In your projects, you'll probably want to install Exemplary as a "dev" dependency. It's a tool for updating and testing your documentation.
What problem does Exemplary solve?
Exemplary solves two main problems:
- It makes sure that the examples in your documentation actually work.
- It renders the output for your examples, so that your documentation shows what your users are really going to see.
How do you use Exemplary?
TLDR:
exemplary.run(pathnames)
-- runs all the Python examples in your Markdown files.exemplary.run(pathnames, render=True)
-- runs all your Python examples, and also renders the output of any examples that start with>>>
.
(Hint: Use glob('**/*.md', recursive=True)
to run Exemplary on all the
Markdown files in your project.)
Or, to run exemplary from the command line:
python3 -m exemplary --paths "**/*.md" --render
For testing:
Put some Python sections in your markdown files.
Then, in your tests:
from glob import glob
import exemplary
def test_docs():
# Run all the examples in your markdown files:
pathnames = glob('**/*.md', recursive=True)
exemplary.run(pathnames)
This raises an exception if any of your examples fail.
For rendering:
In this context, "rendering" means, "Taking an example and showing what it looks like when you run it in Python's interactive interpreter."
So, let's say you have some markdown like this:
# How to use deque
```python
>>> from collections import deque
>>> d = deque([1, 2, 3])
>>> d.popleft()
>>> d.pop()
```
In your build script, run Exemplary with render=True
:
from glob import glob
import exemplary
def render_docs():
# Render all the examples in your markdown files:
pathnames = glob('**/*.md', recursive=True)
exemplary.run(pathnames, render=True)
Or run from a shell script:
python3 -m exemplary --paths "**/*.md" --render
Aftwards, the example will look like this:
# How to use deque
```python
>>> from collections import deque
>>> d = deque([1, 2, 3])
>>> d.popleft()
1
>>> d.pop()
3
```
When Exemplary sees an example that starts with >>>
, it runs the example in
Python's iteractive interpreter, and adds the interpreter's output to your
documentation.
(Exemplary adds an extra newline after the interpreter's output, to improve readability.)
If you run Exemplary again, it will render the example again, ignoring any output that may already appear in the example. This lets you run Exemplary multiple times as you edit your documentation.
Take care: Because Exemplary modifies your files, make sure they are committed to git before you render them.
(Or, as part of your build, copy your Markdown files to a build directory, and then run Exemplary on the copies.)
What if I have multiple examples in one markdown file?
Exemplary runs each example in the same file in the same interpreter. This allows you to break up your examples with text sections.
For example, if you have:
# My example
```python
x = "hello"
```
Now use x:
```python
>>> print(x)
```
When you render this example, Exemplary will add hello
at the end. The point
is that the second python
section can see x
, which is defined in the first
section.
If you need an example to start fresh in its own namespace, you can put a special HTML comment in the line before your example:
<!-- fresh example -->
```python
# Exmplary will run this example in a fresh environment.
import foo
foo.bar('baz')
```
When Exemplary sees the "fresh example" comment, it essentially restarts the interpreter that it's using to test and render your examples.
How can I hide some of the tests for my examples?
Exemplary looks for code sections even in HTML comments. This lets you write additional tests for your examples (to make sure they really work), without cluttering up your documentation.
For example:
# Some Example
Setup:
```python
import something
foo = do_something()
```
<!--
```python
assert foo.some_property
assert some_other_predicate(foo)
```
-->
Exemplary will run both Python sections -- the one before the comment and the one inside the comment.
This way you can:
- thoroughly test your examples.
- keep examples and tests together in the same file.
- hide the tests so that they don't detract from the documentation.
Taken to the extreme, you could treat all of your unit tests as part of your documentation, and structure them this way.
What if I don't want Exemplary to test an example?
Put the HTML comment <!-- skip example -->
on the line above each
example that you want Exemplary to ignore.
# My bad example
Exemplary will never know...
<!-- skip example -->
```python
>>> assert False
```
Exemplary won't try to test or render this example, because it's guarded by
the <!-- skip example -->
comment.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file exemplary-0.0.9.tar.gz
.
File metadata
- Download URL: exemplary-0.0.9.tar.gz
- Upload date:
- Size: 14.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.7.1 importlib_metadata/4.10.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e08e074c869b6c455f0268cdad2a7fe5477fad08bf63c346232067ab74167fae |
|
MD5 | f48aa1fe03cc5324e144241cb6dc01ca |
|
BLAKE2b-256 | 139ec63d1172b61c2f53b07401d84ef735a9198d2f6c6630ff8c167ec6df2488 |