Coverage for src / ezpl / cli / utils / env_manager.py: 71.90%
93 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-13 19:35 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-13 19:35 +0000
1# ///////////////////////////////////////////////////////////////
2# EZPL - Environment Variable Manager
3# Project: ezpl
4# ///////////////////////////////////////////////////////////////
6"""
7Environment variable manager for CLI operations.
9This module provides functionality to manage user environment variables
10for Ezpl configuration.
11"""
13from __future__ import annotations
15# ///////////////////////////////////////////////////////////////
16# IMPORTS
17# ///////////////////////////////////////////////////////////////
18# Standard library imports
19import os
20import sys
21from pathlib import Path
23# ///////////////////////////////////////////////////////////////
24# CLASSES
25# ///////////////////////////////////////////////////////////////
28class UserEnvManager:
29 """
30 Manager for user environment variables.
32 Manages environment variables in user profile for Ezpl configuration.
33 """
35 # Mapping of configuration keys to environment variable names
36 CONFIG_TO_ENV = {
37 "log-level": "EZPL_LOG_LEVEL",
38 "log-file": "EZPL_LOG_FILE",
39 "log-dir": "EZPL_LOG_DIR",
40 "printer-level": "EZPL_PRINTER_LEVEL",
41 "indent-step": "EZPL_INDENT_STEP",
42 "indent-symbol": "EZPL_INDENT_SYMBOL",
43 "base-indent-symbol": "EZPL_BASE_INDENT_SYMBOL",
44 "file-logger-level": "EZPL_FILE_LOGGER_LEVEL",
45 "log-format": "EZPL_LOG_FORMAT",
46 "log-rotation": "EZPL_LOG_ROTATION",
47 "log-retention": "EZPL_LOG_RETENTION",
48 "log-compression": "EZPL_LOG_COMPRESSION",
49 }
51 # ///////////////////////////////////////////////////////////////
52 # INIT
53 # ///////////////////////////////////////////////////////////////
55 def __init__(self) -> None:
56 """Initialize the environment variable manager."""
57 self.env_file = self._get_env_file_path()
58 self._tracked_vars: list[str] = []
60 # ------------------------------------------------
61 # PRIVATE HELPER METHODS
62 # ------------------------------------------------
64 def _get_env_file_path(self) -> Path:
65 """
66 Get the path to the user environment file.
68 Returns:
69 Path to .env file in user's Ezpl directory
70 """
71 if sys.platform == "win32": 71 ↛ 73line 71 didn't jump to line 73 because the condition on line 71 was never true
72 # Windows: %USERPROFILE%\.ezpl\.env
73 user_profile = os.getenv("USERPROFILE", str(Path.home()))
74 return Path(user_profile) / ".ezpl" / ".env"
75 else:
76 # Linux/macOS: ~/.ezpl/.env
77 return Path.home() / ".ezpl" / ".env"
79 def _load_env_file(self) -> dict[str, str]:
80 """
81 Load environment variables from .env file.
83 Returns:
84 Dictionary of environment variables
85 """
86 env_vars = {}
87 if self.env_file.exists():
88 try:
89 with open(self.env_file, encoding="utf-8") as f:
90 for line in f:
91 line = line.strip()
92 if line and not line.startswith("#") and "=" in line:
93 key, value = line.split("=", 1)
94 env_vars[key.strip()] = value.strip()
95 except (OSError, ValueError):
96 pass
97 return env_vars
99 def _save_env_file(self, env_vars: dict[str, str]) -> None:
100 """
101 Save environment variables to .env file.
103 Args:
104 env_vars: Dictionary of environment variables to save
105 """
106 self.env_file.parent.mkdir(parents=True, exist_ok=True)
108 # Keep only managed variables to ensure removals are persisted
109 managed_vars = {
110 key: value for key, value in env_vars.items() if key.startswith("EZPL_")
111 }
113 # Write back
114 try:
115 with open(self.env_file, "w", encoding="utf-8") as f:
116 f.write("# Ezpl User Environment Variables\n")
117 f.write("# Generated by: ezpl config set --env\n")
118 f.write("# DO NOT EDIT MANUALLY - Use 'ezpl config set --env'\n\n")
119 for key, value in sorted(managed_vars.items()):
120 f.write(f"{key}={value}\n")
121 except OSError:
122 pass
124 def _get_tracked_vars(self) -> list[str]:
125 """
126 Get list of tracked environment variables.
128 Returns:
129 List of environment variable names that Ezpl manages
130 """
131 if not self._tracked_vars:
132 # Load from file if exists
133 env_vars = self._load_env_file()
134 self._tracked_vars = [key for key in env_vars if key.startswith("EZPL_")]
135 return self._tracked_vars
137 # ///////////////////////////////////////////////////////////////
138 # PUBLIC METHODS
139 # ///////////////////////////////////////////////////////////////
141 def set_user_env(self, config_key: str, value: str) -> bool:
142 """
143 Set a user environment variable from a config key.
145 Args:
146 config_key: Configuration key (e.g., "log-level")
147 value: Value to set
149 Returns:
150 True if successful, False otherwise
151 """
152 env_var = self.CONFIG_TO_ENV.get(config_key)
153 if not env_var: 153 ↛ 154line 153 didn't jump to line 154 because the condition on line 153 was never true
154 return False
156 try:
157 env_vars = self._load_env_file()
158 env_vars[env_var] = value
159 self._save_env_file(env_vars)
161 # Track this variable
162 if env_var not in self._tracked_vars: 162 ↛ 165line 162 didn't jump to line 165 because the condition on line 162 was always true
163 self._tracked_vars.append(env_var)
165 return True
166 except (OSError, ValueError):
167 return False
169 def get_user_env(self, config_key: str) -> str | None:
170 """
171 Get a user environment variable value from a config key.
173 Args:
174 config_key: Configuration key (e.g., "log-level")
176 Returns:
177 Environment variable value or None
178 """
179 env_var = self.CONFIG_TO_ENV.get(config_key)
180 if not env_var: 180 ↛ 181line 180 didn't jump to line 181 because the condition on line 180 was never true
181 return None
183 env_vars = self._load_env_file()
184 return env_vars.get(env_var)
186 def remove_user_env(self, config_key: str) -> bool:
187 """
188 Remove a user environment variable.
190 Args:
191 config_key: Configuration key (e.g., "log-level")
193 Returns:
194 True if successful, False otherwise
195 """
196 env_var = self.CONFIG_TO_ENV.get(config_key)
197 if not env_var: 197 ↛ 198line 197 didn't jump to line 198 because the condition on line 197 was never true
198 return False
200 try:
201 env_vars = self._load_env_file()
202 if env_var in env_vars: 202 ↛ 207line 202 didn't jump to line 207 because the condition on line 202 was always true
203 del env_vars[env_var]
204 self._save_env_file(env_vars)
206 # Remove from tracked vars
207 if env_var in self._tracked_vars: 207 ↛ 210line 207 didn't jump to line 210 because the condition on line 207 was always true
208 self._tracked_vars.remove(env_var)
210 return True
211 except (OSError, ValueError):
212 return False
214 def remove_all_user_env(self) -> bool:
215 """
216 Remove all Ezpl user environment variables.
218 Returns:
219 True if successful, False otherwise
220 """
221 try:
222 env_vars = self._load_env_file()
223 ezpl_vars = {k: v for k, v in env_vars.items() if k.startswith("EZPL_")}
225 if not ezpl_vars: 225 ↛ 229line 225 didn't jump to line 229 because the condition on line 225 was always true
226 return True
228 # Remove all EZPL_ vars
229 for key in list(ezpl_vars.keys()):
230 del env_vars[key]
232 self._save_env_file(env_vars)
233 self._tracked_vars = []
235 return True
236 except (OSError, ValueError):
237 return False
239 def list_user_env(self) -> dict[str, str]:
240 """
241 List all user environment variables managed by Ezpl.
243 Returns:
244 Dictionary mapping environment variable names to values
245 """
246 env_vars = self._load_env_file()
247 return {k: v for k, v in env_vars.items() if k.startswith("EZPL_")}