decoguard logo

Welcome to decoguard

A lightweight validation layer for your decorators with clear, reliable error reporting


Overview

decoguard is a Python library designed for robust validation of decorated functions.
It provides a clean and structured way to ensure that functions using your decorators comply with specific conditions you have defined.

As of the time of writing, decoguard is the only library known to provide these features.

Note:
This library uses advanced Python concepts, applied in sophisticated ways. These include decorators, introspection, and type hints.

Before reading this documentation or using the library, make sure you are familiar with these concepts, as the documentation assumes prior knowledge.

The core idea is to use meta-decorators on your decorators to enforce and validate their correct usage.

Without decoguard, doing this manually in native Python often results in:

  • Complex and error-prone introspection logic
  • Repetitive validation code scattered across your decorators
  • Poor error reporting caused by stack manipulation or decorator wrapping

decoguard solves these problems by offering a simple and expressive system for decorating your decorators.
It helps you enforce usage rules and provides clear, developer-friendly error messages when violations occur.

Features

  • Decorator and Decorator Factory Support
    Works seamlessly with both regular decorators and decorator factories (decorators that accept arguments).

  • Meta-Decorators for Validation
    Use simple meta-decorators to wrap your decorators with validation logic. No need for messy introspection or boilerplate.

  • Robust Function Validation
    Enforce specific rules on how functions are decorated, such as checking argument types, presence of required attributes, or naming conventions.

  • Centralized Validation Logic
    Keep your validation rules clean and maintainable by moving them out of individual decorators into a centralized, reusable layer.

  • Clear and Informative Errors
    When validation fails, decoguard raises precise, developer-friendly exceptions, no more obscure tracebacks or silent failures.

  • Drop-In Simplicity
    Add validation to existing decorators with minimal changes to your codebase. Designed to integrate smoothly with existing Python code and decorator patterns.

Library architecture

decoguard is divided into 3 differents module:

  • decoguard.decorators This module provides the meta-decorators required to enable validation logic on your custom decorators. Use these decorators to wrap your own, thereby integrating decoguard's validation system seamlessly.

  • decoguard.validators This module provides a variety of validation functions, which are internally implemented as decorator factories. While they are technically decorators, they are not meant to be applied directly to your functions. Instead, these validators should be used as arguments inside a meta-decorator from decoguard.decorators. This allows you to specify which validation logic should be applied when decorating your functions. Use these to define fine-grained validation rules that are executed as part of the decorator pipeline.

  • decoguard.asserts This module includes various assertion utilities used internally by decoguard. These functions are also exposed for general-purpose use, should you need standalone validation logic outside of the decorator context. Think of this as a utility module for reusable assertion checks.

Getting started

Require at least Python 3.8. Tested and working up to Python 3.13.

Install decoguard from PyPi using pip:

pip install decoguard

Once done, you can start by reviewing the following minimal examples to gain a quick understanding of the library's core capabilities. Additionally, feel free to explore other sections of the documentation to discover the full range of included features.

Guard your decorators

from decoguard.decorators import validate_decorated
from decoguard.validators import require_params

@validate_decorated(require_params("x", "y"))
def my_decorator(func): return func

@my_decorator
def correct_usage(x, y): pass

@my_decorator
def bad_usage(x): pass # Will raise an DecoratorUsageValidationError

Let’s break down what’s happening here. As mentioned earlier, you need both decoguard.decorators and decoguard.validators in order to set up the full validation pipeline.

In this case, we want to ensure that functions using @my_decorator are doing so correctly. To indicate that we want those validations, we decorate @my_decorator with @validate_decorated. Then, we specify that any function using @my_decorator must include at least x and y parameters in its signature by passing require_params("x", "y") to @validate_decorated.

Below, we have two examples of how @my_decorator is used. The first one, correct_usage(), respects the validation we applied to the decorator. The function includes all the required parameters (x and y), so it passes validation and simply executes whatever logic @my_decorator provides.

However, the second usage, bad_usage(), does not satisfy the conditions we defined earlier. As such, this incorrect usage will raise the following error:

Exception has occurred: DecoratorUsageValidationError
Function 'bad_usage()' is using '@my_decorator' decorator which requires the function to have the following missing parameters: y

And just like that, even without calling the function, anyone misusing your decorator will be prevented from doing so and will receive a clear explanation of what’s wrong and how to fix it.

Guard your decorator factories

decoguard works exactly the same for decorator factories, as you can see in the following snippet.

@validate_decorated(require_params("x", "y"))
def my_decorator_factory(param):
    def inner(func):
        return func
    return inner
Note:
To guard the arguments sent to your decorator factories, you may use other Python libraries whose purpose is to perform validation directly on functions, as this is not the goal of this library. Indeed, the entire purpose here is to control the functions that use your decorator, not to validate the decorator itself.