mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-26 01:12:21 +00:00
* refactor(ocr): remove the Python OCR execution path and require the Rust route Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fmt * refactor(ocr): tidy the native OCR passthrough binding Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * style(ocr): ruff format the azure passthrough transformation Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor(ocr): resolve passthrough OCR costing in one Rust call Replace passthrough_url/passthrough_transform with passthrough_response, which matches the relayed endpoint against each Azure config's path segments instead of building a fake request to call get_complete_url. The binding drops the unused headers, status and api_base arguments. Catch the ValueError/RuntimeError the binding raises so a relayed body that is not OCR-shaped falls back to the passthrough object instead of failing logging, and cover the relay against the real binding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ocr): drop the unused LlmProviders import from health check helpers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: drop the ocr_testing job now that tests/ocr_tests is gone Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ocr): restore the live OCR matrix and the ocr_testing job The public litellm.ocr / aocr / Router interface is unchanged by the Rust migration, so the live provider matrix still applies. Drops the stale VCR skip list for the deleted test_rust_bridge.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ocr): import Final in the health check helper tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Yujong Lee <yujong@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
88 lines
2.8 KiB
Python
88 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
from collections import Counter
|
|
from collections.abc import Mapping
|
|
from types import MappingProxyType
|
|
from typing import Final
|
|
|
|
from pydantic import BaseModel, ConfigDict, field_validator, model_validator
|
|
from typing_extensions import Self
|
|
|
|
from ..reporting.models import SdkFunction
|
|
|
|
|
|
class _ContractModel(BaseModel):
|
|
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
|
|
|
|
def _clean_unique(values: tuple[str, ...], field: str) -> tuple[str, ...]:
|
|
cleaned: Final = tuple(value.strip().rstrip("/") for value in values)
|
|
if not cleaned or any(not value for value in cleaned):
|
|
raise ValueError(f"{field} must contain non-empty paths")
|
|
duplicates: Final = tuple(value for value, count in Counter(cleaned).items() if count > 1)
|
|
if duplicates:
|
|
raise ValueError(f"{field} contains duplicates: {sorted(duplicates)}")
|
|
return cleaned
|
|
|
|
|
|
class UnitParityExclusionSpec(_ContractModel):
|
|
nodeid: str
|
|
reason: str
|
|
|
|
@field_validator("nodeid", "reason")
|
|
@classmethod
|
|
def validate_fields(cls, value: str) -> str:
|
|
stripped: Final = value.strip()
|
|
if not stripped:
|
|
raise ValueError("must be a non-empty string")
|
|
return stripped
|
|
|
|
|
|
class UnitParitySpec(_ContractModel):
|
|
python_selectors: tuple[str, ...]
|
|
exclusions: tuple[UnitParityExclusionSpec, ...] = ()
|
|
|
|
@field_validator("python_selectors")
|
|
@classmethod
|
|
def validate_python_selectors(cls, value: tuple[str, ...]) -> tuple[str, ...]:
|
|
return _clean_unique(value, "unit parity python_selectors")
|
|
|
|
@model_validator(mode="after")
|
|
def validate_exclusions(self) -> Self:
|
|
nodeids: Final = tuple(exclusion.nodeid for exclusion in self.exclusions)
|
|
duplicates: Final = tuple(nodeid for nodeid, count in Counter(nodeids).items() if count > 1)
|
|
if duplicates:
|
|
raise ValueError(f"unit parity exclusions contain duplicate nodeids: {sorted(duplicates)}")
|
|
return self
|
|
|
|
|
|
class RustUnitSpec(_ContractModel):
|
|
cargo_manifest: str
|
|
cargo_filter: str
|
|
cargo_package: str | None = None
|
|
|
|
@field_validator("cargo_manifest", "cargo_filter")
|
|
@classmethod
|
|
def validate_required_fields(cls, value: str) -> str:
|
|
stripped: Final = value.strip()
|
|
if not stripped:
|
|
raise ValueError("must be a non-empty string")
|
|
return stripped
|
|
|
|
@field_validator("cargo_package")
|
|
@classmethod
|
|
def validate_package(cls, value: str | None) -> str | None:
|
|
if value is None:
|
|
return None
|
|
stripped: Final = value.strip()
|
|
if not stripped:
|
|
raise ValueError("must be a non-empty string when provided")
|
|
return stripped
|
|
|
|
|
|
class UnitTestContract(_ContractModel):
|
|
unit_parity: UnitParitySpec
|
|
rust: RustUnitSpec
|
|
|
|
|
|
UNIT_TEST_CONTRACTS: Final[Mapping[SdkFunction, UnitTestContract]] = MappingProxyType({})
|