Venusian

3.1.1 · active · verified Fri Apr 10

Venusian is a Python library that enables framework authors to defer actions typically performed by decorators at import time. Instead, these actions are executed during a separate 'scan' phase. This allows for more flexible configuration and improved testability of decorated code. The library is actively maintained, with the current version being 3.1.1, and supports CPython and PyPy versions 3.7 and above.

Warnings

Install

Imports

Quickstart

This example demonstrates how to create a custom decorator that uses `venusian.attach` to defer its actions. A `venusian.Scanner` is then used to explicitly trigger these deferred actions, collecting metadata about the decorated functions into a custom registry.

import venusian

# Define a custom decorator that uses venusian.attach
class mydecorator:
    def __init__(self, category='default'):
        self.category = category

    def __call__(self, wrapped):
        def callback(scanner, name, obj):
            # This function is called during the scan phase
            print(f"Scanning {obj.__name__} in category '{self.category}'")
            # You might register `obj` or `name` in a registry here
            scanner.registry.append((name, obj, self.category))
        venusian.attach(wrapped, callback, category=self.category)
        return wrapped # Return the original object, untouched at import time

# Define some functions to be decorated
@mydecorator(category='views')
def my_view():
    return "Hello, Venusian!"

@mydecorator(category='api')
def my_api_endpoint():
    return {"data": "from api"}

# Create a scanner instance and a custom registry
scanner = venusian.Scanner(registry=[])

# Scan the current module (or a specific package/module)
# The callbacks attached via mydecorator will now be executed
scanner.scan(__name__)

# Access the collected information from the registry
print("\n--- Collected Registry Data ---")
for name, obj, category in scanner.registry:
    print(f"Name: {name}, Object: {obj.__name__}, Category: {category}")

# Verify that original functions are callable
print(f"\nDirect call to my_view: {my_view()}")

view raw JSON →