Coverage for src / lilbee / platform.py: 100%
39 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-16 08:27 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-16 08:27 +0000
1"""OS, environment, and platform helpers for lilbee."""
3import os
4import sys
5from pathlib import Path
8def env(key: str, default: str) -> str:
9 """Read a LILBEE_<key> environment variable with fallback."""
10 return os.environ.get(f"LILBEE_{key}", default)
13def env_int(key: str, default: int) -> int:
14 """Read a LILBEE_<key> environment variable as int with fallback."""
15 raw = os.environ.get(f"LILBEE_{key}")
16 if raw is None:
17 return default
18 return int(raw)
21def env_float(key: str, default: float | None = None) -> float | None:
22 """Read a LILBEE_<key> environment variable as float with fallback."""
23 raw = os.environ.get(f"LILBEE_{key}")
24 if raw is None:
25 return default
26 return float(raw)
29def env_int_optional(key: str) -> int | None:
30 """Read a LILBEE_<key> environment variable as optional int."""
31 raw = os.environ.get(f"LILBEE_{key}")
32 if raw is None:
33 return None
34 return int(raw)
37def default_data_dir() -> Path:
38 """Return platform-appropriate data directory.
40 - macOS: ~/Library/Application Support/lilbee
41 - Windows: %LOCALAPPDATA%/lilbee
42 - Linux: ~/.local/share/lilbee (XDG_DATA_HOME)
43 """
44 if sys.platform == "darwin":
45 base = Path.home() / "Library" / "Application Support"
46 elif sys.platform == "win32":
47 base = Path(os.environ.get("LOCALAPPDATA", Path.home() / "AppData" / "Local"))
48 else:
49 base = Path(os.environ.get("XDG_DATA_HOME", Path.home() / ".local" / "share"))
50 return base / "lilbee"
53def find_local_root(start: Path | None = None) -> Path | None:
54 """Walk up from start (default: cwd) looking for .lilbee/ directory."""
55 current = start or Path.cwd()
56 while True:
57 candidate = current / ".lilbee"
58 if candidate.is_dir():
59 return candidate
60 parent = current.parent
61 if parent == current:
62 return None
63 current = parent
66def is_ignored_dir(name: str, ignore_dirs: frozenset[str]) -> bool:
67 """Return True if a directory name should be skipped during traversal."""
68 return name.startswith(".") or name in ignore_dirs or name.endswith(".egg-info")