decorator
Signature-preserving decorator library for Python, making it easy to write correct function decorators and decorator factories
Repository Health
Technical Analysis
decorator is a small, long-lived Python library that makes it easy to write signature-preserving function decorators — decorators whose wrapped function keeps the original function’s name, docstring, and argument signature, instead of collapsing to a generic (*args, **kwargs) signature as with plain functools.wraps. It also ships an implementation of multiple dispatch and other decorator-authoring utilities.
Originally written by Michele Simionato in 2005, decorator predates and inspired parts of the standard library’s own decorator tooling, and remains widely used as a dependency of libraries (such as IPython and NetworkX) that need well-behaved decorators whose introspection (via help(), inspect.signature(), or IDEs) matches the original function rather than a generic wrapper.
What You Get
- A
@decoratormeta-decorator that converts a simplecaller(func, *args, **kwargs)function into a fully signature-preserving decorator - A lower-level
decorate(func, caller)function for cases where you need to apply the pattern without the@decoratorsyntax - Support for decorating generator functions, coroutine functions (
async def), and context managers correctly, matching their original calling convention - A multiple-dispatch implementation (
dispatch_on) for defining functions whose implementation is chosen based on the runtime type of one or more arguments - Full type stub (
.pyi) support and apy.typedmarker for static type checkers
Common Use Cases
- Writing decorators for logging, caching, retrying, or validation where the decorated function must still expose its true signature to
inspect,help(), or IDE autocomplete - Building decorator factories (parameterized decorators) without hand-rolling the nested-closure boilerplate
functools.wrapsalone doesn’t solve - Adding correct decoration support for
async deffunctions and generators, which naive decorators often break - Implementing type-based multiple dispatch for functions that need different behavior per argument type
Under The Hood
Architecture - The core mechanism parses the wrapped function’s signature via inspect.signature/FullArgSpec, then dynamically compiles a new function definition as source text (via a regex-matched def template) whose signature textually mirrors the original, and exec()s it so the resulting wrapper is indistinguishable from the original at the signature level while delegating actual execution to the user-supplied caller(func, *args, **kwargs). This source-generation approach (rather than pure *args/**kwargs proxying) is what lets tools like inspect.signature(), help(), and IDE autocomplete see the real parameter names and defaults. Tech Stack - Pure Python 3 standard library only (inspect, functools, itertools, operator, re, contextlib), with a Python 3.14+ branch that additionally uses the new annotationlib module; packaged as src/decorator with pyproject.toml and shipped with .pyi type stubs. Code Quality - tests/test.py and tests/documentation.py cover the documentation examples as executable tests (a docs-as-tests approach used consistently across the ~20-year history of the project), exercising generator/coroutine decoration, multiple dispatch, and signature preservation edge cases; the project has been actively maintained with 907 GitHub stars and current activity as of this analysis. API Design - The primary entry point is a single @decorator annotation applied to a plain caller(func, *args, **kwargs) function, which is a strictly smaller mental model than writing a decorator by hand with nested closures — most usage is a one-line change from a naive decorator to a signature-correct one.
Used by 3 apps in this directory
argilla
AI Development · Data Engineering
Collaborate on high-quality AI training data with a self-hosted annotation platform built for LLMs, NLP, and multimodal models.
Odoo
ERP · CRM · Productivity
The open source ERP platform that integrates CRM, accounting, inventory, manufacturing, and 60+ business apps into one seamlessly connected suite.
TDengine
Databases
A high-performance, open-source time-series database built in C for IoT, connected vehicles, and industrial monitoring workloads, with built-in stream processing, caching, and data subscription.