Install & Compatibility
Where this runs
tested against v3.1.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.034s · 17.8MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 1.6s · import 0.034s · 18MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Scanner
✓ from venusian import Scanner
Used to initiate the deferred decorator action scan.
attach
✓ venusian.attach(wrapped, callback)
Attaches a callback to a decorated object for later processing during a scan.
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()}")
Debug
Known issues
breakingVersions 3.0.0 and 2.0.0 dropped support for Python 2.7, 3.3, and 3.4. Projects on these older Python versions must remain on `venusian < 2.0.0` or `venusian < 3.0.0` respectively (for Python 3.x).fixUpgrade to Python 3.5+ to use `venusian >= 3.0.0`.
affects: < 3.0.0
breakingVersion 3.1.0 removed support for Python 3.5 and 3.6. Users on these Python versions should use `venusian < 3.1.0` if they cannot upgrade their Python interpreter.fixUpgrade to Python 3.7+ to use `venusian >= 3.1.0`.
affects: < 3.1.0
gotchaBy default, `venusian.Scanner.scan()` will propagate `ImportError` exceptions encountered while trying to import modules. To suppress or handle these errors, provide an `onerror` callback function to the `scan()` method.fixPass an `onerror` callable to `scanner.scan(..., onerror=my_error_handler_func)` to customize error handling.
affects: All versions (since 1.0)
gotchaVenusian decorators attached to a class are not implicitly inherited by subclasses. Each class declaration should have its own local set of callbacks; callbacks added via decorations are not inherited from a superclass.fixIf decorator inheritance is desired, it must be explicitly handled within your custom decorator logic or scan phase, for example, by re-attaching or copying callbacks from the superclass during the scan.
affects: All versions (fixed in 0.4 / 1.0 but design decision)
Upgrade
Version history
3.1.1latest on PyPI · released Dec 2, 2024
Audit
Dependencies
No dependency data recorded yet.