import collections import inspect import sys from typing import Callable def format_by_args(__func: Callable, __title: str, *a, **kw) -> str: params = _func_parameters(__func, *a, **kw) args = list(map(lambda x: _represent(x), a)) return __title.format(*args, **params) # These 2 functions are copied from allure_commons._allure # Duplicate it here in order to be independent of allure and make some adjustments. def _represent(item): if isinstance(item, str): return item elif isinstance(item, (bytes, bytearray)): return repr(type(item)) else: return repr(item) def _func_parameters(func, *args, **kwargs): parameters = {} arg_spec = inspect.getfullargspec(func) arg_order = list(arg_spec.args) args_dict = dict(zip(arg_spec.args, args)) if arg_spec.defaults: kwargs_defaults_dict = dict(zip(arg_spec.args[-len(arg_spec.defaults) :], arg_spec.defaults)) parameters.update(kwargs_defaults_dict) if arg_spec.varargs: arg_order.append(arg_spec.varargs) varargs = args[len(arg_spec.args) :] parameters.update({arg_spec.varargs: varargs} if varargs else {}) if arg_spec.args and arg_spec.args[0] in ["cls", "self"]: args_dict.pop(arg_spec.args[0], None) if kwargs: if sys.version_info < (3, 7): # Sort alphabetically as old python versions does # not preserve call order for kwargs. arg_order.extend(sorted(list(kwargs.keys()))) else: # Keep py3.7 behaviour to preserve kwargs order arg_order.extend(list(kwargs.keys())) parameters.update(kwargs) parameters.update(args_dict) items = parameters.items() sorted_items = sorted(map(lambda kv: (kv[0], _represent(kv[1])), items), key=lambda x: arg_order.index(x[0])) return collections.OrderedDict(sorted_items)