Adding Examples
eXamples makes it easy to add examples to any existing function call. It also provides flexibility in where you define, and you utilize examples.
Decorator Usage
The most straight forward way to add examples is via the @example
decorator. A decorator would be added above a function definition for each example
you wish to add. This is the recommended approach for simple APIs and/or APIs with only a few examples.
from examples import example @example(1, number_2=1) @example(1, 2, _example_returns=3) def add(number_1: int, number_2: int): return number_1 + number_2
Every positional and keyword argument passed into the decorator represents the same passed into the function.
Except, for the following magic parameters (all prefixed with _example_
):
- _example_returns: The exact result you expect the example to return.
- _example_raises: An exception you expect the example to raise (can't be combined with above)
- _example_doc_string: If True example is added to the functions docstring.
See the API reference documentation for a complete definition.
Tip
Examples save the bare minimum information when attached to a function, adding very low overhead. The next approach does provide a no-overhead alternative, but generally overhead shouldn't need to be the primary consideration. You can also combine the two approaches as needed, both for the same or different functions.
Separate Example Registration
Alternatively, if you have a lot of examples, you can store the examples in a separate module. This can allow you to harness the power of eXamples while keeping your implementation code clean and uncluttered. As long as you test your examples, you still won't have to worry about them ever becoming out of sync with your implementation code.
To do this, you can utilize the examples.add_example_to
function, to add examples to a function:
# implementation.py def multiply(number_1: int, number_2: int): return number_1 * number_2
# implementation_examples.py from examples import add_examples_to from .implementation import multiply multiply_example = add_example_to(multiply) multiply_example(2, 2, _example_returns=4) multiply_example(1, 1) # OR add_example_to(multiply)(2, 2, _example_returns=4) add_example_to(multiply)(1, 1) # Optionally, you can even name and make these examples importable! multiply_2_by_2 = add_example_to(multiply)(2, 2, _example_returns=4)
add_example_to
returns a function that takes the same arguments as the @example
decorator used above.
See the API reference documentation for a complete definition.
Warning
When using this approach, it's important to remember that examples won't get added if the example module is never imported.
This can be overcome with documentation and/or strategically importing the examples elsewhere in your code, such as __init__.py
.
On the other hand, this fact can be utilized to incur the overhead of examples only when running in a development environment.
Custom Registry
By default eXamples
creates example registries on-demand per a module that contains functions with examples.
If you need more fine-tuned control over the registration or usage of examples, you can create and reuse your own example registry.
from examples import Examples my_examples = Examples() @my_examples.example(argument_1="value") def my_function(argument_1): return argument_1