|
7 | 7 | from pathlib import Path |
8 | 8 | from typing import Any |
9 | 9 |
|
10 | | -from dotenv import load_dotenv |
| 10 | +try: |
| 11 | + from dotenv import load_dotenv as _load_dotenv |
| 12 | +except ModuleNotFoundError: |
| 13 | + def _load_dotenv(dotenv_path: Path) -> None: |
| 14 | + for raw_line in dotenv_path.read_text(encoding="utf-8").splitlines(): |
| 15 | + line = raw_line.strip() |
| 16 | + if not line or line.startswith("#") or "=" not in line: |
| 17 | + continue |
| 18 | + key, value = line.split("=", 1) |
| 19 | + os.environ.setdefault(key.strip(), value.strip()) |
11 | 20 |
|
12 | 21 | from PalDefender import ( |
13 | 22 | GiveItem, |
|
22 | 31 |
|
23 | 32 | def build_parser() -> argparse.ArgumentParser: |
24 | 33 | parser = argparse.ArgumentParser( |
25 | | - description="Full example CLI for the PalDefender REST client.", |
| 34 | + description="Command-line interface for the PalDefender REST client.", |
| 35 | + ) |
| 36 | + parser.add_argument( |
| 37 | + "--env", |
| 38 | + help="Path to a .env file. Defaults to .env in the current working directory when present.", |
26 | 39 | ) |
27 | 40 | subparsers = parser.add_subparsers(dest="command", required=True) |
28 | 41 |
|
@@ -109,18 +122,30 @@ def build_parser() -> argparse.ArgumentParser: |
109 | 122 | return parser |
110 | 123 |
|
111 | 124 |
|
112 | | -def load_settings(env_path: Path) -> dict[str, Any]: |
113 | | - load_dotenv(env_path) |
| 125 | +def resolve_env_path(raw_env_path: str | None) -> Path | None: |
| 126 | + if raw_env_path: |
| 127 | + return Path(raw_env_path).expanduser().resolve() |
| 128 | + |
| 129 | + default_env_path = Path.cwd() / ".env" |
| 130 | + if default_env_path.is_file(): |
| 131 | + return default_env_path |
| 132 | + return None |
| 133 | + |
| 134 | + |
| 135 | +def load_settings(env_path: Path | None) -> dict[str, Any]: |
| 136 | + if env_path is not None: |
| 137 | + _load_dotenv(env_path) |
114 | 138 |
|
115 | 139 | base_url = os.getenv("PALDEFENDER_BASE_URL", "").strip() |
116 | 140 | bearer_token = os.getenv("PALDEFENDER_BEARER_TOKEN", "").strip() |
117 | 141 | display_address = os.getenv("PALDEFENDER_DISPLAY_ADDRESS", "").strip() or None |
118 | 142 | timeout_raw = os.getenv("PALDEFENDER_TIMEOUT", "30").strip() |
119 | 143 |
|
| 144 | + source = str(env_path) if env_path is not None else "environment variables" |
120 | 145 | if not base_url: |
121 | | - raise ValueError(f"PALDEFENDER_BASE_URL is required in {env_path}") |
| 146 | + raise ValueError(f"PALDEFENDER_BASE_URL is required in {source}") |
122 | 147 | if not bearer_token: |
123 | | - raise ValueError(f"PALDEFENDER_BEARER_TOKEN is required in {env_path}") |
| 148 | + raise ValueError(f"PALDEFENDER_BEARER_TOKEN is required in {source}") |
124 | 149 |
|
125 | 150 | try: |
126 | 151 | timeout = float(timeout_raw) |
@@ -224,9 +249,7 @@ def print_json(data: Any) -> None: |
224 | 249 | def main() -> int: |
225 | 250 | parser = build_parser() |
226 | 251 | args = parser.parse_args() |
227 | | - |
228 | | - example_dir = Path(__file__).resolve().parent |
229 | | - env_path = example_dir / ".env" |
| 252 | + env_path = resolve_env_path(args.env) |
230 | 253 |
|
231 | 254 | try: |
232 | 255 | settings = load_settings(env_path) |
@@ -284,7 +307,3 @@ def main() -> int: |
284 | 307 |
|
285 | 308 | print_json(result) |
286 | 309 | return 0 |
287 | | - |
288 | | - |
289 | | -if __name__ == "__main__": |
290 | | - raise SystemExit(main()) |
|
0 commit comments