mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
fix(windows): sweep remaining bare read_text/write_text sites + linter rule
AST-driven pass over every Path.read_text()/write_text() without an explicit encoding= across non-test code: 71 sites in 34 files (skills_hub, hermes_cli/main+profiles+service_manager+container_boot, mem0/hindsight/honcho plugins, achievements dashboard, release/CI scripts, productivity+comfyui skill helpers, agent/*). Verified zero positional-encoding collisions before insertion; per-file compile() check after. Adds a check-windows-footguns rule flagging bare single-line read_text/write_text (multi-line forms stay covered by the AST guard test from #38985). Together with the salvaged contributor commits this retires the ~169-site bare file-I/O class (#37423's long tail).
This commit is contained in:
parent
adecb0d1a9
commit
75e0d52034
36 changed files with 103 additions and 75 deletions
|
|
@ -86,7 +86,7 @@ def _is_cron_provider_dir(path: Path) -> bool:
|
|||
if not init_file.exists():
|
||||
return False
|
||||
try:
|
||||
source = init_file.read_text(errors="replace")[:8192]
|
||||
source = init_file.read_text(errors="replace", encoding="utf-8")[:8192]
|
||||
return "register_cron_scheduler" in source or "CronScheduler" in source
|
||||
except Exception:
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -110,12 +110,12 @@ def load_tracked() -> List[Dict[str, Any]]:
|
|||
return []
|
||||
|
||||
try:
|
||||
return json.loads(tf.read_text())
|
||||
return json.loads(tf.read_text(encoding="utf-8"))
|
||||
except (json.JSONDecodeError, ValueError):
|
||||
bak = tf.with_suffix(".json.bak")
|
||||
if bak.exists():
|
||||
try:
|
||||
data = json.loads(bak.read_text())
|
||||
data = json.loads(bak.read_text(encoding="utf-8"))
|
||||
_log("WARN: tracked.json corrupted — restored from .bak")
|
||||
return data
|
||||
except Exception:
|
||||
|
|
@ -129,7 +129,7 @@ def save_tracked(tracked: List[Dict[str, Any]]) -> None:
|
|||
tf = get_tracked_file()
|
||||
tf.parent.mkdir(parents=True, exist_ok=True)
|
||||
tmp = tf.with_suffix(".json.tmp")
|
||||
tmp.write_text(json.dumps(tracked, indent=2))
|
||||
tmp.write_text(json.dumps(tracked, indent=2), encoding="utf-8")
|
||||
if tf.exists():
|
||||
shutil.copy2(tf, tf.with_suffix(".json.bak"))
|
||||
tmp.replace(tf)
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ class RealtimeSpeaker:
|
|||
if not self.queue_path.exists():
|
||||
return []
|
||||
out: list[dict] = []
|
||||
for line in self.queue_path.read_text().splitlines():
|
||||
for line in self.queue_path.read_text(encoding="utf-8").splitlines():
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
|
@ -281,10 +281,10 @@ class RealtimeSpeaker:
|
|||
if not remaining:
|
||||
# Keep the file but empty — consumers may be watching for
|
||||
# new writes via mtime, and delete-then-recreate is a race.
|
||||
self.queue_path.write_text("")
|
||||
self.queue_path.write_text("", encoding="utf-8")
|
||||
return
|
||||
self.queue_path.write_text(
|
||||
"\n".join(json.dumps(e) for e in remaining) + "\n"
|
||||
"\n".join(json.dumps(e) for e in remaining) + "\n", encoding="utf-8"
|
||||
)
|
||||
|
||||
def _append_processed(self, entry: dict, result: dict) -> None:
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ def load_state() -> Dict[str, Any]:
|
|||
if not path.exists():
|
||||
return {"unlocks": {}}
|
||||
try:
|
||||
return json.loads(path.read_text())
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
return {"unlocks": {}}
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ def load_state() -> Dict[str, Any]:
|
|||
def save_state(state: Dict[str, Any]) -> None:
|
||||
path = state_path()
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(state, indent=2, sort_keys=True))
|
||||
path.write_text(json.dumps(state, indent=2, sort_keys=True), encoding="utf-8")
|
||||
|
||||
|
||||
def _json_safe(value: Any) -> Any:
|
||||
|
|
@ -185,7 +185,7 @@ def load_snapshot() -> Optional[Dict[str, Any]]:
|
|||
if not path.exists():
|
||||
return None
|
||||
try:
|
||||
data = json.loads(path.read_text())
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if isinstance(data, dict):
|
||||
return data
|
||||
except Exception:
|
||||
|
|
@ -196,7 +196,7 @@ def load_snapshot() -> Optional[Dict[str, Any]]:
|
|||
def save_snapshot(data: Dict[str, Any]) -> None:
|
||||
path = snapshot_path()
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(_json_safe(data), indent=2, sort_keys=True))
|
||||
path.write_text(json.dumps(_json_safe(data), indent=2, sort_keys=True), encoding="utf-8")
|
||||
|
||||
|
||||
def load_checkpoint() -> Dict[str, Any]:
|
||||
|
|
@ -204,7 +204,7 @@ def load_checkpoint() -> Dict[str, Any]:
|
|||
if not path.exists():
|
||||
return {"schema_version": 1, "generated_at": 0, "sessions": {}}
|
||||
try:
|
||||
data = json.loads(path.read_text())
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
if isinstance(data, dict):
|
||||
data.setdefault("schema_version", 1)
|
||||
data.setdefault("generated_at", 0)
|
||||
|
|
@ -219,7 +219,7 @@ def load_checkpoint() -> Dict[str, Any]:
|
|||
def save_checkpoint(data: Dict[str, Any]) -> None:
|
||||
path = checkpoint_path()
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(_json_safe(data), indent=2, sort_keys=True))
|
||||
path.write_text(json.dumps(_json_safe(data), indent=2, sort_keys=True), encoding="utf-8")
|
||||
|
||||
|
||||
def session_fingerprint(meta: Dict[str, Any]) -> Dict[str, Any]:
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ def _is_memory_provider_dir(path: Path) -> bool:
|
|||
if not init_file.exists():
|
||||
return False
|
||||
try:
|
||||
source = init_file.read_text(errors="replace")[:8192]
|
||||
source = init_file.read_text(errors="replace", encoding="utf-8")[:8192]
|
||||
return "register_memory_provider" in source or "MemoryProvider" in source
|
||||
except Exception:
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ def _save_mem0_json(hermes_home: str, data: dict) -> None:
|
|||
except Exception:
|
||||
pass
|
||||
existing.update(data)
|
||||
config_path.write_text(json.dumps(existing, indent=2) + "\n")
|
||||
config_path.write_text(json.dumps(existing, indent=2) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def _setup_platform(hermes_home: str, config: dict, flags: dict[str, str]) -> None:
|
||||
|
|
@ -248,7 +248,7 @@ def _setup_platform(hermes_home: str, config: dict, flags: dict[str, str]) -> No
|
|||
config_path = Path(hermes_home) / "mem0.json"
|
||||
if config_path.exists():
|
||||
try:
|
||||
existing_config = json.loads(config_path.read_text())
|
||||
existing_config = json.loads(config_path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
|
@ -369,7 +369,7 @@ def _setup_selfhosted(hermes_home: str, config: dict, flags: dict[str, str]) ->
|
|||
config_path = Path(hermes_home) / "mem0.json"
|
||||
if config_path.exists():
|
||||
try:
|
||||
existing_config = json.loads(config_path.read_text())
|
||||
existing_config = json.loads(config_path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue