Coverage for .venv/lib/python3.13/site-packages/litellm/proxy/policy_engine/condition_evaluator.py: 82%
30 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
1"""
2Condition Evaluator - Evaluates policy conditions.
4Supports model-based conditions with exact match or regex patterns.
5"""
7import re
9from litellm._logging import verbose_proxy_logger
10from litellm.types.proxy.policy_engine import (
11 PolicyCondition,
12 PolicyMatchContext,
13)
16class ConditionEvaluator:
17 """
18 Evaluates policy conditions against request context.
20 Supports model conditions with:
21 - Exact string match: "gpt-4"
22 - Regex pattern: "gpt-4.*"
23 - List of values: ["gpt-4", "gpt-4-turbo"]
24 """
26 @staticmethod
27 def evaluate(
28 condition: PolicyCondition | None,
29 context: PolicyMatchContext,
30 ) -> bool:
31 """
32 Evaluate a policy condition against a request context.
34 Args:
35 condition: The condition to evaluate (None = always matches)
36 context: The request context with team, key, model
38 Returns:
39 True if condition matches, False otherwise
40 """
41 # No condition means always matches
42 if condition is None: 42 ↛ 43line 42 didn't jump to line 43 because the condition on line 42 was never true
43 return True
45 # Check model condition
46 if condition.model is not None:
47 if not ConditionEvaluator._evaluate_model_condition(
48 condition=condition.model,
49 model=context.model,
50 ):
51 verbose_proxy_logger.debug(
52 "Condition failed: model=%s did not match %s", context.model, condition.model
53 )
54 return False
56 return True
58 @staticmethod
59 def _evaluate_model_condition(
60 condition: str | list[str],
61 model: str | None,
62 ) -> bool:
63 """
64 Evaluate a model condition.
66 Args:
67 condition: String (exact or regex) or list of strings
68 model: The model name to check
70 Returns:
71 True if model matches condition, False otherwise
72 """
73 if model is None:
74 return False
76 # Handle list of values
77 if isinstance(condition, list): 77 ↛ 78line 77 didn't jump to line 78 because the condition on line 77 was never true
78 return any(ConditionEvaluator._matches_pattern(pattern, model) for pattern in condition)
80 # Single value - check as pattern
81 return ConditionEvaluator._matches_pattern(condition, model)
83 @staticmethod
84 def _matches_pattern(pattern: str, value: str) -> bool:
85 """
86 Check if value matches pattern (exact match or regex).
88 Args:
89 pattern: Pattern to match (exact string or regex)
90 value: Value to check
92 Returns:
93 True if matches, False otherwise
94 """
95 # First try exact match
96 if pattern == value:
97 return True
99 # Try as regex pattern
100 try:
101 if re.fullmatch(pattern, value): 101 ↛ 102line 101 didn't jump to line 102 because the condition on line 101 was never true
102 return True
103 except re.error:
104 # Invalid regex, treat as literal string (already checked above)
105 pass
107 return False