Skip to content

Module examples

View Source
from examples.api import (

    add_example_to,

    example,

    get_examples,

    test_all_examples,

    test_examples,

    verify_all_signatures,

    verify_and_test_all_examples,

    verify_and_test_examples,

    verify_signatures,

)

from examples.registry import Examples

__version__ = "0.1.2"

__all__ = [

    "__version__",

    "add_example_to",

    "example",

    "example_returns",

    "get_examples",

    "verify_signatures",

    "test_examples",

    "verify_and_test_examples",

    "verify_all_signatures",

    "test_all_examples",

    "verify_and_test_all_examples",

    "Examples",

]

Sub-modules

Variables

__version__

Functions

add_example_to
def (
    function: Callable
) -> Callable

Returns a function that when called will add an example to the provide function.

This can be re-used multiple times to add multiple examples:

    add_example = add_example_to(my_sum_function)
    add_example(1, 2)
    add_example(2, 3, _example_returns=5)

Or, can be used once for a single example:

    add_example_to(my_sum_function)(1, 1, _example_returns=5)

The returned function follows the same signature as the @example decorator except it returns the produced examples, allowing you to expose it:

    add_example = add_example_to(my_sum_function)(1, 1)
View Source
def add_example_to(function: Callable) -> Callable:

    """Returns a function that when called will add an example to the provide function.

    This can be re-used multiple times to add multiple examples:

            add_example = add_example_to(my_sum_function)

            add_example(1, 2)

            add_example(2, 3, _example_returns=5)

    Or, can be used once for a single example:

            add_example_to(my_sum_function)(1, 1, _example_returns=5)

    The returned function follows the same signature as the @example decorator except

    it returns the produced examples, allowing you to expose it:

            add_example = add_example_to(my_sum_function)(1, 1)

    """

    def example_factory(

        *args,

        _example_returns: Any = NotDefined,

        _example_raises: Any = None,

        _example_doc_string: bool = True,

        **kwargs,

    ) -> CallableExample:

        example(

            *args,

            _example_returns=_example_returns,

            _example_raises=_example_raises,

            _example_doc_string=_example_doc_string,

            **kwargs,

        )(function)

        return get_examples(function)[-1]

    return example_factory
example
def (
    *args,
    _example_returns: Any = <class 'examples.example_objects.NotDefined'>,
    _example_raises: Any = None,
    _example_doc_string: bool = True,
    **kwargs
) -> Callable

A decorator that adds an example to the decorated function.

Everything passed in to the example will be passed into the wrapped function in the unchanged when testing or using the example.

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 doc string.
View Source
def example(

    *args,

    _example_returns: Any = NotDefined,

    _example_raises: Any = None,

    _example_doc_string: bool = True,

    **kwargs,

) -> Callable:

    """A decorator that adds an example to the decorated function.

    Everything passed in to the example will be passed into the wrapped function in the

    unchanged when testing or using the example.

    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 doc string.

    """

    def wrap_example(function: Callable) -> Callable:

        attached_module_name = function.__module__

        if attached_module_name not in registry.module_registry:

            registry.module_registry[attached_module_name] = registry.Examples()

        module_registry = registry.module_registry[attached_module_name]

        return module_registry.example(

            *args, _example_returns=_example_returns, _example_raises=_example_raises, **kwargs

        )(function)

    return wrap_example
get_examples
def (
    item: Any
) -> List[examples.example_objects.CallableExample]

Returns all examples associated with the provided item. Provided item should be of type function, module, or module name.

View Source
@singledispatch

def get_examples(item: Any) -> List[CallableExample]:

    """Returns all examples associated with the provided item.

       Provided item should be of type function, module, or module name.

    """

    raise NotImplementedError(f"Currently examples can not be attached to {type(item)}.")
test_all_examples
def (
    verify_return_type: bool = False
) -> None

Tests all examples against their associated functions.

View Source
def test_all_examples(verify_return_type: bool = False) -> None:

    """Tests all examples against their associated functions."""

    for module_name in registry.module_registry:

        test_examples(module_name, verify_return_type=verify_return_type)
test_examples
def (
    item: Any,
    verify_return_type: bool = True
) -> None

Run all examples verifying they work as defined against the associated function. Provided item should be of type function, module, or module name.

  • verify_return_type: If True all examples will have have their return value types checked against their associated functions type annotations.
View Source
@singledispatch

def test_examples(item: Any, verify_return_type: bool = True) -> None:

    """Run all examples verifying they work as defined against the associated function.

       Provided item should be of type function, module, or module name.

       - *verify_return_type*: If `True` all examples will have have their return value types

         checked against their associated functions type annotations.

    """

    raise NotImplementedError(f"Currently examples can not be attached to {type(item)}.")
verify_all_signatures
def (
    verify_types: bool = False
) -> None

Verify all examples against their associated functions signatures.

View Source
def verify_all_signatures(verify_types: bool = False) -> None:

    """Verify all examples against their associated functions signatures."""

    for module_name in registry.module_registry:

        verify_signatures(module_name, verify_types=verify_types)
verify_and_test_all_examples
def (
    verify_types: bool = False
) -> None

Tests all examples while verifying them against their associated functions signatures.

View Source
def verify_and_test_all_examples(verify_types: bool = False) -> None:

    """Tests all examples while verifying them against their associated functions signatures."""

    for module_name in registry.module_registry:

        verify_and_test_examples(module_name, verify_types=verify_types)
verify_and_test_examples
def (
    item: Any,
    verify_return_type: bool = True
) -> None

Verifies the signature of all examples associated with the provided item then runs all examples verifying they work as defined. Provided item should be of type function, module, or module name.

  • verify_types: If True all examples will have have their types checked against their associated functions type annotations.
View Source
@singledispatch

def verify_and_test_examples(item: Any, verify_return_type: bool = True) -> None:

    """Verifies the signature of all examples associated with the provided item then

       runs all examples verifying they work as defined.

       Provided item should be of type function, module, or module name.

       - *verify_types*: If `True` all examples will have have their types checked against

         their associated functions type annotations.

    """

    raise NotImplementedError(f"Currently examples can not be attached to {type(item)}.")
verify_signatures
def (
    item: Any,
    verify_types: bool = True
) -> None

Verifies the signature of all examples associated with the provided item. Provided item should be of type function, module, or module name.

  • verify_types: If True all examples will have have their types checked against their associated functions type annotations.
View Source
@singledispatch

def verify_signatures(item: Any, verify_types: bool = True) -> None:

    """Verifies the signature of all examples associated with the provided item.

       Provided item should be of type function, module, or module name.

       - *verify_types*: If `True` all examples will have have their types checked against

         their associated functions type annotations.

    """

    raise NotImplementedError(f"Currently examples can not be attached to {type(item)}.")

Classes

Examples
class (
    add_to_doc_strings: bool = True
)

An object that holds a set of examples as they are registered.

View Source
class Examples:

    """An object that holds a set of examples as they are registered."""

    __slots__ = ("examples", "add_to_doc_strings", "_callable_mapping")

    def __init__(self, add_to_doc_strings: bool = True):

        self.examples: List[CallableExample] = []

        self.add_to_doc_strings: bool = add_to_doc_strings

        self._callable_mapping: Dict[Callable, list] = {}

    def _add_to_doc_string(self, function: Callable, example: CallableExample) -> None:

        if function.__doc__ is None:

            function.__doc__ = ""

        indent: int = 4

        for line in reversed(function.__doc__.split("\n")):

            if line.strip():

                indent = len(line) - len(line.lstrip(" "))

        indent_spaces: str = " " * indent

        if "Examples:" not in function.__doc__:

            function.__doc__ += f"\n\n{indent_spaces}Examples:\n\n"

        indented_example = str(example).replace("\n", f"\n{indent_spaces}        ")

        function.__doc__ += f"\n\n{indent_spaces}        {indented_example}"

        function.__doc__ += "\n-------"

    def example(

        self,

        *args,

        _example_returns: Any = NotDefined,

        _example_raises: Any = None,

        _example_doc_string: Optional[bool] = None,

        **kwargs,

    ) -> Callable:

        def example_wrapper(function):

            new_example = CallableExample(

                function, returns=_example_returns, raises=_example_raises, args=args, kwargs=kwargs

            )

            self._callable_mapping.setdefault(function, []).append(new_example)

            if _example_doc_string or (_example_doc_string is None and self.add_to_doc_strings):

                self._add_to_doc_string(function, new_example)

            self.examples.append(new_example)

            return function

        return example_wrapper

    def verify_signatures(self, verify_types: bool = True) -> None:

        for example in self.examples:

            example.verify_signature(verify_types=verify_types)

    def test_examples(self, verify_return_type: bool = True) -> None:

        for example in self.examples:

            example.test(verify_return_type=verify_return_type)

    def verify_and_test_examples(self, verify_types: bool = True) -> None:

        for example in self.examples:

            example.verify_and_test(verify_types=verify_types)

    def get(self, function: Callable) -> List[CallableExample]:

        """Returns back any examples registered for a specific function"""

        return self._callable_mapping.get(function, [])