Skip to main content

Decorator utility that operates on black magic

Project description

Build Status Coverage Latest Version Downloads License

Metaprogramming modules that operate on black magic!

Currently there is only one module available. However, I am all open for cool ideas.


This is intended to become a more modern and flexible replacement for the the well known decorator module. This module benefits an API for more flexible usage. The behaviour of the decorator module can easily be duplicated.

For those who don’t know the decorator module: It can be used to create wrappers for functions that look identical to the original - a common task when replacing functions via decorators.

Furthermore, this module makes it possible to create wrappers with modified signatures. Currently, the only specialized function that is explicitly dedicated to this purpose is partial. If you are interested in doing more complex modifications you can pass a dynamically created Signature to wraps. If you make something useful, please consider contributing your functionality to this module.


wraps can be used similarly to the standard functools.wraps function. However, it returns a real function, i.e. something that will have a useful signature when being inspected with help() or by other metaprogramming tools. Furthermore, it knows how to copy the signature exactly, even remembering object identity of default arguments and annotations:

>>> from black_magic.decorator import wraps

>>> def real(a=[])
...     return a

>>> @wraps(real)
... def fake(*args, **kwargs):
...     return args

>>> fake()[0] is real()
>>> fake(a=1)

If you want to get real crazy you can even use ast.expr’s:

>>> import ast
>>> fake = wraps(real)(ast.Num(n=1))
>>> fake(0)

WARNING: Do not use wraps with functools.partial! It won’t work (if using any keyword bindings).


This is similar to the functools.partial function.

>>> from black_magic.decorator import partial

>>> def real(arg):
...     print(arg)
>>> partial(real, arg=0)()

There are some differences, though:

  • this function returns a function object which looks like the input function, except for the modified parameters.

  • all overwritten parameters are completely removed from the signature. In functools.partial this is true only for arguments bound by position.

  • the **kwargs are stripped first, then *args

    >>> partial(lambda a,b,c: (a,b,c), 2, a=1)(3)
    (1, 2, 3)
  • by leaving the func argument empty partial can act as decorator:

    >>> @partial(None, bar=0)
    ... def foo(bar):
    ...     print(bar)
    >>> foo()


This is the canonic utility to create decorators:

>>> from black_magic.decorator import decorator

>>> @decorator
... def plus_one(fn):
...     def fake(*args, **kwargs):
...         return 1 + fn(*args, **kwargs)
...     return fake

>>> @plus_one
... def mul_plus_one(a, b):
...     return a * b

>>> mul_plus_one(2, 3)


flatorator imitates the functionality of the well known decorator module.

>>> from black_magic.decorator import flatorator

>>> @flatorator
... def times_two(fn, *args, **kwargs):
...     return 2 * fn(*args, **kwargs)

>>> @times_two
... def add_times_two(a, b):
...     return a + b

>>> add_times_two(1, 2)

Under the hood

Q: This uses ugly str concat and eval code, right?

A: No, it uses ugly abstract syntax tree code to do its dynamic code generation.


This module has been tested to work on python{2.6, 2.7, 3.2, 3.3} and PyPy1.9 using Travis CI.


To the extent possible under law, Thomas Gläßle has waived all copyright and related or neighboring rights to black-magic. This work is published from: Germany.

To the extent possible under law, the person who associated CC0 with black-magic has waived all copyright and related or neighboring rights to black-magic.

You should have received a copy of the CC0 legalcode along with this work. If not, see



  • fix functools.update_wrapper emulation in black_magic.decorator.wraps()


  • add black_magic.decorator.partial


  • support any callable to be passed to ASTorator.decorate
  • convert README to .rst

Project details

Release history Release notifications

History Node


History Node


History Node


History Node


History Node


History Node


This version
History Node


History Node


History Node


History Node


History Node


History Node


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Filename, size & hash SHA256 hash help File type Python version Upload date
black-magic-0.0.6.tar.gz (13.4 kB) Copy SHA256 hash SHA256 Source None Feb 24, 2014

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging CloudAMQP CloudAMQP RabbitMQ AWS AWS Cloud computing Fastly Fastly CDN DigiCert DigiCert EV certificate StatusPage StatusPage Status page