An inherited HERMES_HOME can defeat a test bundle's data-directory suffix. Older Windows installers also persisted that variable in the user registry. This gives the app fresh UI state while its backend reads existing sessions. Add --bundle-unset NAME, encoded as null in the existing bundle environment object. Apply each clear as an explicit empty value before module startup. Do not restore an explicitly empty HERMES_HOME from the Windows registry. Ordinary defaults still preserve runtime overrides. Verified the release parser, builder handoff, compiled startup ordering, registry opt-out, and child environment with focused regression tests. A native Windows probe passed with an inherited home. No MSIX was rebuilt.
38 lines
1.5 KiB
Python
38 lines
1.5 KiB
Python
"""Non-secret environment defaults and explicit clears carried by a desktop bundle."""
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Sequence
|
|
import json
|
|
import re
|
|
|
|
|
|
def validate(values: object) -> dict[str, str | None]:
|
|
if not isinstance(values, dict):
|
|
raise ValueError("Bundle environment must be a JSON object")
|
|
for key, value in values.items():
|
|
if not isinstance(key, str) or not re.fullmatch(r"[A-Za-z_][A-Za-z0-9_]*", key):
|
|
raise ValueError("Bundle environment names must be valid environment identifiers")
|
|
if value is not None and (not isinstance(value, str) or "\0" in value):
|
|
raise ValueError(f"Bundle environment value for {key} must be a string without NUL or null")
|
|
return values
|
|
|
|
|
|
def parse_assignments(assignments: list[str], unset: Sequence[str] = ()) -> dict[str, str | None]:
|
|
values: dict[str, str | None] = {}
|
|
for assignment in assignments:
|
|
key, separator, value = assignment.partition("=")
|
|
if not separator:
|
|
raise ValueError("--bundle-env requires NAME=VALUE")
|
|
if key in values:
|
|
raise ValueError(f"Duplicate bundle environment name: {key}")
|
|
values[key] = value
|
|
for key in unset:
|
|
if key in values:
|
|
raise ValueError(f"Duplicate bundle environment name: {key}")
|
|
values[key] = None
|
|
return validate(values)
|
|
|
|
|
|
def decode(raw: str) -> dict[str, str | None]:
|
|
return validate(json.loads(raw or "{}"))
|