Skip to main content

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

Project description

simplibs-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

# Assemble a signature from multiple sources
sig = create_signature(extra_param, base_func=my_func)

# Or use the decorator shorthand
@signature(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 simplibs-signature
from simplibs.signature import create_signature, signature, signature_copy

Note: This library automatically installs simplibs-exception and simplibs-sentinels as core dependencies.


Quick start

The library is built around SignatureCreator — a class that assembles an inspect.Signature from any combination of callables and inspect.Parameter instances. Its direct functional interface is create_signature, which accepts identical parameters and returns the assembled signature without exposing the builder instance.

On top of that, the library provides a set of utilities for working with signatures directly — retrieving, copying, applying — and two decorators, signature_copy and signature, that cover the most common use cases in a compact one-liner form.

Assemble a signature programmatically

from simplibs.signature import create_signature, create_keyword_parameter

extra = create_keyword_parameter("timeout", annotation=int, default=30)

sig = create_signature(extra, base_func=my_func)
# → (host: str, port: int, *, timeout: int = 30)

Copy a signature from an existing function

from simplibs.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

Merge parameters from multiple sources

from simplibs.signature import signature, create_keyword_parameter

extra = create_keyword_parameter("timeout", annotation=int, default=30)

@signature(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.

from simplibs.signature import signature_copy

@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

Assembles a new signature from the decorated function and any additional parameter sources. The decorated function becomes base_func.

from simplibs.signature import signature

@signature(param_or_func, ..., base_func_first=True)
def my_func(*args, **kwargs):
    ...
Parameter Type Description
*sources 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 simplibs.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 simplibs.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 simplibs.signature import create_copy_signature
from simplibs.sentinels import 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 simplibs.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 simplibs.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 simplibs.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 simplibs.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 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 simplibs.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
*sources 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 simplibs.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 simplibs ecosystem

simplibs-signature is part of the simplibs ecosystem — a collection of small, self-contained Python libraries united under a common namespace and philosophy. The name simplibs is short for simple libraries.

This library builds on two other simplibs packages:

  • simplibs-exception — a structured exception that communicates with the developer: describing not just what went wrong, but pointing towards a fix. All errors raised by simplibs-signature are structured SimpleException subclasses, catchable as SignatureError or the more specific SignatureParameterError and SignatureBuildError:
from simplibs.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 simplibs-signature errors
  • simplibs-sentinels — sentinel values shared across the ecosystem. UNSET is used throughout simplibs-signature to distinguish between a parameter that was not provided and one explicitly set to None:
from simplibs.sentinels import UNSET
from simplibs.signature import create_copy_signature

sig = create_copy_signature(my_func, return_type=UNSET)  # preserve original
sig = create_copy_signature(my_func, return_type=None)   # remove annotation

All libraries in the simplibs 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.

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

simplibs_signature-0.2.2.tar.gz (63.8 kB view details)

Uploaded Source

Built Distribution

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

simplibs_signature-0.2.2-py3-none-any.whl (94.8 kB view details)

Uploaded Python 3

File details

Details for the file simplibs_signature-0.2.2.tar.gz.

File metadata

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

File hashes

Hashes for simplibs_signature-0.2.2.tar.gz
Algorithm Hash digest
SHA256 8cb3246d35b03f26bd3add11a35f9a34187ec53bde9b0bdd97d522d7763c266f
MD5 aaf8ba0ac7c9a63da1423136603154d9
BLAKE2b-256 2eba3e79a9aec0918c27494be97b7cb7803321278cc4a7a3351b73d1ce52cb33

See more details on using hashes here.

File details

Details for the file simplibs_signature-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for simplibs_signature-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e3099276c5a104a0376ccc809a8f34f0ada752c08d97df26169cb8d6cdd887d6
MD5 7fff51c8acac2f488bb627ba43c37848
BLAKE2b-256 da5c9b7557462caa1cdb0101dadef325cc002d50f7712096aac9713b80f94069

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