examples.31_dataclass_integration
Demonstrates how to use ConstrainedValue types (like
EnumValue and RangeValue) inside a dataclass-style
configuration object to validate and normalize input data.
This example shows:
- How to wrap constrained values within a dataclass.
- How to perform field-by-field validation during initialization.
- How to return a tuple of
(ok, result)indicating success or errors.
Run directly:
python examples/31_dataclass_integration.py
Expected output:
OK: True WidgetConfig(name='Gizmo', color='green', slots=4) OK2: False {'color': "Value must be one of ('red', 'green', 'blue'), got purple", 'slots': 'Value must be greater than or equal to 1, got 0'}
1"""Demonstrates how to use :class:`ConstrainedValue` types (like 2:class:`EnumValue` and :class:`RangeValue`) inside a dataclass-style 3configuration object to validate and normalize input data. 4 5This example shows: 6 * How to wrap constrained values within a dataclass. 7 * How to perform field-by-field validation during initialization. 8 * How to return a tuple of `(ok, result)` indicating success or errors. 9 10Run directly: 11 12 python examples/31_dataclass_integration.py 13 14Expected output: 15 16 OK: True WidgetConfig(name='Gizmo', color='green', slots=4) 17 OK2: False {'color': "Value must be one of ('red', 'green', 'blue'), got purple", 18 'slots': 'Value must be greater than or equal to 1, got 0'} 19""" 20 21import sys 22import pathlib 23from dataclasses import dataclass 24from enum import Enum 25from typing import Any, Dict, Tuple, Union 26 27# --------------------------------------------------------------------------- 28# Make repo root importable when running this file directly 29# --------------------------------------------------------------------------- 30sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1])) 31 32from constrained_values import EnumValue, RangeValue 33 34 35class Color(Enum): 36 """An enumeration of valid widget colors.""" 37 RED = "red" 38 GREEN = "green" 39 BLUE = "blue" 40 41 42@dataclass 43class WidgetConfig: 44 """A dataclass-like configuration object that uses constrained fields. 45 46 Attributes: 47 name: The name of the widget (unvalidated string). 48 color: Validated color, as a :class:`Color` enum member. 49 slots: Validated integer slot count between 1 and 16. 50 """ 51 52 name: str 53 color: Any 54 slots: Any 55 56 @classmethod 57 def from_input(cls, name: str, color: Any, slots: Any) -> Tuple[bool, Union["WidgetConfig", Dict[str, str]]]: 58 """Validate input and construct a `WidgetConfig` instance. 59 60 Wraps input fields in :class:`ConstrainedValue` types to ensure 61 they meet constraints before constructing the dataclass. 62 63 Args: 64 name: The widget's name (any string). 65 color: The color input (enum value or string). 66 slots: The slot count to validate (integer). 67 68 Returns: 69 Tuple[bool, Union[WidgetConfig, Dict[str, str]]]: 70 * `(True, WidgetConfig)` if all validations succeed. 71 * `(False, errors_dict)` if one or more validations fail. 72 """ 73 cv_color = EnumValue(color, Color) 74 cv_slots = RangeValue(slots, 1, 16) 75 76 ok = cv_color.ok and cv_slots.ok 77 if not ok: 78 errors: Dict[str, str] = {} 79 if not cv_color.ok: 80 errors["color"] = cv_color.details 81 if not cv_slots.ok: 82 errors["slots"] = cv_slots.details 83 return False, errors 84 85 return True, cls(name=name, color=cv_color.value, slots=cv_slots.value) 86 87 88def main() -> None: 89 """Run the dataclass integration demonstration. 90 91 Steps: 92 1. Construct a valid configuration using `"Gizmo", "green", 4"`. 93 2. Attempt to construct an invalid configuration with `"purple", 0"`. 94 3. Print the success flag and resulting object or error dictionary. 95 96 Prints: 97 * `"OK: True WidgetConfig(name='Gizmo', color='green', slots=4)"` 98 * `"OK2: False {'color': "Value must be one of ('red', 'green', 'blue'), 99 * got purple", 'slots': 'Value must be greater than or equal to 1, got 0'}"` 100 """ 101 ok, res = WidgetConfig.from_input("Gizmo", "green", 4) 102 print("OK:", ok, res) 103 104 ok2, res2 = WidgetConfig.from_input("Oops", "purple", 0) 105 print("OK2:", ok2, res2) 106 107 108if __name__ == "__main__": 109 main()
36class Color(Enum): 37 """An enumeration of valid widget colors.""" 38 RED = "red" 39 GREEN = "green" 40 BLUE = "blue"
An enumeration of valid widget colors.
Inherited Members
- enum.Enum
- name
- value
43@dataclass 44class WidgetConfig: 45 """A dataclass-like configuration object that uses constrained fields. 46 47 Attributes: 48 name: The name of the widget (unvalidated string). 49 color: Validated color, as a :class:`Color` enum member. 50 slots: Validated integer slot count between 1 and 16. 51 """ 52 53 name: str 54 color: Any 55 slots: Any 56 57 @classmethod 58 def from_input(cls, name: str, color: Any, slots: Any) -> Tuple[bool, Union["WidgetConfig", Dict[str, str]]]: 59 """Validate input and construct a `WidgetConfig` instance. 60 61 Wraps input fields in :class:`ConstrainedValue` types to ensure 62 they meet constraints before constructing the dataclass. 63 64 Args: 65 name: The widget's name (any string). 66 color: The color input (enum value or string). 67 slots: The slot count to validate (integer). 68 69 Returns: 70 Tuple[bool, Union[WidgetConfig, Dict[str, str]]]: 71 * `(True, WidgetConfig)` if all validations succeed. 72 * `(False, errors_dict)` if one or more validations fail. 73 """ 74 cv_color = EnumValue(color, Color) 75 cv_slots = RangeValue(slots, 1, 16) 76 77 ok = cv_color.ok and cv_slots.ok 78 if not ok: 79 errors: Dict[str, str] = {} 80 if not cv_color.ok: 81 errors["color"] = cv_color.details 82 if not cv_slots.ok: 83 errors["slots"] = cv_slots.details 84 return False, errors 85 86 return True, cls(name=name, color=cv_color.value, slots=cv_slots.value)
A dataclass-like configuration object that uses constrained fields.
Attributes:
- name: The name of the widget (unvalidated string).
- color: Validated color, as a
Colorenum member. - slots: Validated integer slot count between 1 and 16.
57 @classmethod 58 def from_input(cls, name: str, color: Any, slots: Any) -> Tuple[bool, Union["WidgetConfig", Dict[str, str]]]: 59 """Validate input and construct a `WidgetConfig` instance. 60 61 Wraps input fields in :class:`ConstrainedValue` types to ensure 62 they meet constraints before constructing the dataclass. 63 64 Args: 65 name: The widget's name (any string). 66 color: The color input (enum value or string). 67 slots: The slot count to validate (integer). 68 69 Returns: 70 Tuple[bool, Union[WidgetConfig, Dict[str, str]]]: 71 * `(True, WidgetConfig)` if all validations succeed. 72 * `(False, errors_dict)` if one or more validations fail. 73 """ 74 cv_color = EnumValue(color, Color) 75 cv_slots = RangeValue(slots, 1, 16) 76 77 ok = cv_color.ok and cv_slots.ok 78 if not ok: 79 errors: Dict[str, str] = {} 80 if not cv_color.ok: 81 errors["color"] = cv_color.details 82 if not cv_slots.ok: 83 errors["slots"] = cv_slots.details 84 return False, errors 85 86 return True, cls(name=name, color=cv_color.value, slots=cv_slots.value)
Validate input and construct a WidgetConfig instance.
Wraps input fields in ConstrainedValue types to ensure
they meet constraints before constructing the dataclass.
Arguments:
- name: The widget's name (any string).
- color: The color input (enum value or string).
- slots: The slot count to validate (integer).
Returns:
Tuple[bool, Union[WidgetConfig, Dict[str, str]]]: *
(True, WidgetConfig)if all validations succeed. *(False, errors_dict)if one or more validations fail.
89def main() -> None: 90 """Run the dataclass integration demonstration. 91 92 Steps: 93 1. Construct a valid configuration using `"Gizmo", "green", 4"`. 94 2. Attempt to construct an invalid configuration with `"purple", 0"`. 95 3. Print the success flag and resulting object or error dictionary. 96 97 Prints: 98 * `"OK: True WidgetConfig(name='Gizmo', color='green', slots=4)"` 99 * `"OK2: False {'color': "Value must be one of ('red', 'green', 'blue'), 100 * got purple", 'slots': 'Value must be greater than or equal to 1, got 0'}"` 101 """ 102 ok, res = WidgetConfig.from_input("Gizmo", "green", 4) 103 print("OK:", ok, res) 104 105 ok2, res2 = WidgetConfig.from_input("Oops", "purple", 0) 106 print("OK2:", ok2, res2)
Run the dataclass integration demonstration.
Steps:
- Construct a valid configuration using
"Gizmo", "green", 4".- Attempt to construct an invalid configuration with
"purple", 0".- Print the success flag and resulting object or error dictionary.
Prints:
"OK: True WidgetConfig(name='Gizmo', color='green', slots=4)"- `"OK2: False {'color': "Value must be one of ('red', 'green', 'blue'),
- got purple", 'slots': 'Value must be greater than or equal to 1, got 0'}"`