Added ProxyObject + CLAUDE.md

This commit is contained in:
2025-12-03 21:20:20 +01:00
parent 0ef9523e6b
commit d8b1ef2e2c
5 changed files with 628 additions and 6 deletions

251
tests/test_proxyobject.py Normal file
View File

@@ -0,0 +1,251 @@
import pytest
from myutils.ProxyObject import ProxyObject
# Test fixtures
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class City:
def __init__(self, name, zip_code):
self.name = name
self.zip_code = zip_code
class Address:
def __init__(self, city, country):
self.city = city
self.country = country
class Employee:
def __init__(self, name, age, address):
self.name = name
self.age = age
self.address = address
@pytest.fixture
def person():
return Person("John", 30)
@pytest.fixture
def employee():
address = Address("Paris", "France")
return Employee("Alice", 25, address)
# ============================================================================
# Basic tests
# ============================================================================
def test_i_can_create_proxy_object_with_simple_mapping(person):
"""
ProxyObject should be created successfully with a simple mapping.
"""
mappings = {"display_name": "name"}
proxy = ProxyObject(person, mappings)
assert isinstance(proxy, ProxyObject)
def test_i_can_access_mapped_property(person):
"""
Accessing a mapped property should return the value from the source object.
"""
mappings = {"display_name": "name"}
proxy = ProxyObject(person, mappings)
assert proxy.display_name == "John"
def test_i_can_map_nested_properties(employee):
"""
Nested properties using dot notation should be mapped correctly.
"""
mappings = {"city_name": "address.city"}
proxy = ProxyObject(employee, mappings)
assert proxy.city_name == "Paris"
def test_i_can_map_nested_nested_properties():
address = Address(City("Paris", "75001"), "France")
employee2 = Employee("Alice", 25, address)
mappings = {"city_zip_code": "address.city.zip_code"}
proxy = ProxyObject(employee2, mappings)
assert proxy.city_zip_code == "75001"
def test_i_can_map_multiple_properties(employee):
"""
Multiple mappings should work simultaneously.
"""
mappings = {
"full_name": "name",
"years": "age",
"city_name": "address.city"
}
proxy = ProxyObject(employee, mappings)
assert proxy.full_name == "Alice"
assert proxy.years == 25
assert proxy.city_name == "Paris"
def test_i_can_manage_wild_card(employee):
mappings = {"*": ""}
proxy = ProxyObject(employee, mappings)
assert proxy.name == employee.name
assert proxy.age == employee.age
assert proxy.address == employee.address
def test_i_can_manage_wild_card_2(employee):
mappings = {"*": "*"}
proxy = ProxyObject(employee, mappings)
assert proxy.name == employee.name
assert proxy.age == employee.age
assert proxy.city == employee.address.city
assert proxy.country == employee.address.country
def test_i_can_manage_wild_card_on_nested_properties():
address = Address(City("Paris", "75001"), "France")
employee2 = Employee("Alice", 25, address)
mappings = {"name": "name", "*": "address"}
proxy = ProxyObject(employee2, mappings)
assert proxy.name == employee2.name
assert proxy.city == employee2.address.city
assert proxy.country == employee2.address.country
def test_i_can_manage_wild_card_on_multiple_properties():
address = Address(City("Paris", "75001"), "France")
employee2 = Employee("Alice", 25, address)
mappings = {"*": "address.*"}
proxy = ProxyObject(employee2, mappings)
assert proxy.name == employee2.address.city.name
assert proxy.zip_code == employee2.address.city.zip_code
assert proxy.country == employee2.address.country
# ============================================================================
# Edge case tests
# ============================================================================
def test_i_cannot_access_unmapped_property(person):
"""
Accessing an unmapped property should raise AttributeError.
"""
mappings = {"display_name": "name"}
proxy = ProxyObject(person, mappings)
with pytest.raises(AttributeError):
_ = proxy.unknown_property
def test_i_can_handle_missing_source_property(person):
"""
When the source property doesn't exist, the proxy should handle it gracefully.
The current implementation breaks the loop and assigns the last valid value.
"""
mappings = {"missing": "non_existent_attr"}
proxy = ProxyObject(person, mappings)
# The property exists in _props (because of break behavior)
# but contains the original object
assert proxy.missing == person
def test_i_can_handle_none_values():
"""
None values should be handled correctly.
"""
person = Person(None, 30)
mappings = {"display_name": "name"}
proxy = ProxyObject(person, mappings)
assert proxy.display_name is None
# ============================================================================
# Special methods tests
# ============================================================================
def test_proxy_objects_with_same_props_are_equal(person):
"""
Two ProxyObject instances with the same _props should be equal.
"""
mappings = {"display_name": "name", "years": "age"}
proxy1 = ProxyObject(person, mappings)
proxy2 = ProxyObject(person, mappings)
assert proxy1 == proxy2
def test_proxy_objects_with_different_props_are_not_equal(person):
"""
Two ProxyObject instances with different _props should not be equal.
"""
mappings1 = {"display_name": "name"}
mappings2 = {"years": "age"}
proxy1 = ProxyObject(person, mappings1)
proxy2 = ProxyObject(person, mappings2)
assert proxy1 != proxy2
def test_i_can_hash_proxy_object(person):
"""
ProxyObject should be hashable and usable in sets/dicts.
"""
mappings = {"display_name": "name", "years": "age"}
proxy = ProxyObject(person, mappings)
# Should not raise an exception
proxy_hash = hash(proxy)
assert isinstance(proxy_hash, int)
# Should be usable in a set
proxy_set = {proxy}
assert proxy in proxy_set
def test_repr_shows_key_when_present():
"""
When 'key' is present in _props, __repr__ should show it.
"""
person = Person("key_value", 30)
mappings = {"key": "name"}
proxy = ProxyObject(person, mappings)
repr_str = repr(proxy)
assert "key=key_value" in repr_str
def test_repr_truncates_long_content(person):
"""
When _props content is longer than 50 chars, __repr__ should truncate it.
"""
mappings = {
"very_long_property_name_1": "name",
"very_long_property_name_2": "age"
}
proxy = ProxyObject(person, mappings)
repr_str = repr(proxy)
assert "..." in repr_str
assert len(repr_str) < 100 # Should be truncated