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

1"""OS, environment, and platform helpers for lilbee.""" 

2 

3import os 

4import sys 

5from pathlib import Path 

6 

7 

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) 

11 

12 

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) 

19 

20 

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) 

27 

28 

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) 

35 

36 

37def default_data_dir() -> Path: 

38 """Return platform-appropriate data directory. 

39 

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" 

51 

52 

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 

64 

65 

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")