decorator

raw JSON →
5.2.1 verified Tue May 12 auth: no python install: verified quickstart: verified

A Python module that simplifies the creation of decorators, ensuring they preserve the original function's signature. Current version: 5.2.1, released on February 24, 2025. Maintained by Michele Simionato. Requires Python 3.8 or higher.

pip install decorator
error ModuleNotFoundError: No module named 'decorator'
cause The 'decorator' library is not installed in your Python environment.
fix
Install the library using pip: pip install decorator
error TypeError: 'decorator' object is not callable
cause This error often occurs when you attempt to use the 'decorator' module itself or an object returned by it directly as a decorator without properly applying the `decorate` function to wrap your function, or when a decorator function is not correctly structured to return a callable.
fix
Ensure you are using decorator.decorate correctly to create the decorator, or that your custom decorator function returns a callable. For example, to create a simple decorator preserving signature: from decorator import decorator @decorator def my_decorator(func, *args, **kwargs): print('Before function call') result = func(*args, **kwargs) print('After function call') return result @my_decorator def my_function(): return 'Hello'
error SyntaxError: invalid syntax
cause This usually arises when the expression immediately following the `@` symbol in a decorator definition is not a simple dotted name or a function call, which are the only forms allowed by Python's grammar for decorators.
fix
Ensure that the expression after @ is a valid callable (e.g., a function name, module.function_name, or a function call that returns a callable). Complex expressions like @(lambda f: f) or chained calls like @f()() are not allowed directly. You might need to assign the result of a complex expression to a variable first, then use that variable as the decorator. The decorator library's decorate function is designed to handle more complex programmatic decorator creation, but the @ syntax itself has strict rules. Example of incorrect vs. correct usage:
# Incorrect
# @(lambda f: f)
# def my_func(): pass

# Correct (assign lambda to a name first)
identity_decorator = lambda f: f
@identity_decorator
def my_func():
    pass

# If using 'decorator' library to build a decorator factory:
from decorator import decorator

def my_decorator_factory(arg):
    @decorator
    def my_actual_decorator(func, *args, **kwargs):
        print(f'Decorator arg: {arg}')
        return func(*args, **kwargs)
    return my_actual_decorator

@my_decorator_factory('test')
def another_func():
    return 'World'
breaking Importing the 'decorator' function as 'import decorator' is incorrect and will lead to an ImportError.
fix Use 'from decorator import decorator' to correctly import the function.
gotcha The 'decorator' module requires Python 3.8 or higher. Using it with earlier versions will result in a VersionError.
fix Ensure your Python environment is version 3.8 or higher before using the 'decorator' module.
gotcha Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager.
fix It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
python os / libc status wheel install import disk
3.10 alpine (musl) - - 0.01s 17.8M
3.10 slim (glibc) - - 0.01s 18M
3.11 alpine (musl) - - 0.03s 19.6M
3.11 slim (glibc) - - 0.02s 20M
3.12 alpine (musl) - - 0.04s 11.5M
3.12 slim (glibc) - - 0.04s 12M
3.13 alpine (musl) - - 0.04s 11.2M
3.13 slim (glibc) - - 0.04s 12M
3.9 alpine (musl) - - 0.01s 17.3M
3.9 slim (glibc) - - 0.01s 18M

An example demonstrating how to define and use a decorator with the 'decorator' module.

import time
import logging
from decorator import decorator

@decorator
def warn_slow(func, timelimit=60, *args, **kw):
    t0 = time.time()
    result = func(*args, **kw)
    dt = time.time() - t0
    if dt > timelimit:
        logging.warning('%s took %d seconds', func.__name__, dt)
    else:
        logging.info('%s took %d seconds', func.__name__, dt)
    return result

@warn_slow  # warn if it takes more than 1 minute
def preprocess_input_files(inputdir, tempdir):
    # Function implementation here
    pass

@warn_slow(timelimit=600)  # warn if it takes more than 10 minutes
def run_calculation(tempdir, outdir):
    # Function implementation here
    pass

# Usage
preprocess_input_files('/path/to/input', '/path/to/temp')
run_calculation('/path/to/temp', '/path/to/output')