mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-05 02:41:56 +00:00
Add unit test for MRO-aware method override detection
Tests that the fix using `getattr(type(self), method_name) is not getattr(CustomLogger, method_name)` correctly walks the full Method Resolution Order, unlike the buggy `method_name in type(self).__dict__` which only checks the immediate class.
This commit is contained in:
parent
31eaa70111
commit
33440858aa
1 changed files with 77 additions and 0 deletions
|
|
@ -1132,3 +1132,80 @@ def test_per_callback_redaction_proceeds_when_global_redaction_not_applied():
|
|||
|
||||
# Result should be different (redacted), not the same object
|
||||
assert result is not original_result
|
||||
|
||||
|
||||
def test_method_override_detection_walks_full_mro():
|
||||
"""
|
||||
Test that method override detection correctly walks the full Method Resolution Order (MRO),
|
||||
not just the immediate class's __dict__.
|
||||
|
||||
This tests the fix for a bug where:
|
||||
- `method_name in type(self).__dict__` only checks the immediate class
|
||||
- `getattr(type(self), method_name) is not getattr(CustomLogger, method_name)` walks the full MRO
|
||||
|
||||
The bug caused incorrect behavior when:
|
||||
- ClassA(CustomLogger) overrides a method
|
||||
- ClassB(ClassA) does NOT override the method
|
||||
- ClassB instance should still detect the override from ClassA
|
||||
"""
|
||||
from litellm.integrations.custom_logger import CustomLogger
|
||||
|
||||
# Case 1: Direct override - should be detected
|
||||
class DirectOverrideLogger(CustomLogger):
|
||||
def redact_standard_logging_payload_from_model_call_details(
|
||||
self, model_call_details, global_redaction_applied=False
|
||||
):
|
||||
# Custom implementation
|
||||
return {"custom": "redacted"}
|
||||
|
||||
direct_logger = DirectOverrideLogger()
|
||||
method_name = "redact_standard_logging_payload_from_model_call_details"
|
||||
|
||||
# Using the correct MRO-aware check
|
||||
is_overridden_mro = getattr(type(direct_logger), method_name) is not getattr(
|
||||
CustomLogger, method_name
|
||||
)
|
||||
assert is_overridden_mro is True, "Direct override should be detected"
|
||||
|
||||
# Case 2: Inherited override (the bug case) - should also be detected
|
||||
class InheritedOverrideLogger(DirectOverrideLogger):
|
||||
# Does NOT override the method - inherits from DirectOverrideLogger
|
||||
pass
|
||||
|
||||
inherited_logger = InheritedOverrideLogger()
|
||||
|
||||
# The buggy check (only checks immediate class __dict__) would return False
|
||||
buggy_check = method_name in type(inherited_logger).__dict__
|
||||
assert buggy_check is False, "Buggy check incorrectly misses inherited override"
|
||||
|
||||
# The correct MRO-aware check should return True
|
||||
is_overridden_mro = getattr(type(inherited_logger), method_name) is not getattr(
|
||||
CustomLogger, method_name
|
||||
)
|
||||
assert is_overridden_mro is True, "MRO check should detect inherited override"
|
||||
|
||||
# Case 3: No override - should NOT be detected as overridden
|
||||
class NoOverrideLogger(CustomLogger):
|
||||
# Does NOT override the method
|
||||
pass
|
||||
|
||||
no_override_logger = NoOverrideLogger()
|
||||
is_overridden_mro = getattr(type(no_override_logger), method_name) is not getattr(
|
||||
CustomLogger, method_name
|
||||
)
|
||||
assert is_overridden_mro is False, "No override should not be detected"
|
||||
|
||||
# Case 4: Verify actual behavior - inherited override should NOT skip redaction
|
||||
model_call_details = {
|
||||
"messages": [{"content": "secret"}],
|
||||
"standard_logging_object": {"response": "sensitive"},
|
||||
}
|
||||
|
||||
# With global_redaction_applied=True and an inherited override,
|
||||
# the method should NOT early-return (should proceed to custom implementation)
|
||||
result = inherited_logger.redact_standard_logging_payload_from_model_call_details(
|
||||
model_call_details=model_call_details,
|
||||
global_redaction_applied=True,
|
||||
)
|
||||
# DirectOverrideLogger returns {"custom": "redacted"}
|
||||
assert result == {"custom": "redacted"}, "Inherited override should execute custom logic"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue