Skip to main content

Lightweight utilities for dynamic and declarative function signature manipulation, inspection, and validation.

Project description

Mám vše co potřebuji — jdeme na to! 🙂


simple-signature

Lightweight utilities for dynamic and declarative function signature manipulation. Inspect, copy, assemble, and apply inspect.Signature objects — with a clean API and no magic.

Python Licence PyPI

@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

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_signatureself 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 tests across all modules — unit tests and integration tests alike. Tests are part of the repository and serve as living documentation of the expected behaviour.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simple_signature-0.1.0.tar.gz (37.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

simple_signature-0.1.0-py3-none-any.whl (56.0 kB view details)

Uploaded Python 3

File details

Details for the file simple_signature-0.1.0.tar.gz.

File metadata

  • Download URL: simple_signature-0.1.0.tar.gz
  • Upload date:
  • Size: 37.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for simple_signature-0.1.0.tar.gz
Algorithm Hash digest
SHA256 79f2008613b2c1d15e47bf2f28a285b6605c62a9395aa2d3e1591a88fb900079
MD5 f0aa2dfe4b37612b13719f67f001342d
BLAKE2b-256 d2335a21d5a5c6e89c336bd5a83e7a15884b79d1d26e9f9b12785cbb34e8013a

See more details on using hashes here.

File details

Details for the file simple_signature-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for simple_signature-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b3f128c7368bc769eceb767dfca5b04dbf08a9e1e629155f624512a407f5284b
MD5 1fa4c46f6d023e2a43fc6dff87fb259c
BLAKE2b-256 4834e826e4f06f0e6fb996e1da1d2d7a4084173e6d63379df3434edd68b448ff

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page