Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #!/usr/bin/env python3
  2. import json
  3. from pathlib import Path
  4. from typing import Any
  5. class ConfigHelper:
  6. """Helper class for reading and writing configuration files."""
  7. def __init__(self, base_dir: Path | None = None):
  8. """Initialize ConfigHelper with base directory.
  9. Args:
  10. base_dir: Base directory for config files. If None, uses setup/config
  11. """
  12. if base_dir is None:
  13. # Default to config directory in setup folder
  14. base_dir = Path(__file__).parent.parent / "setup" / "config"
  15. self.base_dir = base_dir
  16. self.state_file = "stress_test_state.json"
  17. def ensure_config_dir(self) -> None:
  18. """Ensure the config directory exists."""
  19. self.base_dir.mkdir(exist_ok=True, parents=True)
  20. def get_config_path(self, filename: str) -> Path:
  21. """Get the full path for a config file.
  22. Args:
  23. filename: Name of the config file (e.g., 'admin_config.json')
  24. Returns:
  25. Full path to the config file
  26. """
  27. if not filename.endswith(".json"):
  28. filename += ".json"
  29. return self.base_dir / filename
  30. def read_config(self, filename: str) -> dict[str, Any] | None:
  31. """Read a configuration file.
  32. DEPRECATED: Use read_state() or get_state_section() for new code.
  33. This method provides backward compatibility.
  34. Args:
  35. filename: Name of the config file to read
  36. Returns:
  37. Dictionary containing config data, or None if file doesn't exist
  38. """
  39. # Provide backward compatibility for old config names
  40. if filename in ["admin_config", "token_config", "app_config", "api_key_config"]:
  41. section_map = {
  42. "admin_config": "admin",
  43. "token_config": "auth",
  44. "app_config": "app",
  45. "api_key_config": "api_key",
  46. }
  47. return self.get_state_section(section_map[filename])
  48. config_path = self.get_config_path(filename)
  49. if not config_path.exists():
  50. return None
  51. try:
  52. with open(config_path, "r") as f:
  53. return json.load(f)
  54. except (json.JSONDecodeError, IOError) as e:
  55. print(f"❌ Error reading {filename}: {e}")
  56. return None
  57. def write_config(self, filename: str, data: dict[str, Any]) -> bool:
  58. """Write data to a configuration file.
  59. DEPRECATED: Use write_state() or update_state_section() for new code.
  60. This method provides backward compatibility.
  61. Args:
  62. filename: Name of the config file to write
  63. data: Dictionary containing data to save
  64. Returns:
  65. True if successful, False otherwise
  66. """
  67. # Provide backward compatibility for old config names
  68. if filename in ["admin_config", "token_config", "app_config", "api_key_config"]:
  69. section_map = {
  70. "admin_config": "admin",
  71. "token_config": "auth",
  72. "app_config": "app",
  73. "api_key_config": "api_key",
  74. }
  75. return self.update_state_section(section_map[filename], data)
  76. self.ensure_config_dir()
  77. config_path = self.get_config_path(filename)
  78. try:
  79. with open(config_path, "w") as f:
  80. json.dump(data, f, indent=2)
  81. return True
  82. except IOError as e:
  83. print(f"❌ Error writing {filename}: {e}")
  84. return False
  85. def config_exists(self, filename: str) -> bool:
  86. """Check if a config file exists.
  87. Args:
  88. filename: Name of the config file to check
  89. Returns:
  90. True if file exists, False otherwise
  91. """
  92. return self.get_config_path(filename).exists()
  93. def delete_config(self, filename: str) -> bool:
  94. """Delete a configuration file.
  95. Args:
  96. filename: Name of the config file to delete
  97. Returns:
  98. True if successful, False otherwise
  99. """
  100. config_path = self.get_config_path(filename)
  101. if not config_path.exists():
  102. return True # Already doesn't exist
  103. try:
  104. config_path.unlink()
  105. return True
  106. except IOError as e:
  107. print(f"❌ Error deleting {filename}: {e}")
  108. return False
  109. def read_state(self) -> dict[str, Any] | None:
  110. """Read the entire stress test state.
  111. Returns:
  112. Dictionary containing all state data, or None if file doesn't exist
  113. """
  114. state_path = self.get_config_path(self.state_file)
  115. if not state_path.exists():
  116. return None
  117. try:
  118. with open(state_path, "r") as f:
  119. return json.load(f)
  120. except (json.JSONDecodeError, IOError) as e:
  121. print(f"❌ Error reading {self.state_file}: {e}")
  122. return None
  123. def write_state(self, data: dict[str, Any]) -> bool:
  124. """Write the entire stress test state.
  125. Args:
  126. data: Dictionary containing all state data to save
  127. Returns:
  128. True if successful, False otherwise
  129. """
  130. self.ensure_config_dir()
  131. state_path = self.get_config_path(self.state_file)
  132. try:
  133. with open(state_path, "w") as f:
  134. json.dump(data, f, indent=2)
  135. return True
  136. except IOError as e:
  137. print(f"❌ Error writing {self.state_file}: {e}")
  138. return False
  139. def update_state_section(self, section: str, data: dict[str, Any]) -> bool:
  140. """Update a specific section of the stress test state.
  141. Args:
  142. section: Name of the section to update (e.g., 'admin', 'auth', 'app', 'api_key')
  143. data: Dictionary containing section data to save
  144. Returns:
  145. True if successful, False otherwise
  146. """
  147. state = self.read_state() or {}
  148. state[section] = data
  149. return self.write_state(state)
  150. def get_state_section(self, section: str) -> dict[str, Any] | None:
  151. """Get a specific section from the stress test state.
  152. Args:
  153. section: Name of the section to get (e.g., 'admin', 'auth', 'app', 'api_key')
  154. Returns:
  155. Dictionary containing section data, or None if not found
  156. """
  157. state = self.read_state()
  158. if state:
  159. return state.get(section)
  160. return None
  161. def get_token(self) -> str | None:
  162. """Get the access token from auth section.
  163. Returns:
  164. Access token string or None if not found
  165. """
  166. auth = self.get_state_section("auth")
  167. if auth:
  168. return auth.get("access_token")
  169. return None
  170. def get_app_id(self) -> str | None:
  171. """Get the app ID from app section.
  172. Returns:
  173. App ID string or None if not found
  174. """
  175. app = self.get_state_section("app")
  176. if app:
  177. return app.get("app_id")
  178. return None
  179. def get_api_key(self) -> str | None:
  180. """Get the API key token from api_key section.
  181. Returns:
  182. API key token string or None if not found
  183. """
  184. api_key = self.get_state_section("api_key")
  185. if api_key:
  186. return api_key.get("token")
  187. return None
  188. # Create a default instance for convenience
  189. config_helper = ConfigHelper()