Coverage for pytest_beehave/config.py: 100%

45 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2026-04-21 04:49 +0000

1"""Configuration reader for pytest-beehave.""" 

2 

3import tomllib 

4from pathlib import Path 

5from typing import Literal, cast 

6 

7DEFAULT_FEATURES_PATH: str = "docs/features" 

8type StubFormat = Literal["functions", "classes"] 

9VALID_STUB_FORMATS: tuple[str, ...] = ("functions", "classes") 

10DEFAULT_STUB_FORMAT: StubFormat = "functions" 

11 

12 

13def _read_beehave_section(rootdir: Path) -> dict[str, object]: 

14 """Read the [tool.beehave] section from pyproject.toml. 

15 

16 Args: 

17 rootdir: Absolute path to the project root. 

18 

19 Returns: 

20 The [tool.beehave] dict, or empty dict if absent. 

21 """ 

22 pyproject = rootdir / "pyproject.toml" 

23 if not pyproject.exists(): 

24 return {} 

25 with pyproject.open("rb") as f: 

26 data = tomllib.load(f) 

27 return data.get("tool", {}).get("beehave", {}) 

28 

29 

30def show_steps_in_terminal(rootdir: Path) -> bool: 

31 """Return True if show_steps_in_terminal is enabled (default: True). 

32 

33 Args: 

34 rootdir: Absolute path to the project root. 

35 

36 Returns: 

37 True unless explicitly set to false in [tool.beehave]. 

38 """ 

39 section = _read_beehave_section(rootdir) 

40 return bool(section.get("show_steps_in_terminal", True)) 

41 

42 

43def show_steps_in_html(rootdir: Path) -> bool: 

44 """Return True if show_steps_in_html is enabled (default: True). 

45 

46 Args: 

47 rootdir: Absolute path to the project root. 

48 

49 Returns: 

50 True unless explicitly set to false in [tool.beehave]. 

51 """ 

52 section = _read_beehave_section(rootdir) 

53 return bool(section.get("show_steps_in_html", True)) 

54 

55 

56def _read_configured_path(pyproject: Path) -> str | None: 

57 """Read features_path from [tool.beehave] in pyproject.toml. 

58 

59 Args: 

60 pyproject: Path to the pyproject.toml file. 

61 

62 Returns: 

63 The configured features_path string, or None if not set. 

64 """ 

65 with pyproject.open("rb") as f: 

66 data = tomllib.load(f) 

67 tool_section = data.get("tool", {}) 

68 beehave_section = tool_section.get("beehave", {}) 

69 return beehave_section.get("features_path") 

70 

71 

72def is_explicitly_configured(rootdir: Path) -> bool: 

73 """Return True if features_path is explicitly set in [tool.beehave]. 

74 

75 Args: 

76 rootdir: Absolute path to the project root. 

77 

78 Returns: 

79 True if [tool.beehave].features_path is present in pyproject.toml. 

80 """ 

81 pyproject = rootdir / "pyproject.toml" 

82 if not pyproject.exists(): 

83 return False 

84 return _read_configured_path(pyproject) is not None 

85 

86 

87def resolve_features_path(rootdir: Path) -> Path: 

88 """Resolve the features directory path from config or fall back to default. 

89 

90 Args: 

91 rootdir: Absolute path to the project root. 

92 

93 Returns: 

94 Resolved absolute Path to the features directory. 

95 """ 

96 pyproject = rootdir / "pyproject.toml" 

97 if not pyproject.exists(): 

98 return rootdir / DEFAULT_FEATURES_PATH 

99 configured = _read_configured_path(pyproject) 

100 if configured is None: 

101 return rootdir / DEFAULT_FEATURES_PATH 

102 return rootdir / configured 

103 

104 

105def read_stub_format(rootdir: Path) -> StubFormat: 

106 """Read stub_format from [tool.beehave] in pyproject.toml. 

107 

108 Args: 

109 rootdir: Absolute path to the project root. 

110 

111 Returns: 

112 The configured StubFormat, or DEFAULT_STUB_FORMAT if absent. 

113 

114 Raises: 

115 SystemExit: If stub_format has an invalid value. 

116 """ 

117 section = _read_beehave_section(rootdir) 

118 value = section.get("stub_format", DEFAULT_STUB_FORMAT) 

119 if value not in VALID_STUB_FORMATS: 

120 raise SystemExit( 

121 f"[beehave] invalid stub_format: {value!r}" 

122 f" — valid values are {VALID_STUB_FORMATS}" 

123 ) 

124 return cast(StubFormat, value)