uf.specs#

Function specification management for uf.

Provides a Mapping-based interface to function specifications, including RJSF form specs and OpenAPI schemas.

Functions

doc_of_func(func)

The docstring of func; for a functools.partial (whose own __doc__ is the generic one of partial), that of the function it wraps.

name_funcs(funcs)

{name: callable} from a mapping of explicit names, or an iterable of callables (named by name_of_func).

name_of_func(func)

The name a function is served under: its __name__; failing that, for a functools.partial, that of the function it wraps; for a callable instance, its class name.

unwrap_partials(func)

The function a (possibly nested) functools.partial wraps; anything else as is.

Classes

FunctionSpecStore(funcs, *[, rjsf_config, ...])

A mapping from function names to their RJSF specifications.

Exceptions

FormSpecError

The form spec of a function could not be generated (the cause is chained).

JuNotInstalledWarning

Emitted when ju is absent and uf falls back to basic form specs.

UnintrospectableCallableError

A callable has no signature to build a form from (e.g. max, getattr).

UnservableCallableError

A callable can never be called from a uf form (e.g. it has a required positional-only parameter).

exception uf.specs.FormSpecError[source]#

Bases: ValueError

The form spec of a function could not be generated (the cause is chained).

class uf.specs.FunctionSpecStore(funcs, *, rjsf_config=None, ui_schema_factory=None, param_to_prop_type=None, validate=False)[source]#

Bases: Mapping

A mapping from function names to their RJSF specifications.

Lazily generates and caches form specs for each function.

Parameters:
  • funcs (Union[Iterable[Callable], Mapping[str, Callable]]) – Iterable of callables to generate specs for (named by name_of_func: __name__, the wrapped function’s for a functools.partial, the class name for a callable instance), or a mapping {name: callable} to name them explicitly

  • rjsf_config (Optional[dict]) – Optional configuration dict for RJSF generation

  • ui_schema_factory (Optional[Callable]) – Optional callable to customize UI schema generation

  • param_to_prop_type (Optional[Callable]) – Optional callable to map parameters to property types

  • validate (bool) – If true, every function is checked and its spec generated at construction, so a callable uf can’t build a form for fails there, naming it, rather than on the first request (default false: checked on first access of its spec; mk_rjsf_app validates).

Example

>>> def add(x: int, y: int) -> int:
...     '''Add two numbers'''
...     return x + y
>>> specs = FunctionSpecStore([add])
>>> 'add' in specs
True
>>> spec = specs['add']
>>> 'schema' in spec
True
property function_list: list[dict]#

Get list of all functions with basic metadata.

Returns:

List of dictionaries with function name and description

get_func(func_name)[source]#

Get the original function object by name.

Parameters:

func_name (str) – Name of the function

Return type:

Callable

Returns:

The function object

Raises:

KeyError – If function name not found

exception uf.specs.JuNotInstalledWarning[source]#

Bases: UserWarning

Emitted when ju is absent and uf falls back to basic form specs.

exception uf.specs.UnintrospectableCallableError[source]#

Bases: ValueError

A callable has no signature to build a form from (e.g. max, getattr).

exception uf.specs.UnservableCallableError[source]#

Bases: ValueError

A callable can never be called from a uf form (e.g. it has a required positional-only parameter).

uf.specs.doc_of_func(func)[source]#

The docstring of func; for a functools.partial (whose own __doc__ is the generic one of partial), that of the function it wraps.

Return type:

Optional[str]

>>> import functools
>>> def f(x, y):
...     "Add."
>>> doc_of_func(functools.partial(f, y=1))
'Add.'
uf.specs.name_funcs(funcs)[source]#

{name: callable} from a mapping of explicit names, or an iterable of callables (named by name_of_func). Two different callables sharing a name raise.

Return type:

dict

>>> import functools
>>> name_funcs([len, functools.partial(int, base=2)])
{'len': <built-in function len>, 'int': functools.partial(<class 'int'>, base=2)}
>>> name_funcs({'size': len})
{'size': <built-in function len>}
uf.specs.name_of_func(func)[source]#

The name a function is served under: its __name__; failing that, for a functools.partial, that of the function it wraps; for a callable instance, its class name.

Return type:

str

>>> import functools
>>> name_of_func(len)
'len'
>>> name_of_func(functools.partial(int, base=2))
'int'
>>> class Doubler:
...     def __call__(self, x): return 2 * x
>>> name_of_func(Doubler())
'Doubler'
uf.specs.unwrap_partials(func)[source]#

The function a (possibly nested) functools.partial wraps; anything else as is.

Return type:

Callable

>>> import functools
>>> def f(x, y, z): ...
>>> unwrap_partials(functools.partial(functools.partial(f, 1), 2)) is f
True
>>> unwrap_partials(f) is f
True