⚠️ DEPRECATED — Use simplibs instead
This package is deprecated and no longer maintained.
Please migrate to: simplibs-signature
This older version remains available for backward compatibility, but new projects should use the simplibs ecosystem instead.
simple-signature
Lightweight utilities for dynamic and declarative function signature manipulation. Inspect, copy, assemble, and apply
inspect.Signatureobjects — with a clean API and no magic.
@signature_from(extra_param, base_func_first=False)
def my_func(*args, **kwargs):
...
@signature_copy(MyClass.__init__, return_type=MyClass)
def create(*args, **kwargs):
...
Contents
- Installation
- Quick start
- Decorators
- Signature operations
- Parameter creators
- SignatureCreator
- Constants
- About the Simple ecosystem
Installation
pip install simple-signature
from simple_signature import signature_from, signature_copy
Note: This library automatically installs simple-exception as a core dependency.
Quick start
Python's inspect.Signature is powerful — but working with it directly is
verbose. simple-signature gives you a small set of focused tools for the
most common scenarios: copying a signature from one function to another,
assembling a signature from multiple sources, and applying it as a decorator.
Copy a signature from an existing function
The most common use case — take the signature from one callable and apply it
to another. signature_copy always normalises the result: removes self/cls
and appends **kwargs:
from simple_signature import signature_copy
class MyClass:
def __init__(self, name: str, value: int = 0):
...
@signature_copy(MyClass.__init__, return_type=MyClass)
def create(*args, **kwargs):
return MyClass(*args, **kwargs)
# create now reports: (name: str, value: int = 0, **kwargs) -> MyClass
Assemble a signature from multiple sources
signature_from turns the decorated function itself into the base — then
merges in additional parameters from adds:
from simple_signature import signature_from, create_keyword_parameter
extra = create_keyword_parameter("timeout", annotation=int, default=30)
@signature_from(extra)
def connect(host: str, port: int):
...
# connect now reports: (host: str, port: int, *, timeout: int = 30)
Decorators
The two main decorators — the primary public interface of the library.
signature_copy
Copies and normalises a signature from an existing callable onto the decorated
function. Always removes self/cls and appends **kwargs.
@signature_copy(base_func, return_type=MyClass)
def my_func(*args, **kwargs):
...
| Parameter | Type | Description |
|---|---|---|
base_func |
Callable |
The function or method whose signature is copied |
return_type |
type | None | UNSET |
Override the return annotation. UNSET preserves the original, None removes it |
signature_from
Assembles a new signature from the decorated function and any additional
parameter sources. The decorated function becomes base_func.
@signature_from(param_or_func, ..., base_func_first=True)
def my_func(*args, **kwargs):
...
| Parameter | Type | Description |
|---|---|---|
*adds |
inspect.Parameter | Callable |
Parameters or callables to merge into the signature |
excluded_names |
tuple[str, ...] |
Parameter names to exclude |
return_type |
type | Callable | None | UNSET |
Return annotation. If UNSET and base_func has one, it is inherited |
base_func_first |
bool |
If True, decorated function's parameters come first (default: True) |
accept_double |
bool |
If True, duplicate parameter names are silently skipped (default: True) |
Signature operations
Lower-level tools for working with inspect.Signature objects directly.
get_signature
Safely retrieves an inspect.Signature from any callable. Converts Python's
raw ValueError and TypeError into structured SignatureBuildError instances:
from simple_signature import get_signature
sig = get_signature(my_func)
set_signature
Assigns an inspect.Signature directly to a function via __signature__.
Returns the original function — allows inline assignment:
from simple_signature import set_signature
set_signature(my_func, my_signature)
create_copy_signature
Creates a modified copy of a signature from a callable — the lower-level
counterpart to signature_copy. Use when you need full control over
normalisation or want the inspect.Signature object directly rather than
a decorator:
from simple_signature import create_copy_signature, UNSET
sig = create_copy_signature(
MyClass.__init__,
return_type = MyClass, # override return annotation
normalize = True, # remove self/cls, append **kwargs (default: True)
)
apply_signature_to_wraps
Creates a new wrapper around a function and assigns a custom signature to it. The building block for decorators — use when you need a new callable, not just a modified one:
from simple_signature import apply_signature_to_wraps
wrapped = apply_signature_to_wraps(my_func, my_signature)
create_signature_decorator
Produces a reusable decorator from an inspect.Signature. Use when the same
signature needs to be applied to multiple functions:
from simple_signature import create_signature_decorator
decorator = create_signature_decorator(my_signature)
@decorator
def func_a(*args, **kwargs): ...
@decorator
def func_b(*args, **kwargs): ...
Parameter creators
Convenience factories for building inspect.Parameter instances without
touching the inspect module directly.
create_positional_parameter
from simple_signature import create_positional_parameter
param = create_positional_parameter("name", annotation=str)
param = create_positional_parameter("x", annotation=int, default=0, positional_only=True)
create_keyword_parameter
from simple_signature import create_keyword_parameter
param = create_keyword_parameter("timeout", annotation=int, default=30)
Both factories accept:
| Parameter | Type | Description |
|---|---|---|
name |
str |
Parameter name |
annotation |
type |
Type annotation — omit for no annotation |
default |
Any |
Default value — omit for no default |
positional_only |
bool |
create_positional_parameter only — produces POSITIONAL_ONLY if True |
SignatureCreator
The engine behind signature_from and create_signature — assembles an
inspect.Signature from any combination of callables and inspect.Parameter
instances. Use it directly when you need the builder instance itself, or reach
for create_signature for the one-liner functional form:
from simple_signature import SignatureCreator, create_signature
# Builder form — access the instance if needed
creator = SignatureCreator(extra_param, base_func=my_func)
sig = creator.signature
# Functional form — when only the signature is needed
sig = create_signature(extra_param, base_func=my_func)
| Parameter | Type | Description |
|---|---|---|
*adds |
inspect.Parameter | Callable |
Parameters or callables to merge in |
excluded_names |
tuple[str, ...] |
Parameter names to exclude |
return_type |
type | Callable | None | UNSET |
Return annotation source — type, callable, None, or UNSET |
base_func |
Callable | None |
Base function — its parameters and return type are the starting point |
base_func_first |
bool |
If True, base_func parameters come first (default: True) |
accept_double |
bool |
If True, duplicate names are silently skipped (default: True) |
return_type priority
| Value | Behaviour |
|---|---|
| a type | Used directly as the return annotation |
| a callable | Its return annotation is extracted and used |
None |
Return annotation is removed |
UNSET |
Inherited from base_func if available, otherwise empty |
Constants
Pre-built inspect.Parameter instances and a frozenset of default exclusions —
ready to use without touching the inspect module:
from simple_signature import ARGS, KWARGS, EXCLUDED
# ARGS — *args (VAR_POSITIONAL)
# KWARGS — **kwargs (VAR_KEYWORD)
# EXCLUDED — frozenset({"self", "cls"})
EXCLUDED is the default exclusion set used by ParameterCollector and
create_copy_signature — self and cls are always skipped automatically.
About the Simple ecosystem
simple-signature is part of the Simple ecosystem — a collection of small,
self-contained Python libraries, each solving exactly one thing.
The Simple ecosystem is built on simple-exception — a structured exception
that communicates with the developer: describing not just what went wrong, but
pointing towards a fix. All errors raised by simple-signature are structured
SimpleException subclasses, catchable as SignatureError or the more
specific SignatureParameterError and SignatureBuildError:
from simple_signature import SignatureError, SignatureBuildError, SignatureParameterError
try:
create_signature() # no sources provided
except SignatureBuildError:
... # signature could not be built
try:
create_keyword_parameter(name=123) # wrong type
except SignatureParameterError:
... # invalid argument
try:
...
except SignatureError:
... # catches all simple-signature errors
All libraries in the Simple ecosystem share a common philosophy:
Dyslexia-friendly — minimise mental load. Atomise code into self-contained units, name files after the logic they contain, write explanations that describe why — not just what.
Programmer's zen — nothing should be missing and nothing should be superfluous. The journey is the destination: code should be fully understood; better to go slowly and correctly than quickly and with mistakes. The crystallisation approach — not perfection on the first try, but gradual refinement towards it.
Defensive style — anticipate all possible failure modes so that only safe paths remain. Never raise unexpected errors; degrade gracefully.
Minimalism — find the path to the goal in as few steps as possible, but leave nothing out. Each file has one responsibility.
Code as craft — code should be pleasant to look at and evoke a sense of harmony. Treat code as a small work of art — like a carpenter carving a sculpture. Optimise for the user: everything should make sense without having to study the documentation at length.
These are aspirations — a sense of direction. And that is exactly what the note about the journey becoming the destination is all about. 🙂
The library is covered by unit tests across all modules. Tests are part of the repository and serve as living documentation of the expected behaviour.
Release files for simple-signature 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| simple_signature-0.1.2.tar.gz | 37.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| simple_signature-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 93.6 kB
Release files / simple_signature-0.1.2.tar.gz
| Download URL | simple_signature-0.1.2.tar.gz |
|---|---|
| Size | 37.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
365eb65dbda970c29a6388bf4becdd949720859905971c551e50f326442d560b
|
|
BLAKE2b-256 checksum How to use checksums |
73d99eb4a4a8581c9bc8df6b9929edef268c45ed9af2f0609fdb5b582c8918b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|
Release files / simple_signature-0.1.2-py3-none-any.whl
| Download URL | simple_signature-0.1.2-py3-none-any.whl |
|---|---|
| Size | 56.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
928cafac764a71eda3cbdd780545c2db4d35635e163989c87b2935bb03d784a9
|
|
BLAKE2b-256 checksum How to use checksums |
869093be83e37a308b8692fecc8ebec76fe87f7f13725300ee638bc2b7e7a242
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|