This commit is contained in:
Chirag Honnyal 2026-09-30 07:00:24 +05:30 • committed by GitHub
commit b7cd59f7e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 62 additions and 5 deletions

View file

@ -38,7 +38,7 @@ RESPONSE_TYPES: Final[dict[str, type]] = {
def _load_endpoints_config() -> dict:
"""Load the endpoints configuration from JSON file."""
config_path: Final = Path(__file__).parent / "endpoints.json"
with open(config_path) as f:
with open(config_path, encoding="utf-8") as f:
return json.load(f)

View file

@ -55,7 +55,7 @@ def load_snapshot() -> dict[str, dict] | None:
if not SNAPSHOT_FILE.exists():
return None
try:
with SNAPSHOT_FILE.open() as f:
with SNAPSHOT_FILE.open(encoding="utf-8") as f:
return json.load(f)
except (json.JSONDecodeError, OSError):
return None

View file

@ -30,7 +30,7 @@ from litellm.proxy.container_endpoints.ownership import (
def _load_endpoints_config() -> dict:
"""Load the endpoints configuration from JSON file."""
config_path: Final = Path(__file__).parent.parent.parent / "containers" / "endpoints.json"
with open(config_path) as f:
with open(config_path, encoding="utf-8") as f:
return json.load(f)

View file

@ -5390,7 +5390,7 @@ class ProxyConfig:
Load and parse a YAML file
"""
try:
with open(file_path, "r") as file:
with open(file_path, "r", encoding="utf-8") as file:
return yaml.safe_load(file) or {}
except Exception as e:
raise Exception(f"Error loading yaml file {file_path}: {e}")
@ -5411,7 +5411,7 @@ class ProxyConfig:
# Load existing config
## Yaml
if os.path.exists(f"{file_path}"):
with open(f"{file_path}", "r") as config_file:
with open(f"{file_path}", "r", encoding="utf-8") as config_file:
config = yaml.safe_load(config_file)
elif file_path is not None:
raise Exception(f"Config file not found: {file_path}")

View file

@ -14211,6 +14211,63 @@ async def test_ptu_rollup_job_not_registered_without_opt_in(monkeypatch):
assert len(scheduler.get_jobs()) > 0
CONFIG_WITH_NON_ASCII = """model_list:
- model_name: café-gpt
litellm_params:
model: openai/gpt-4o
api_key: sk-test
"""
def test_load_yaml_file_reads_non_ascii_config(tmp_path):
"""A UTF-8 config decoded with the locale encoding silently yields café-gpt on a cp1252 host,
so the wrong model name reaches routing with no error raised."""
from litellm.proxy.proxy_server import ProxyConfig
config_path = tmp_path / "config.yaml"
config_path.write_text(CONFIG_WITH_NON_ASCII, encoding="utf-8")
config = ProxyConfig()._load_yaml_file(str(config_path))
assert config["model_list"][0]["model_name"] == "café-gpt"
def test_load_yaml_file_reads_config_with_byte_undefined_in_cp1252(tmp_path):
"""Cafe plus U+0301 encodes to a 0x81 byte, which cp1252 has no mapping for, so this raised
UnicodeDecodeError rather than merely mangling the name."""
from litellm.proxy.proxy_server import ProxyConfig
config_path = tmp_path / "config.yaml"
config_path.write_text("model_list:\n - model_name: Café\n", encoding="utf-8")
config = ProxyConfig()._load_yaml_file(str(config_path))
assert config["model_list"][0]["model_name"] == "Café"
def test_load_yaml_file_specifies_an_encoding(tmp_path):
"""Asserting the decoded value passes on any UTF-8 host regardless of the fix, and CI is Linux.
Running the loader under warn_default_encoding fails on every platform instead."""
config_path = tmp_path / "config.yaml"
config_path.write_text(CONFIG_WITH_NON_ASCII, encoding="utf-8")
body = (
"import warnings\n"
"from litellm.proxy.proxy_server import ProxyConfig\n"
'warnings.simplefilter("error", EncodingWarning)\n'
f'config = ProxyConfig()._load_yaml_file(r"{config_path}")\n'
'assert config["model_list"][0]["model_name"] == "caf\u00e9-gpt", config\n'
'print("OK")\n'
)
proc = subprocess.run(
[sys.executable, "-X", "warn_default_encoding", "-W", "error::EncodingWarning", "-c", body],
capture_output=True,
text=True,
check=False,
)
assert "EncodingWarning" not in proc.stderr, proc.stderr
assert proc.returncode == 0, proc.stderr
@pytest.mark.asyncio
async def test_moderations_reraises_proxy_exception_unwrapped():
"""A 400 ProxyException from request validation must surface as-is,