Generate signature function from actual function.
(fun: Callable[..., Any], bound: bool = False)
| 352 | |
| 353 | |
| 354 | def head_from_fun(fun: Callable[..., Any], bound: bool = False) -> str: |
| 355 | """Generate signature function from actual function.""" |
| 356 | # we could use inspect.Signature here, but that implementation |
| 357 | # is very slow since it implements the argument checking |
| 358 | # in pure-Python. Instead we use exec to create a new function |
| 359 | # with an empty body, meaning it has the same performance as |
| 360 | # as just calling a function. |
| 361 | is_function = inspect.isfunction(fun) |
| 362 | is_callable = callable(fun) |
| 363 | is_cython = fun.__class__.__name__ == 'cython_function_or_method' |
| 364 | is_method = inspect.ismethod(fun) |
| 365 | |
| 366 | if not is_function and is_callable and not is_method and not is_cython: |
| 367 | name, fun = fun.__class__.__name__, fun.__call__ |
| 368 | else: |
| 369 | name = fun.__name__ |
| 370 | definition = FUNHEAD_TEMPLATE.format( |
| 371 | fun_name=name, |
| 372 | fun_args=_argsfromspec(_getfullargspec(fun)), |
| 373 | fun_value=1, |
| 374 | ) |
| 375 | logger.debug(definition) |
| 376 | namespace = {'__name__': fun.__module__} |
| 377 | # pylint: disable=exec-used |
| 378 | # Tasks are rarely, if ever, created at runtime - exec here is fine. |
| 379 | exec(definition, namespace) |
| 380 | result = namespace[name] |
| 381 | result._source = definition |
| 382 | if bound: |
| 383 | return partial(result, object()) |
| 384 | return result |
| 385 | |
| 386 | |
| 387 | def arity_greater(fun, n): |