Coverage for coverage / context.py: 73.214%

38 statements  

« prev     ^ index     » next       coverage.py v7.12.1a0.dev1, created at 2025-11-30 17:57 +0000

1# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 

2# For details: https://github.com/coveragepy/coveragepy/blob/main/NOTICE.txt 

3 

4"""Determine contexts for coverage.py""" 

5 

6from __future__ import annotations 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

7 

8from collections.abc import Sequence 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

9from types import FrameType 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

10 

11from coverage.types import TShouldStartContextFn 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

12 

13 

14def combine_context_switchers( 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

15 context_switchers: Sequence[TShouldStartContextFn], 

16) -> TShouldStartContextFn | None: 

17 """Create a single context switcher from multiple switchers. 

18 

19 `context_switchers` is a list of functions that take a frame as an 

20 argument and return a string to use as the new context label. 

21 

22 Returns a function that composites `context_switchers` functions, or None 

23 if `context_switchers` is an empty list. 

24 

25 When invoked, the combined switcher calls `context_switchers` one-by-one 

26 until a string is returned. The combined switcher returns None if all 

27 `context_switchers` return None. 

28 """ 

29 if not context_switchers: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

30 return None 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

31 

32 if len(context_switchers) == 1: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

33 return context_switchers[0] 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

34 

35 def should_start_context(frame: FrameType) -> str | None: 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

36 """The combiner for multiple context switchers.""" 

37 for switcher in context_switchers: 

38 new_context = switcher(frame) 

39 if new_context is not None: 

40 return new_context 

41 return None 

42 

43 return should_start_context 1abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234

44 

45 

46def should_start_context_test_function(frame: FrameType) -> str | None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

47 """Is this frame calling a test_* function?""" 

48 co_name = frame.f_code.co_name 

49 if co_name.startswith("test") or co_name == "runTest": 

50 return qualname_from_frame(frame) 

51 return None 

52 

53 

54def qualname_from_frame(frame: FrameType) -> str | None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

55 """Get a qualified name for the code running in `frame`.""" 

56 co = frame.f_code 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

57 fname = co.co_name 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

58 method = None 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

59 if co.co_argcount and co.co_varnames[0] == "self": 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

60 self = frame.f_locals.get("self", None) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

61 method = getattr(self, fname, None) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

62 

63 if method is None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

64 func = frame.f_globals.get(fname) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

65 if func is None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

66 return None 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

67 return f"{func.__module__}.{fname}" 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

68 

69 func = getattr(method, "__func__", None) 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

70 if func is None: 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

71 cls = self.__class__ 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

72 return f"{cls.__module__}.{cls.__name__}.{fname}" 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234

73 

74 return f"{func.__module__}.{func.__qualname__}" 1abcdefghijklmnopqrstuvwxyzABCDEF5GH6IJ7KL8MN9OP!QR#ST$UV%WX'YZ(01)234