NamedValue Design¶
The NamedValue
class implements a type-safe container for named values with built-in validation and serialization support. It follows several key design principles to ensure robust and flexible value handling.
Core Design Principles¶
1. Type Safety¶
The NamedValue
class uses Python's generic typing system to enforce type safety at both runtime and static analysis time:
# Type-safe value container
array_value = NamedValue[np.ndarray]("my_array", value=np.array([1, 2, 3]))
int_value = NamedValue[int]("my_int", value=42)
Type safety is enforced through:
- Generic type parameters (NamedValue[T]
)
- Runtime type validation
- Automatic type conversion when possible
- Clear error messages when types don't match
2. Value Immutability¶
Values are immutable by default after initial setting to prevent accidental modifications:
value = NamedValue[int]("counter", 1)
value.value = 2 # Raises ValueError - value is frozen
value.force_set_value(2) # Explicit override when needed
3. Flexible Type Conversion¶
The system attempts to convert values to the correct type when possible:
# String to int conversion
int_value = NamedValue[int]("count", "123") # Automatically converts to int(123)
# Float to int conversion
int_value = NamedValue[int]("count", 123.0) # Automatically converts to int(123)
4. Inheritance Support¶
Two different patterns are supported for extending NamedValue
:
-
Direct generic usage:
-
Subclass with custom behavior:
Error Handling Design¶
The class implements a sophisticated error handling system that distinguishes between different usage patterns:
-
Direct Usage Errors (TypeError):
-
Subclass Usage Errors (ValueError):
Testing Strategy¶
The design principles are verified through comprehensive testing:
1. Type Safety Tests¶
def test_type_checking(self):
# Test with explicit type parameter
class IntValue(NamedValue[int]):
pass
# Valid integer assignment
int_value = IntValue("test", 42)
assert int_value.value == 42
# Valid string that can be cast to int
str_int_value = IntValue("test2", "123")
assert str_int_value.value == 123
# Invalid type that can't be cast
with pytest.raises(TypeError):
IntValue("test3", "not an integer")
2. Inheritance Tests¶
def test_type_casting_inheritance(self):
class IntegerValue(NamedValue[int]):
def __init__(self, name: str, value: int = None):
super().__init__(name, value)
# Test valid assignment
int_value = IntegerValue("test", 42)
assert isinstance(int_value.value, int)
# Test type hints are preserved
with pytest.raises(ValueError):
IntegerValue("test", "not an integer")
3. Value Immutability Tests¶
def test_value_immutability(self):
value = NamedValue[int]("test", 42)
# Cannot change value after setting
with pytest.raises(ValueError):
value.value = 43
# Can force change value when needed
value.force_set_value(43)
assert value.value == 43
Serialization Support¶
The class implements JSON serialization support through pydantic:
value = NamedValue[int]("counter", 42)
serialized = value.model_dump_json()
deserialized = NamedValue.model_validate_json(serialized)
Usage Guidelines¶
-
Use direct generic syntax for simple value containers:
-
Create subclasses for custom validation or behavior:
-
Use
force_set_value()
only when value mutability is explicitly needed:
Best Practices¶
-
Always specify the type parameter for clarity:
-
Use meaningful names that describe the value's purpose:
-
Handle type conversion errors appropriately:
By following these design principles and usage patterns, NamedValue
provides a robust and type-safe way to manage named values in your application.