Coverage for src/domain/validation/coverage_args.py: 12%

1"""Pure helper functions for rewriting coverage command arguments.

2

3 These functions extract and transform pytest/coverage command arguments

4 without side effects, making them easy to test in isolation.

5"""

6

7 from __future__ import annotations

8

9 import shlex

10

11

12 def strip_xdist_flags(args: list[str]) -> list[str]:

13 """Remove pytest-xdist parallel execution flags.

14

15 Strips -n, --numprocesses, and --dist flags (both standalone and =value forms)

16 to ensure deterministic coverage generation.

17

18 Args:

19 args: Command arguments list.

20

21 Returns:

22 New list with xdist flags removed.

23 """

24 result = []

25 skip_next = False

26 for arg in args:

27 if skip_next:

28 skip_next = False

29 continue

30 # Flags that take a separate value

31 if arg in {"-n", "--numprocesses", "--dist"}:

32 skip_next = True

33 continue

34 # Flags with value attached via =

35 if (

36 arg.startswith("-n=")

37 or arg.startswith("--numprocesses=")

38 or arg.startswith("--dist=")

39 ):

40 continue

41 result.append(arg)

42 return result

43

44

45 def strip_cov_fail_under(args: list[str]) -> list[str]:

46 """Remove --cov-fail-under arguments.

47

48 Args:

49 args: Command arguments list.

50

51 Returns:

52 New list with --cov-fail-under removed.

53 """

54 result = []

55 skip_next = False

56 for arg in args:

57 if skip_next:

58 skip_next = False

59 continue

60 if arg.startswith("--cov-fail-under="):

61 continue

62 if arg == "--cov-fail-under":

63 skip_next = True

64 continue

65 result.append(arg)

66 return result

67

68

69 def extract_marker_expr(args: list[str]) -> tuple[list[str], str | None]:

70 """Extract -m marker expression from arguments.

71

72 Args:

73 args: Command arguments list.

74

75 Returns:

76 Tuple of (args with -m removed, extracted marker expression or None).

77 """

78 result = []

79 marker_expr: str | None = None

80 skip_next = False

81 for arg in args:

82 if skip_next:

83 # This is the value after -m

84 marker_expr = arg

85 skip_next = False

86 continue

87 if arg.startswith("-m="):

88 marker_expr = arg.split("=", 1)[1]

89 continue

90 if arg == "-m":

91 skip_next = True

92 continue

93 result.append(arg)

94 return result, marker_expr

95

96

97 def normalize_marker_expr(expr: str | None) -> str:

98 """Normalize marker expression for baseline coverage.

99

100 Defaults to "unit or integration" and filters out e2e markers.

101

102 Args:

103 expr: Original marker expression or None.

104

105 Returns:

106 Normalized marker expression.

107 """

108 marker = (expr or "unit or integration").strip()

109 if "e2e" in marker:

110 marker = "unit or integration"

111 return marker

112

113

114 def strip_cov_report_xml(args: list[str]) -> list[str]:

115 """Remove --cov-report=xml arguments.

116

117 Strips both --cov-report=xml and --cov-report=xml:<path> forms.

118

119 Args:

120 args: Command arguments list.

121

122 Returns:

123 New list with xml report arguments removed.

124 """

125 return [

126 arg

127 for arg in args

128 if arg != "--cov-report=xml" and not arg.startswith("--cov-report=xml:")

129 ]

130

131

132 def rewrite_coverage_command(cmd: str, coverage_file: str) -> list[str]:

133 """Rewrite coverage command for baseline refresh.

134

135 Applies all transformations:

136 - Strips xdist flags

137 - Strips --cov-fail-under

138 - Extracts and normalizes marker expression

139 - Strips existing xml report paths

140 - Adds new xml report path and --cov-fail-under=0

141

142 Args:

143 cmd: Original coverage command string.

144 coverage_file: Path for XML coverage output.

145

146 Returns:

147 Transformed command as list of arguments.

148 """

149 args = shlex.split(cmd)

150 args = strip_xdist_flags(args)

151 args = strip_cov_fail_under(args)

152 args, marker_expr = extract_marker_expr(args)

153 marker_expr = normalize_marker_expr(marker_expr)

154 args = strip_cov_report_xml(args)

155 args.append(f"--cov-report=xml:{coverage_file}")

156 args.append("--cov-fail-under=0")

157 args.extend(["-m", marker_expr])

158 return args