Coverage for /home/runner/work/bijux-cli/bijux-cli/src/bijux_cli/contracts/config.py: 100%

16 statements  

« prev     ^ index     » next       coverage.py v7.10.4, created at 2025-08-19 23:36 +0000

1# SPDX-License-Identifier: MIT 

2# Copyright © 2025 Bijan Mousavi 

3 

4"""Defines the contract for the application configuration service. 

5 

6This module specifies the `ConfigProtocol`, a formal interface that any 

7configuration management service within the application must implement. This 

8ensures a consistent API for loading, accessing, modifying, and persisting 

9key-value settings, promoting modularity and testability. 

10""" 

11 

12from __future__ import annotations 

13 

14from pathlib import Path 

15from typing import Any, Protocol, runtime_checkable 

16 

17 

18@runtime_checkable 

19class ConfigProtocol(Protocol): 

20 """Defines the contract for application configuration management. 

21 

22 This interface specifies the methods for loading, accessing, modifying, and 

23 persisting configuration data from various sources (e.g., .env, JSON, 

24 or YAML files). 

25 """ 

26 

27 def load(self, path: str | Path | None = None) -> None: 

28 """Loads configuration from a specified file path. 

29 

30 Args: 

31 path (str | Path | None): The path to the configuration file. If 

32 None, the service may load from a default location. 

33 

34 Returns: 

35 None: 

36 """ 

37 ... 

38 

39 def get(self, key: str, default: Any = None) -> Any: 

40 """Retrieves a configuration value by its key. 

41 

42 Args: 

43 key (str): The key of the value to retrieve. 

44 default (Any): The value to return if the key is not found. 

45 

46 Returns: 

47 Any: The configuration value or the provided default. 

48 """ 

49 ... 

50 

51 def set(self, key: str, value: Any) -> None: 

52 """Sets a configuration key and persists the change. 

53 

54 Args: 

55 key (str): The key to set or update. 

56 value (Any): The value to associate with the key. 

57 

58 Returns: 

59 None: 

60 """ 

61 ... 

62 

63 def export(self, path: str | Path, out_format: str | None = None) -> None: 

64 """Exports the current configuration to a file. 

65 

66 Args: 

67 path (str | Path): The path to the destination file. 

68 out_format (str | None): The desired output format (e.g., 'env'). 

69 If None, the format may be inferred from the path. 

70 

71 Returns: 

72 None: 

73 """ 

74 ... 

75 

76 def reload(self) -> None: 

77 """Reloads the configuration from its last-known source file.""" 

78 ... 

79 

80 def save(self) -> None: 

81 """Saves the current in-memory configuration state to its source file.""" 

82 ... 

83 

84 def delete(self, key: str) -> None: 

85 """Deletes a configuration key and persists the change. 

86 

87 Args: 

88 key (str): The key to delete. 

89 

90 Returns: 

91 None: 

92 """ 

93 ... 

94 

95 def unset(self, key: str) -> None: 

96 """Removes a configuration key from the current in-memory session. 

97 

98 Unlike `delete`, this operation may not be immediately persisted to the 

99 source file. 

100 

101 Args: 

102 key (str): The key to remove from the in-memory configuration. 

103 

104 Returns: 

105 None: 

106 """ 

107 ... 

108 

109 def clear(self) -> None: 

110 """Clears all configuration data from memory.""" 

111 ... 

112 

113 def list_keys(self) -> list[str]: 

114 """Returns a list of all configuration keys. 

115 

116 Returns: 

117 list[str]: A list of all keys present in the configuration. 

118 """ 

119 ... 

120 

121 def all(self) -> dict[str, str]: 

122 """Returns all configuration key-value pairs. 

123 

124 Returns: 

125 dict[str, str]: A dictionary of all configuration data. 

126 """ 

127 ...