binding
¶
Utilities for automatic unmarshalling of inputs according to a callable object's signature.
Typical Usage
>>> from typelib import binding
>>>
>>> def foo(val: int) -> int:
... return val * 2
...
>>> bound = binding.bind(foo)
>>> bound("2")
4
>>> bound.call("3")
'33'
AbstractBinding
¶
AbstractBinding(*, signature: Signature, binding: BindingT, varkwd: AbstractUnmarshaller | None = None, varpos: AbstractUnmarshaller | None = None, startpos: int | None = None)
The abstract base class for all type-enforced bindings.
Note
"Bindings" are callables which leverage the type annotations in a signature to unmarshal inputs.
We differentiate each subclass based upon the possible combinations of parameter kinds:
- Positional-only arguments
- Keyword-only arguments
- Positional-or-Keyword arguments
- Variable-positional arguments (
*args
) - Variable-keyword arguments (
**kwargs
)
This allows us to micro-optimize the call for each subclass to exactly what is necessary for the that combination, which can lead to a significant speedup in hot loops.
Parameters:
-
signature
(Signature
) –The signature for the binding.
-
binding
(BindingT
) –A mapping of parameter names and positions to unmarshallers. This accounts for positional, keyword, or positional-or-keyword arguments.
-
varkwd
(AbstractUnmarshaller | None
, default:None
) –The unmarshaller for var-keyword arguments (
**kwargs
). -
varpos
(AbstractUnmarshaller | None
, default:None
) –The unmarshaller for var-positional arguments (
*args
). -
startpos
(int | None
, default:None
) –The start position of var-positional arguments (
*args
). This accounts for the fact that var-positional comes after positional-only.
Source code in src/typelib/binding.py
__call__
abstractmethod
¶
Inspect the given args
and kwargs
and unmarshal them.
Parameters:
Source code in src/typelib/binding.py
BoundRoutine
dataclass
¶
BoundRoutine(call: Callable[P, R], binding: AbstractBinding[P])
bind
¶
bind(obj: Callable[P, R]) -> BoundRoutine[P, R]
Create a type-enforced, bound routine for a callable object.
Note
In contrast to typelib.binding.wrap
, this function creates a new,
type-enforced BoundRoutine
instance. Rather than
masquerading as the given obj
, we encapsulate it in the routine
instance, which is more obvious and provides developers with the ability to
side-step type enforcement when it is deemed unnecessary, which should be
most of the time if your code is strongly typed and statically analyzed.
TL;DR
This function returns an object that walks like your duck and quacks like your duck, but doesn't look like your duck.
Parameters:
-
obj
(Callable[P, R]
) –The callable object to bind.
Source code in src/typelib/binding.py
wrap
¶
Wrap a callable object for runtime type coercion of inputs.
Note
If a class is given, we will attempt to wrap the init method.
Warning
This is a useful feature. It is also very surprising. By wrapping a callable in this decorator, we end up with implicit behavior that's not obvious to the caller or a fellow developer.
You're encouraged to prefer typelib.binding.bind
for similar
functionality, less the implicit nature, especially when a class is given.
TL;DR
This function returns an object walks, quacks, and tries to look like your duck.
Parameters:
-
obj
(Callable[P, R]
) –The callable object to wrap. Maybe be a function, a callable class instance, or a class.