diff --git a/tests/hermes_cli/test_plugins_cmd.py b/tests/hermes_cli/test_plugins_cmd.py index 1f38fca04749f..2c49b12441889 100644 --- a/tests/hermes_cli/test_plugins_cmd.py +++ b/tests/hermes_cli/test_plugins_cmd.py @@ -189,14 +189,14 @@ class TestReadManifest: assert result == {} def test_invalid_yaml_returns_empty_and_logs(self, tmp_path, caplog): - (tmp_path / "plugin.yaml").write_text(": : : bad yaml [[[") + (tmp_path / "plugin.yaml").write_text(": : : bad yaml [[[", encoding="utf-8") with caplog.at_level(logging.WARNING, logger="hermes_cli.plugins_cmd"): result = _read_manifest(tmp_path) assert result == {} assert any("Failed to read plugin.yaml" in r.message for r in caplog.records) def test_empty_file_returns_empty(self, tmp_path): - (tmp_path / "plugin.yaml").write_text("") + (tmp_path / "plugin.yaml").write_text("", encoding="utf-8") result = _read_manifest(tmp_path) assert result == {} @@ -388,7 +388,7 @@ class TestCopyExampleFiles: # Create example file example_file = tmp_path / "config.yaml.example" - example_file.write_text("key: value") + example_file.write_text("key: value", encoding="utf-8") _copy_example_files(tmp_path, console) @@ -404,7 +404,7 @@ class TestCopyExampleFiles: # Create example file example_file = tmp_path / "config.yaml.example" - example_file.write_text("key: value") + example_file.write_text("key: value", encoding="utf-8") # Mock shutil.copy2 to raise an error with patch( @@ -497,10 +497,10 @@ class TestProviderDiscovery: """Saving a context engine persists to config.yaml.""" monkeypatch.setenv("HERMES_HOME", str(tmp_path)) config_file = tmp_path / "config.yaml" - config_file.write_text("context:\n engine: compressor\n") + config_file.write_text("context:\n engine: compressor\n", encoding="utf-8") from hermes_cli.plugins_cmd import _save_context_engine _save_context_engine("lcm") - content = yaml.safe_load(config_file.read_text()) + content = yaml.safe_load(config_file.read_text(encoding="utf-8")) assert content["context"]["engine"] == "lcm" @@ -525,7 +525,7 @@ class TestNoAutoActivation: # This tests the run_agent.py logic indirectly by checking that the # code path for default config doesn't call get_plugin_context_engine. import run_agent as ra_module - source = open(ra_module.__file__).read() + source = Path(ra_module.__file__).read_text(encoding="utf-8") # The old code had: "Even with default config, check if a plugin registered one" # The fix removes this. Verify it's gone. assert "Even with default config, check if a plugin registered one" not in source @@ -545,16 +545,19 @@ class TestSubdirInstallE2E: repo_root.mkdir(parents=True, exist_ok=True) # Root-level noise: docs + tests that should NOT be installed. - (repo_root / "README.md").write_text("# Monorepo docs\n") + (repo_root / "README.md").write_text("# Monorepo docs\n", encoding="utf-8") (repo_root / "tests").mkdir() - (repo_root / "tests" / "test_x.py").write_text("def test_x():\n pass\n") + (repo_root / "tests" / "test_x.py").write_text( + "def test_x():\n pass\n", encoding="utf-8" + ) # The actual plugin in a subdirectory. plugin_dir = repo_root / "my-plugin" plugin_dir.mkdir() (plugin_dir / "plugin.yaml").write_text( - "name: my-plugin\nmanifest_version: 1\ndescription: A subdir plugin\n" + "name: my-plugin\nmanifest_version: 1\ndescription: A subdir plugin\n", + encoding="utf-8", ) - (plugin_dir / "__init__.py").write_text("# plugin entry\n") + (plugin_dir / "__init__.py").write_text("# plugin entry\n", encoding="utf-8") env = { **os.environ, diff --git a/tests/stress/test_atypical_scenarios.py b/tests/stress/test_atypical_scenarios.py index 936dbaf5baf61..ed537956ce855 100644 --- a/tests/stress/test_atypical_scenarios.py +++ b/tests/stress/test_atypical_scenarios.py @@ -705,7 +705,7 @@ def _idempotency_race_worker(hermes_home: str, key: str, result_file: str, ) finally: conn.close() - with open(result_file, "w") as f: + with open(result_file, "w", encoding="utf-8") as f: f.write(tid) @@ -731,12 +731,16 @@ def _(home, kb): p.start() time.sleep(0.1) # let them hit the spin # Fire the gun - with open(barrier, "w") as f: + with open(barrier, "w", encoding="utf-8") as f: f.write("go") for p in procs: p.join(timeout=10) - tids = [open(r).read().strip() for r in results if os.path.exists(r)] + tids = [ + Path(r).read_text(encoding="utf-8").strip() + for r in results + if os.path.exists(r) + ] assert len(tids) == 2, f"only {len(tids)} workers finished" assert tids[0] == tids[1], ( f"idempotency key race produced two different tasks: {tids}" diff --git a/tests/tools/test_web_tools_truncate.py b/tests/tools/test_web_tools_truncate.py index b89466fe6540e..d1dab454fe7fb 100644 --- a/tests/tools/test_web_tools_truncate.py +++ b/tests/tools/test_web_tools_truncate.py @@ -6,6 +6,7 @@ _get_extract_char_limit, and the end-to-end web_extract_tool truncation behavior import asyncio import json import os +from pathlib import Path from unittest.mock import patch import pytest @@ -49,7 +50,7 @@ class TestTruncation: path_line = next(ln for ln in out.splitlines() if "Full text saved to:" in ln) stored_path = path_line.split("Full text saved to:", 1)[1].strip() assert os.path.exists(stored_path) - full = open(stored_path).read() + full = Path(stored_path).read_text(encoding="utf-8") assert "UNIQUE_MIDDLE_MARKER" in full assert "row 2500" in full # the omitted-middle row is in the stored file