Skip to content

Commit f8c0999

Browse files
committed
Centralize env/~ expansion and add dedupe key
Introduce a single _expand_user_and_env() helper to consistently expand environment variables and '~', and use it across path normalization and glob validation. Update _normalize_path() to rely on the helper and Path handling, switch file existence checks to use a Path object, and add _dedup_key() to normalize deduplication on case-insensitive filesystems (Windows). Replace scattered os.path.expandvars/os.path.expanduser calls with the new helper for more predictable cross-platform behavior.
1 parent 2510076 commit f8c0999

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

dlclivegui/cameras/backends/utils/gentl_discovery.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,35 @@ def cti_files_as_list(value) -> list[str]:
6161
return [s] if s else []
6262

6363

64+
def _expand_user_and_env(value: str) -> str:
65+
"""
66+
Expand environment variables and '~' in a string path/pattern.
67+
pathlib does not expand env vars, so we use os.path.expandvars for that part.
68+
"""
69+
if value is None:
70+
return ""
71+
s = str(value).strip()
72+
if not s:
73+
return ""
74+
# Expand env vars first (e.g., %VAR% / $VAR), then user home (~)
75+
s = os.path.expandvars(s)
76+
try:
77+
s = str(Path(s).expanduser())
78+
except Exception:
79+
# If expanduser fails for some reason, keep the env-expanded string
80+
pass
81+
return s
82+
83+
6484
def _normalize_path(p: str) -> str:
6585
"""
6686
Normalize a filesystem path in a cross-platform way:
6787
- expands ~ and environment variables
6888
- resolves to absolute where possible (without requiring existence)
6989
"""
70-
pp = Path(os.path.expandvars(os.path.expanduser(p)))
90+
expanded = _expand_user_and_env(p)
91+
pp = Path(expanded)
7192
try:
72-
# resolve(strict=False) will resolve as much as possible without raising if the path doesn't exist
7393
return str(pp.resolve(strict=False))
7494
except Exception:
7595
return str(pp.absolute())
@@ -101,6 +121,11 @@ def _split_env_paths(raw: str) -> list[str]:
101121
return out
102122

103123

124+
def _dedup_key(path_str: str) -> str:
125+
# Windows filesystem is case-insensitive by default -> normalize key case
126+
return path_str.casefold() if os.name == "nt" else path_str
127+
128+
104129
_GLOB_META_CHARS = set("*?[")
105130

106131

@@ -149,7 +174,7 @@ def _validate_glob_pattern(
149174
if not pattern or not str(pattern).strip():
150175
return False, "empty glob pattern"
151176

152-
expanded = os.path.expandvars(os.path.expanduser(pattern)).strip()
177+
expanded = _expand_user_and_env(pattern).strip()
153178

154179
# Basic traversal guard
155180
parts = Path(expanded).parts
@@ -291,7 +316,8 @@ def discover_cti_files(
291316

292317
def _add_candidate(path: str, reason_ctx: str) -> None:
293318
norm = _normalize_path(path)
294-
if must_exist and not Path(norm).is_file():
319+
p = Path(norm)
320+
if must_exist and not p.is_file():
295321
rejected.append((norm, f"not a file ({reason_ctx})"))
296322
return
297323
if not norm.lower().endswith(".cti"):
@@ -305,7 +331,7 @@ def _add_candidate(path: str, reason_ctx: str) -> None:
305331

306332
# Process glob patterns
307333
for pat in patterns:
308-
expanded_pat = os.path.expandvars(os.path.expanduser(pat))
334+
expanded_pat = _expand_user_and_env(pat)
309335

310336
if not allow_globs:
311337
rejected.append((_normalize_path(expanded_pat), "glob patterns disabled"))
@@ -350,7 +376,7 @@ def _add_candidate(path: str, reason_ctx: str) -> None:
350376
seen = set()
351377
unique: list[str] = []
352378
for c in candidates:
353-
key = c.lower() if os.name == "nt" else c # Windows case-insensitive
379+
key = _dedup_key(c)
354380
if key in seen:
355381
continue
356382
seen.add(key)

0 commit comments

Comments
 (0)