17db96d56Sopenharmony_ciimport functools
27db96d56Sopenharmony_ciimport inspect
37db96d56Sopenharmony_ciimport reprlib
47db96d56Sopenharmony_ciimport sys
57db96d56Sopenharmony_ciimport traceback
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_cifrom . import constants
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_cidef _get_function_source(func):
117db96d56Sopenharmony_ci    func = inspect.unwrap(func)
127db96d56Sopenharmony_ci    if inspect.isfunction(func):
137db96d56Sopenharmony_ci        code = func.__code__
147db96d56Sopenharmony_ci        return (code.co_filename, code.co_firstlineno)
157db96d56Sopenharmony_ci    if isinstance(func, functools.partial):
167db96d56Sopenharmony_ci        return _get_function_source(func.func)
177db96d56Sopenharmony_ci    if isinstance(func, functools.partialmethod):
187db96d56Sopenharmony_ci        return _get_function_source(func.func)
197db96d56Sopenharmony_ci    return None
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_cidef _format_callback_source(func, args):
237db96d56Sopenharmony_ci    func_repr = _format_callback(func, args, None)
247db96d56Sopenharmony_ci    source = _get_function_source(func)
257db96d56Sopenharmony_ci    if source:
267db96d56Sopenharmony_ci        func_repr += f' at {source[0]}:{source[1]}'
277db96d56Sopenharmony_ci    return func_repr
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_cidef _format_args_and_kwargs(args, kwargs):
317db96d56Sopenharmony_ci    """Format function arguments and keyword arguments.
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ci    Special case for a single parameter: ('hello',) is formatted as ('hello').
347db96d56Sopenharmony_ci    """
357db96d56Sopenharmony_ci    # use reprlib to limit the length of the output
367db96d56Sopenharmony_ci    items = []
377db96d56Sopenharmony_ci    if args:
387db96d56Sopenharmony_ci        items.extend(reprlib.repr(arg) for arg in args)
397db96d56Sopenharmony_ci    if kwargs:
407db96d56Sopenharmony_ci        items.extend(f'{k}={reprlib.repr(v)}' for k, v in kwargs.items())
417db96d56Sopenharmony_ci    return '({})'.format(', '.join(items))
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_cidef _format_callback(func, args, kwargs, suffix=''):
457db96d56Sopenharmony_ci    if isinstance(func, functools.partial):
467db96d56Sopenharmony_ci        suffix = _format_args_and_kwargs(args, kwargs) + suffix
477db96d56Sopenharmony_ci        return _format_callback(func.func, func.args, func.keywords, suffix)
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci    if hasattr(func, '__qualname__') and func.__qualname__:
507db96d56Sopenharmony_ci        func_repr = func.__qualname__
517db96d56Sopenharmony_ci    elif hasattr(func, '__name__') and func.__name__:
527db96d56Sopenharmony_ci        func_repr = func.__name__
537db96d56Sopenharmony_ci    else:
547db96d56Sopenharmony_ci        func_repr = repr(func)
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci    func_repr += _format_args_and_kwargs(args, kwargs)
577db96d56Sopenharmony_ci    if suffix:
587db96d56Sopenharmony_ci        func_repr += suffix
597db96d56Sopenharmony_ci    return func_repr
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_cidef extract_stack(f=None, limit=None):
637db96d56Sopenharmony_ci    """Replacement for traceback.extract_stack() that only does the
647db96d56Sopenharmony_ci    necessary work for asyncio debug mode.
657db96d56Sopenharmony_ci    """
667db96d56Sopenharmony_ci    if f is None:
677db96d56Sopenharmony_ci        f = sys._getframe().f_back
687db96d56Sopenharmony_ci    if limit is None:
697db96d56Sopenharmony_ci        # Limit the amount of work to a reasonable amount, as extract_stack()
707db96d56Sopenharmony_ci        # can be called for each coroutine and future in debug mode.
717db96d56Sopenharmony_ci        limit = constants.DEBUG_STACK_DEPTH
727db96d56Sopenharmony_ci    stack = traceback.StackSummary.extract(traceback.walk_stack(f),
737db96d56Sopenharmony_ci                                           limit=limit,
747db96d56Sopenharmony_ci                                           lookup_lines=False)
757db96d56Sopenharmony_ci    stack.reverse()
767db96d56Sopenharmony_ci    return stack
77