examples.08_hashing_valid_vs_invalid
Demonstrates how valid and invalid ConstrainedValue instances behave when
hashed or used in sets and equality comparisons.
This example shows:
- Valid values hash based on their (class, value) pair.
- Invalid values hash based on their (class, status) pair.
- Equal valid instances collapse to one entry in a set.
- Invalid instances remain distinct, even if their input data is identical.
Run directly:
python examples/08_hashing_valid_vs_invalid.py
Expected output:
equal valid hashes: True set size for valid duplicates (1): 1 invalid equal? (False): False both hashable: True set size for invalid values (2): 2
1"""Demonstrates how valid and invalid `ConstrainedValue` instances behave when 2hashed or used in sets and equality comparisons. 3 4This example shows: 5 * Valid values hash based on their **(class, value)** pair. 6 * Invalid values hash based on their **(class, status)** pair. 7 * Equal valid instances collapse to one entry in a set. 8 * Invalid instances remain distinct, even if their input data is identical. 9 10Run directly: 11 12 python examples/08_hashing_valid_vs_invalid.py 13 14Expected output: 15 16 equal valid hashes: True 17 set size for valid duplicates (1): 1 18 invalid equal? (False): False 19 both hashable: True 20 set size for invalid values (2): 2 21""" 22 23import sys 24import pathlib 25from typing import Any 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 Response, Status 33from constrained_values.value import TransformationStrategy, ConstrainedValue 34 35 36class Pass(TransformationStrategy[Any, Any]): 37 """A transformation strategy that always succeeds. 38 39 Produces an `OK` response and returns the input value unchanged. 40 """ 41 42 def transform(self, value: Any) -> Response[Any]: 43 """Return an OK response with the input value. 44 45 Args: 46 value: The input to pass through unchanged. 47 48 Returns: 49 Response[Any]: A successful response containing: 50 * `status = Status.OK` 51 * `details = "ok"` 52 * `value` equal to the input 53 """ 54 return Response(status=Status.OK, details="ok", value=value) 55 56 57class Fail(TransformationStrategy[Any, Any]): 58 """A transformation strategy that always fails. 59 60 Used to demonstrate how failed constrained values behave when hashed. 61 """ 62 63 def transform(self, value: Any) -> Response[Any]: 64 """Return a failed response. 65 66 Args: 67 value: Any input value (ignored). 68 69 Returns: 70 Response[Any]: A failed response containing: 71 * `status = Status.EXCEPTION` 72 * `details = "boom"` 73 * `value = None` 74 """ 75 return Response(status=Status.EXCEPTION, details="boom", value=None) 76 77 78class ValidInt(ConstrainedValue[int]): 79 """A valid constrained integer that always succeeds. 80 81 Uses a single `Pass` strategy. 82 """ 83 84 def get_strategies(self): 85 """Return a one-step pass-through pipeline.""" 86 return [Pass()] 87 88 89class InvalidInt(ConstrainedValue[int]): 90 """An invalid constrained integer that always fails. 91 92 Uses a single `Fail` strategy to simulate validation failure. 93 """ 94 95 def get_strategies(self): 96 """Return a one-step failing pipeline.""" 97 return [Fail()] 98 99 100def main() -> None: 101 """Run the hashing comparison demonstration. 102 103 Steps: 104 1. Create two valid constrained values (`a`, `b`) with identical input. 105 2. Show that they have equal hashes and collapse in a set. 106 3. Create two invalid constrained values (`x`, `y`) and show that 107 they are not equal, but remain hashable and distinct in sets. 108 109 Prints: 110 * Whether the hashes of valid values are equal (`True`) 111 * The set size for valid duplicates (`1`) 112 * Equality result for invalid values (`False`) 113 * Confirmation that invalid values are still hashable (`True`) 114 * The set size for invalid values (`2`) 115 """ 116 a, b = ValidInt(42), ValidInt(42) 117 print("equal valid hashes:", hash(a) == hash(b)) 118 s = {a, b} 119 print("set size for valid duplicates (1):", len(s)) 120 121 x, y = InvalidInt(1), InvalidInt(1) 122 print("invalid equal? (False):", x == y) 123 print("both hashable:", isinstance(hash(x), int) and isinstance(hash(y), int)) 124 s2 = {x, y} 125 print("set size for invalid values (2):", len(s2)) 126 127 128if __name__ == "__main__": 129 main()
37class Pass(TransformationStrategy[Any, Any]): 38 """A transformation strategy that always succeeds. 39 40 Produces an `OK` response and returns the input value unchanged. 41 """ 42 43 def transform(self, value: Any) -> Response[Any]: 44 """Return an OK response with the input value. 45 46 Args: 47 value: The input to pass through unchanged. 48 49 Returns: 50 Response[Any]: A successful response containing: 51 * `status = Status.OK` 52 * `details = "ok"` 53 * `value` equal to the input 54 """ 55 return Response(status=Status.OK, details="ok", value=value)
A transformation strategy that always succeeds.
Produces an OK response and returns the input value unchanged.
43 def transform(self, value: Any) -> Response[Any]: 44 """Return an OK response with the input value. 45 46 Args: 47 value: The input to pass through unchanged. 48 49 Returns: 50 Response[Any]: A successful response containing: 51 * `status = Status.OK` 52 * `details = "ok"` 53 * `value` equal to the input 54 """ 55 return Response(status=Status.OK, details="ok", value=value)
Return an OK response with the input value.
Arguments:
- value: The input to pass through unchanged.
Returns:
Response[Any]: A successful response containing: *
status = Status.OK*details = "ok"*valueequal to the input
58class Fail(TransformationStrategy[Any, Any]): 59 """A transformation strategy that always fails. 60 61 Used to demonstrate how failed constrained values behave when hashed. 62 """ 63 64 def transform(self, value: Any) -> Response[Any]: 65 """Return a failed response. 66 67 Args: 68 value: Any input value (ignored). 69 70 Returns: 71 Response[Any]: A failed response containing: 72 * `status = Status.EXCEPTION` 73 * `details = "boom"` 74 * `value = None` 75 """ 76 return Response(status=Status.EXCEPTION, details="boom", value=None)
A transformation strategy that always fails.
Used to demonstrate how failed constrained values behave when hashed.
64 def transform(self, value: Any) -> Response[Any]: 65 """Return a failed response. 66 67 Args: 68 value: Any input value (ignored). 69 70 Returns: 71 Response[Any]: A failed response containing: 72 * `status = Status.EXCEPTION` 73 * `details = "boom"` 74 * `value = None` 75 """ 76 return Response(status=Status.EXCEPTION, details="boom", value=None)
Return a failed response.
Arguments:
- value: Any input value (ignored).
Returns:
Response[Any]: A failed response containing: *
status = Status.EXCEPTION*details = "boom"*value = None
79class ValidInt(ConstrainedValue[int]): 80 """A valid constrained integer that always succeeds. 81 82 Uses a single `Pass` strategy. 83 """ 84 85 def get_strategies(self): 86 """Return a one-step pass-through pipeline.""" 87 return [Pass()]
A valid constrained integer that always succeeds.
Uses a single Pass strategy.
Inherited Members
- constrained_values.value.ConstrainedValue
- ConstrainedValue
- status
- details
- value
- unwrap
- ok
90class InvalidInt(ConstrainedValue[int]): 91 """An invalid constrained integer that always fails. 92 93 Uses a single `Fail` strategy to simulate validation failure. 94 """ 95 96 def get_strategies(self): 97 """Return a one-step failing pipeline.""" 98 return [Fail()]
An invalid constrained integer that always fails.
Uses a single Fail strategy to simulate validation failure.
Inherited Members
- constrained_values.value.ConstrainedValue
- ConstrainedValue
- status
- details
- value
- unwrap
- ok
101def main() -> None: 102 """Run the hashing comparison demonstration. 103 104 Steps: 105 1. Create two valid constrained values (`a`, `b`) with identical input. 106 2. Show that they have equal hashes and collapse in a set. 107 3. Create two invalid constrained values (`x`, `y`) and show that 108 they are not equal, but remain hashable and distinct in sets. 109 110 Prints: 111 * Whether the hashes of valid values are equal (`True`) 112 * The set size for valid duplicates (`1`) 113 * Equality result for invalid values (`False`) 114 * Confirmation that invalid values are still hashable (`True`) 115 * The set size for invalid values (`2`) 116 """ 117 a, b = ValidInt(42), ValidInt(42) 118 print("equal valid hashes:", hash(a) == hash(b)) 119 s = {a, b} 120 print("set size for valid duplicates (1):", len(s)) 121 122 x, y = InvalidInt(1), InvalidInt(1) 123 print("invalid equal? (False):", x == y) 124 print("both hashable:", isinstance(hash(x), int) and isinstance(hash(y), int)) 125 s2 = {x, y} 126 print("set size for invalid values (2):", len(s2))
Run the hashing comparison demonstration.
Steps:
- Create two valid constrained values (
a,b) with identical input.- Show that they have equal hashes and collapse in a set.
- Create two invalid constrained values (
x,y) and show that they are not equal, but remain hashable and distinct in sets.
Prints:
- Whether the hashes of valid values are equal (
True)- The set size for valid duplicates (
1)- Equality result for invalid values (
False)- Confirmation that invalid values are still hashable (
True)- The set size for invalid values (
2)