Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pluggy/_callers.py: 8%

40 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-25 06:11 +0000

1""" 

2Call loop machinery 

3""" 

4import sys 

5 

6from ._result import HookCallError, _Result, _raise_wrapfail 

7 

8 

9def _multicall(hook_name, hook_impls, caller_kwargs, firstresult): 

10 """Execute a call into multiple python functions/methods and return the 

11 result(s). 

12 

13 ``caller_kwargs`` comes from _HookCaller.__call__(). 

14 """ 

15 __tracebackhide__ = True 

16 results = [] 

17 excinfo = None 

18 try: # run impl and wrapper setup functions in a loop 

19 teardowns = [] 

20 try: 

21 for hook_impl in reversed(hook_impls): 

22 try: 

23 args = [caller_kwargs[argname] for argname in hook_impl.argnames] 

24 except KeyError: 

25 for argname in hook_impl.argnames: 

26 if argname not in caller_kwargs: 

27 raise HookCallError( 

28 f"hook call must provide argument {argname!r}" 

29 ) 

30 

31 if hook_impl.hookwrapper: 

32 try: 

33 gen = hook_impl.function(*args) 

34 next(gen) # first yield 

35 teardowns.append(gen) 

36 except StopIteration: 

37 _raise_wrapfail(gen, "did not yield") 

38 else: 

39 res = hook_impl.function(*args) 

40 if res is not None: 

41 results.append(res) 

42 if firstresult: # halt further impl calls 

43 break 

44 except BaseException: 

45 excinfo = sys.exc_info() 

46 finally: 

47 if firstresult: # first result hooks return a single value 

48 outcome = _Result(results[0] if results else None, excinfo) 

49 else: 

50 outcome = _Result(results, excinfo) 

51 

52 # run all wrapper post-yield blocks 

53 for gen in reversed(teardowns): 

54 try: 

55 gen.send(outcome) 

56 _raise_wrapfail(gen, "has second yield") 

57 except StopIteration: 

58 pass 

59 

60 return outcome.get_result()