diff --git a/src/apm_cli/config.py b/src/apm_cli/config.py index 0d453221..75028adf 100644 --- a/src/apm_cli/config.py +++ b/src/apm_cli/config.py @@ -16,7 +16,7 @@ def ensure_config_exists(): os.makedirs(CONFIG_DIR) if not os.path.exists(CONFIG_FILE): - with open(CONFIG_FILE, "w") as f: + with open(CONFIG_FILE, "w", encoding="utf-8") as f: json.dump({"default_client": "vscode"}, f) @@ -32,7 +32,7 @@ def get_config(): if _config_cache is not None: return _config_cache ensure_config_exists() - with open(CONFIG_FILE, "r") as f: + with open(CONFIG_FILE, "r", encoding="utf-8") as f: _config_cache = json.load(f) return _config_cache @@ -53,7 +53,7 @@ def update_config(updates): config = get_config() config.update(updates) - with open(CONFIG_FILE, "w") as f: + with open(CONFIG_FILE, "w", encoding="utf-8") as f: json.dump(config, f, indent=2) _invalidate_config_cache() diff --git a/src/apm_cli/marketplace/client.py b/src/apm_cli/marketplace/client.py index 6fba4edf..5d6da1e0 100644 --- a/src/apm_cli/marketplace/client.py +++ b/src/apm_cli/marketplace/client.py @@ -83,13 +83,13 @@ def _read_cache(name: str) -> Optional[Dict]: if not os.path.exists(data_path) or not os.path.exists(meta_path): return None try: - with open(meta_path, "r") as f: + with open(meta_path, "r", encoding="utf-8") as f: meta = json.load(f) fetched_at = meta.get("fetched_at", 0) ttl = meta.get("ttl_seconds", _CACHE_TTL_SECONDS) if time.time() - fetched_at > ttl: return None # Expired - with open(data_path, "r") as f: + with open(data_path, "r", encoding="utf-8") as f: return json.load(f) except (json.JSONDecodeError, OSError, KeyError) as exc: logger.debug("Cache read failed for '%s': %s", name, exc) @@ -102,7 +102,7 @@ def _read_stale_cache(name: str) -> Optional[Dict]: if not os.path.exists(data_path): return None try: - with open(data_path, "r") as f: + with open(data_path, "r", encoding="utf-8") as f: return json.load(f) except (json.JSONDecodeError, OSError): return None @@ -113,9 +113,9 @@ def _write_cache(name: str, data: Dict) -> None: data_path = _cache_data_path(name) meta_path = _cache_meta_path(name) try: - with open(data_path, "w") as f: + with open(data_path, "w", encoding="utf-8") as f: json.dump(data, f, indent=2) - with open(meta_path, "w") as f: + with open(meta_path, "w", encoding="utf-8") as f: json.dump( {"fetched_at": time.time(), "ttl_seconds": _CACHE_TTL_SECONDS}, f, diff --git a/src/apm_cli/marketplace/registry.py b/src/apm_cli/marketplace/registry.py index 3aa668d5..4ddab2dd 100644 --- a/src/apm_cli/marketplace/registry.py +++ b/src/apm_cli/marketplace/registry.py @@ -30,7 +30,7 @@ def _ensure_file() -> str: ensure_config_exists() path = _marketplaces_path() if not os.path.exists(path): - with open(path, "w") as f: + with open(path, "w", encoding="utf-8") as f: json.dump({"marketplaces": []}, f, indent=2) return path @@ -48,7 +48,7 @@ def _load() -> List[MarketplaceSource]: path = _ensure_file() try: - with open(path, "r") as f: + with open(path, "r", encoding="utf-8") as f: data = json.load(f) except (json.JSONDecodeError, OSError) as exc: logger.warning("Failed to read %s: %s", path, exc) @@ -71,7 +71,7 @@ def _save(sources: List[MarketplaceSource]) -> None: path = _ensure_file() data = {"marketplaces": [s.to_dict() for s in sources]} tmp = path + ".tmp" - with open(tmp, "w") as f: + with open(tmp, "w", encoding="utf-8") as f: json.dump(data, f, indent=2) os.replace(tmp, path) _registry_cache = list(sources) diff --git a/src/apm_cli/models/plugin.py b/src/apm_cli/models/plugin.py index aa486d37..40eba1cb 100644 --- a/src/apm_cli/models/plugin.py +++ b/src/apm_cli/models/plugin.py @@ -108,7 +108,7 @@ def from_path(cls, plugin_path: Path) -> "Plugin": if metadata_file is None: raise FileNotFoundError(f"Plugin metadata not found in any expected location: {plugin_path}") - with open(metadata_file, "r") as f: + with open(metadata_file, "r", encoding="utf-8") as f: metadata_dict = json.load(f) metadata = PluginMetadata.from_dict(metadata_dict) diff --git a/src/apm_cli/runtime/copilot_runtime.py b/src/apm_cli/runtime/copilot_runtime.py index 485057f1..39bee709 100644 --- a/src/apm_cli/runtime/copilot_runtime.py +++ b/src/apm_cli/runtime/copilot_runtime.py @@ -200,7 +200,7 @@ def get_mcp_servers(self) -> Dict[str, Any]: return {} try: - with open(mcp_config_path, 'r') as f: + with open(mcp_config_path, 'r', encoding="utf-8") as f: config = json.load(f) return config.get('servers', {}) except Exception as e: