"""Compute function signatures
==============================
Internal API
------------
.. autofunction:: _format_types_as_backend_types
.. autofunction:: compute_signatures_from_typeobjects
.. autofunction:: _make_signature_from_template_variables
.. autofunction:: make_signatures_from_typehinted_func
"""
import itertools
import inspect
from typing import List
from transonic.typing import format_type_as_backend_type, str2type
[docs]def compute_signatures_from_typeobjects(
types_in, backend_type_formatter
) -> List[List[str]]:
"""Compute a list of lists (signatures) of strings (backend types)"""
if isinstance(types_in, dict):
types_in = types_in.values()
types = []
for type_ in types_in:
if isinstance(type_, str):
type_ = str2type(type_)
types.append(type_)
template_parameters = set()
for type_ in types:
if hasattr(type_, "get_template_parameters"):
template_parameters.update(type_.get_template_parameters())
if not template_parameters:
if "_empty" in types:
raise ValueError(
"At least one annotation type lacking in a signature.\n"
f"types = {types}"
)
str_types = [
format_type_as_backend_type(type_, backend_type_formatter)
for type_ in types
]
return (str_types,)
if not all(param.values for param in template_parameters):
raise ValueError(
f"{template_parameters}, {[param.values for param in template_parameters]}"
)
values_template_parameters = {}
for param in template_parameters:
values_template_parameters[param.__name__] = param.values
backend_types = []
names = values_template_parameters.keys()
for set_types in itertools.product(*values_template_parameters.values()):
template_variables = dict(zip(names, set_types))
backend_types.append(
_format_types_as_backend_types(
types, backend_type_formatter, **template_variables
)
)
return backend_types
[docs]def _make_signature_from_template_variables(
func, backend_type_formatter, _signature=None, as_list_str=False, **kwargs
):
"""Create signature for a function with values for the template types
(This function should only be used in
:func:`make_signatures_from_typehinted_func`)
Parameters
----------
func: a function
kwargs : dict
The template types and their value
"""
if _signature is None:
_signature = inspect.signature(func)
types = [param.annotation for param in _signature.parameters.values()]
backend_types = _format_types_as_backend_types(
types, backend_type_formatter, **kwargs
)
# "multiply" the signatures to take into account the "or" syntax
multi_pythran_types = [
_ for _ in itertools.product(*[t.split(" or ") for t in backend_types])
]
signatures = []
for backend_types in multi_pythran_types:
if as_list_str:
signature = backend_types
else:
signature = f"{func.__name__}(" + ", ".join(backend_types) + ")"
signatures.append(signature)
return signatures
[docs]def make_signatures_from_typehinted_func(
func, backend_type_formatter, as_list_str=False
):
"""Make the signatures from annotations if it is possible
Useful when there are only "not templated" types.
"""
annotations = func.__annotations__
if not annotations:
return tuple()
for key, value in annotations.items():
if isinstance(value, str):
annotations[key] = str2type(value)
types = annotations.values()
template_parameters = []
for type_ in types:
if hasattr(type_, "get_template_parameters"):
template_parameters.extend(type_.get_template_parameters())
template_parameters = set(template_parameters)
_signature = inspect.signature(func)
if not template_parameters:
signatures = _make_signature_from_template_variables(
func,
backend_type_formatter,
_signature=_signature,
as_list_str=as_list_str,
)
return signatures
if not all(param.values for param in template_parameters):
return tuple()
values_template_parameters = {}
for param in template_parameters:
values_template_parameters[param.__name__] = param.values
names = values_template_parameters.keys()
signatures = []
for set_types in itertools.product(*values_template_parameters.values()):
template_variables = dict(zip(names, set_types))
signatures.extend(
_make_signature_from_template_variables(
func,
backend_type_formatter,
_signature=_signature,
as_list_str=as_list_str,
**template_variables,
)
)
return signatures