litellm/tests/test_litellm/containers/test_container_utils.py
yuneng-jiang 6a0d03914c
test: drop the cwd-relative sys.path.insert calls from the test suite (#37802)
* test: drop the cwd-relative sys.path.insert calls from the test suite

TQ003 stands at 1,077 across 1,058 files, and 1,015 of them are the same shape:
sys.path.insert(0, os.path.abspath("../..")) and its deeper siblings. The
argument resolves against the working directory rather than the file, so from
the repo root, where every job runs pytest, it inserts the directory two levels
above the checkout. It has never pointed at litellm. The package is installed
into the environment anyway, which is what actually makes the import work, and
what the rule's message has said all along.

Removing them leaves 1,634 imports of sys and os with no remaining reference,
and those go too, except where another test module imports the name back out of
the file. The rest of TQ003 is 62 call sites that resolve against __file__ or a
variable, which are a different question and are left alone.

Collection is identical either way: 45,871 tests and the same 51 pre-existing
collection errors before and after, and ruff reports no new undefined name.

* test: drop the duplicate imports the sys.path sweep exposed to F811

* test(pre-call-utils): restore the os import the new bedrock tests need
2026-08-22 09:25:58 -07:00

261 lines
9.5 KiB
Python

import pytest
import litellm
from litellm.containers.utils import (
ContainerRequestUtils,
decode_managed_container_id_for_request,
)
from litellm.responses.utils import ResponsesAPIRequestUtils
from litellm.types.router import GenericLiteLLMParams
from litellm.llms.openai.containers.transformation import OpenAIContainerConfig
from litellm.types.containers.main import (
ContainerCreateOptionalRequestParams,
ContainerListOptionalRequestParams,
DeleteContainerFileResponse,
)
class TestContainerRequestUtils:
"""Test suite for container request utilities."""
def test_get_optional_params_container_create_basic(self):
"""Test that optional parameters are correctly processed for container creation."""
# Setup
config = OpenAIContainerConfig()
optional_params = ContainerCreateOptionalRequestParams(
{
"expires_after": {"anchor": "last_active_at", "minutes": 30},
"file_ids": ["file_123", "file_456"],
}
)
# Execute
result = ContainerRequestUtils.get_optional_params_container_create(
container_provider_config=config,
container_create_optional_params=optional_params,
)
# Assert
assert result == optional_params
assert "expires_after" in result
assert result["expires_after"]["minutes"] == 30
assert "file_ids" in result
assert result["file_ids"] == ["file_123", "file_456"]
def test_get_optional_params_container_create_unsupported_param(self):
"""Test that unsupported parameters are filtered out by ContainerCreateOptionalRequestParams."""
# Setup
config = OpenAIContainerConfig()
# ContainerCreateOptionalRequestParams will only accept valid parameters
# so this test verifies the type validation works correctly
valid_params = ContainerCreateOptionalRequestParams(
{
"expires_after": {"anchor": "last_active_at", "minutes": 30},
"file_ids": ["file_123"],
}
)
# Execute - should work fine with valid parameters
result = ContainerRequestUtils.get_optional_params_container_create(
container_provider_config=config,
container_create_optional_params=valid_params,
)
assert result["expires_after"]["minutes"] == 30
assert result["file_ids"] == ["file_123"]
def test_get_requested_container_create_optional_param(self):
"""Test filtering parameters to only include those in ContainerCreateOptionalRequestParams."""
# Setup
params = {
"name": "Test Container", # This should be excluded as it's required
"expires_after": {"anchor": "last_active_at", "minutes": 30},
"file_ids": ["file_123"],
"invalid_param": "value",
"custom_llm_provider": "openai", # This should be excluded
}
# Execute
result = ContainerRequestUtils.get_requested_container_create_optional_param(
params
)
# Assert
assert "expires_after" in result
assert "file_ids" in result
assert "invalid_param" not in result
assert "name" not in result
assert "custom_llm_provider" not in result
assert result["expires_after"]["minutes"] == 30
assert result["file_ids"] == ["file_123"]
def test_get_requested_container_list_optional_param(self):
"""Test filtering parameters for container list requests."""
# Setup
params = {
"after": "cntr_123",
"limit": 10,
"order": "desc",
"invalid_param": "value",
"custom_llm_provider": "openai", # This should be excluded
}
# Execute
result = ContainerRequestUtils.get_requested_container_list_optional_param(
params
)
# Assert
assert "after" in result
assert "limit" in result
assert "order" in result
assert "invalid_param" not in result
assert "custom_llm_provider" not in result
assert result["after"] == "cntr_123"
assert result["limit"] == 10
assert result["order"] == "desc"
def test_get_optional_params_container_create_empty_params(self):
"""Test handling of empty optional parameters."""
# Setup
config = OpenAIContainerConfig()
optional_params = ContainerCreateOptionalRequestParams({})
# Execute
result = ContainerRequestUtils.get_optional_params_container_create(
container_provider_config=config,
container_create_optional_params=optional_params,
)
# Assert
assert result == optional_params
assert len(result) == 0
def test_get_optional_params_container_create_with_none_values(self):
"""Test handling of None values in optional parameters."""
# Setup
config = OpenAIContainerConfig()
optional_params = ContainerCreateOptionalRequestParams(
{"expires_after": None, "file_ids": None}
)
# Execute
result = ContainerRequestUtils.get_optional_params_container_create(
container_provider_config=config,
container_create_optional_params=optional_params,
)
# Assert
assert result == optional_params
assert "expires_after" in result
assert "file_ids" in result
assert result["expires_after"] is None
assert result["file_ids"] is None
def test_get_requested_container_list_optional_param_partial(self):
"""Test filtering with only some list parameters present."""
# Setup
params = {
"limit": 5,
"custom_llm_provider": "openai", # Should be excluded
"timeout": 600, # Should be excluded
}
# Execute
result = ContainerRequestUtils.get_requested_container_list_optional_param(
params
)
# Assert
assert "limit" in result
assert "custom_llm_provider" not in result
assert "timeout" not in result
assert "after" not in result # Not present in input
assert "order" not in result # Not present in input
assert result["limit"] == 5
def test_container_create_optional_params_type_validation(self):
"""Test that ContainerCreateOptionalRequestParams validates types correctly."""
# Test with valid expires_after
valid_params = ContainerCreateOptionalRequestParams(
{
"expires_after": {"anchor": "last_active_at", "minutes": 20},
"file_ids": ["file_1", "file_2"],
}
)
assert valid_params["expires_after"]["anchor"] == "last_active_at"
assert valid_params["expires_after"]["minutes"] == 20
assert valid_params["file_ids"] == ["file_1", "file_2"]
def test_container_list_optional_params_type_validation(self):
"""Test that ContainerListOptionalRequestParams validates types correctly."""
# Test with valid parameters
valid_params = ContainerListOptionalRequestParams(
{"after": "cntr_123", "limit": 10, "order": "desc"}
)
assert valid_params["after"] == "cntr_123"
assert valid_params["limit"] == 10
assert valid_params["order"] == "desc"
def test_get_optional_params_with_supported_params_check(self):
"""Test that only supported parameters are accepted."""
# Setup
config = OpenAIContainerConfig()
# Get supported params to understand what should be allowed
supported_params = config.get_supported_openai_params()
# Create params with only valid parameters
test_params = {"expires_after": {"anchor": "last_active_at", "minutes": 15}}
optional_params = ContainerCreateOptionalRequestParams(test_params)
# Execute - should work fine with supported params
result = ContainerRequestUtils.get_optional_params_container_create(
container_provider_config=config,
container_create_optional_params=optional_params,
)
assert result["expires_after"]["minutes"] == 15
def test_decode_managed_container_id_returns_provider_container_id(self):
"""Managed IDs must decode to the short ID sent on upstream requests."""
inner = "cntr_69d4ff00deadbeef"
managed = ResponsesAPIRequestUtils._build_container_id(
custom_llm_provider="openai",
model_id=None,
container_id=inner,
)
assert len(managed) > len(inner)
litellm_params: GenericLiteLLMParams = GenericLiteLLMParams()
original_id, provider, updated = decode_managed_container_id_for_request(
managed, "openai", litellm_params
)
assert original_id == inner
assert provider == "openai"
assert updated is litellm_params
class TestDeleteContainerFileResponseWireFormat:
"""OpenAI / Azure return ``container.file.deleted`` on DELETE file."""
def test_accepts_openai_dot_notation(self):
m = DeleteContainerFileResponse(
id="cfile_abc",
object="container.file.deleted",
deleted=True,
)
assert m.object == "container.file.deleted"
def test_accepts_legacy_underscore(self):
m = DeleteContainerFileResponse(
id="cfile_abc",
object="container_file.deleted",
deleted=True,
)
assert m.object == "container_file.deleted"