🗃 dek - the decorator-decorator 🗃
======================================================

``dek`` decorates your decorators to diminish defects and drudgery.

Writing a decorator with parameters needs three levels of function and
several opportunities for error, which ``dek`` deletes.

EXAMPLE:

Write a decorator ``print_before`` that prints a function's arguments with a
label when it executes

.. code-block:: python

    # Without dek all is sadness

    import functools

    def print_before(label='label'):
        def deferred(func):
            @functools.wraps(func)
            def wrapped(*args, **kwargs):
                print(label, args, kwargs)
                return func(*args, **kwargs)

            return wrapped

        if callable(label):
            return deferred(label)

        return deferred


    # Things go better with dek
    from dek import dek

    @dek
    def print_before(func, args, kwargs, label='debug'):
        print(label, args, kwargs)
        return func(*args, **kargs)


    # For finer control, enjoy ``dek.dek2``
    from dek import dek2

    @dek2
    def print_before(func, label='debug'):
        def wrapped(foo, bar):
            print(label, foo, bar)
            return func(foo, bar)

        return wrapped

NOTES:

All these forms are supported:

1. ``@print_before``
2. ``@print_before()``
3. ``@print_before('debug')``
4. ``@print_before(label='debug')``
5. ``@print_before('debug', verbose=True)``

`This article <https://medium.com/better-programming/how-to-write-python-decorators-that-take-parameters-b5a07d7fe393>`_ talks more about
decorators that take parameters.

For advanced problems, the PyPi library
`decorator <https://github.com/micheles/decorator/blob/master/docs/documentation.md>`_ does not do what ``dek`` does, but does pretty anything
else you could conceive of in a decorator library.

API
---

``dek.dek(decorator)``
~~~~~~~~~~~~~~~~~~~~~~

(`dek.py, 82-105 <https://github.com/rec/dek/blob/master/dek.py#L82-L105>`_)

Implement a decorator with parameters, from a simple function

The function ``decorator`` has signature
``decorator(func, args, kwargs, ...)`` where:

* ``func`` is the function being wrapped
* ``args`` are the positional arguments to ``func``
* ``kwargs`` are the  keyword arguments to ``func``
* and the remaining arguments (`...`), positional or keyword, can be
  anything you need to implement the decorator.

EXAMPLE:

.. code-block:: python

    @dek
    def print_before(func, args, kwargs, my_label='debug'):
        print(my_label, args, kwargs)
        return func(*args, **kargs)

``dek.dek2(decorator)``
~~~~~~~~~~~~~~~~~~~~~~~

(`dek.py, 107-130 <https://github.com/rec/dek/blob/master/dek.py#L107-L130>`_)

Implement a decorator with parameters, from a function that returns
a function.

The top-level function ``decorator`` has signature ``decorator(func, ...)``
where ``func`` is the function being wrapped, and it returns the
wrapper function, that has any signature needed.

EXAMPLE:

.. code-block:: python

    @dek2
    def print_before(func, label='label'):
        def wrapper(foo, bar):
            if verbose:
                print(label, foo, bar)
            return func(foo, bar)

        return wrapper

(automatically generated by `doks <https://github.com/rec/doks/>`_ on 2020-07-05T21:40:20.301083)
