dol.sig_builtins¶
Signatures for the callables that inspect.signature can’t handle.
Many builtins (print, map, itertools.product, …) have no signature that
inspect can read. This module holds hand-made ones, and the function Sig uses
to get a signature for any callable, falling back to those:
_robust_signature_of_callable:inspect.signature, with the fallbacks belowsigs_for_builtins,sigs_for_builtin_modules,sigs_for_type_name: the hand-made signatures, by name (sigs_for_sigless_builtin_namemerges the first two)resolve_function,dict_of_attribute_signatures: helpers
It depends on nothing else in dol. It used to be part of dol.signatures, which
still re-exports all of it (i2mint/dol#70).
>>> from dol.sig_builtins import _robust_signature_of_callable
>>> _robust_signature_of_callable(isinstance)
<Signature (obj, class_or_tuple, /)>
Functions
A function that extracts the signatures of all callable attributes of a class. |
|
|
Get the underlying function of a property or cached_property |
- dol.sig_builtins.dict_of_attribute_signatures(cls)[source]¶
A function that extracts the signatures of all callable attributes of a class.
- Parameters:
cls (
type) – The class that holds the the(name, func)pairs we want to extract.- Return type:
- Returns:
A dict of
(name, signature(func))pairs extracted from class.
One of the intended applications is to use
dict_of_attribute_signaturesas a decorator, like so:>>> @dict_of_attribute_signatures ... class names_and_signatures: ... def foo(x: str, *, y=2) -> tuple: ... ... def bar(z, /) -> float: ... >>> names_and_signatures {'foo': <Signature (x: str, *, y=2) -> tuple>, 'bar': <Signature (z, /) -> float>}
- dol.sig_builtins.resolve_function(obj)[source]¶
Get the underlying function of a property or cached_property
Note that if all conditions fail, the object itself is returned.
The problem this function solves is that sometimes there’s a function behind an object, but it’s not always easy to get to it. For example, in a class, you might want to get the source of the code decorated with
@property, a@cached_property, or apartialfunction.Consider the following example:
>>> from functools import cached_property, partial >>> class C: ... @property ... def prop(self): ... pass ... @cached_property ... def cached_prop(self): ... pass ... partial_func = partial(partial)
Note that
propis not callable, and you can’t get its source.>>> import inspect >>> callable(C.prop) False >>> inspect.getsource(C.prop) Traceback (most recent call last): ... TypeError: <property object at 0x...> is not a module, class, method, function, traceback, frame, or code object
But if you grab the underlying function, you can get the source:
>>> func = resolve_function(C.prop) >>> callable(func) True >>> isinstance(inspect.getsource(func), str) True
Same goes with
cached_propertyandpartial:>>> isinstance(inspect.getsource(resolve_function(C.cached_prop)), str) True >>> isinstance(inspect.getsource(resolve_function(C.partial_func)), str) True