examples.20_sorting_with_invalid

Demonstrates how sorting a list containing both valid and invalid ConstrainedValue instances results in an error.

This example shows:
  • Valid constrained values (Status.OK) are comparable and sortable.
  • Invalid values (Status.EXCEPTION) cannot be meaningfully compared.
  • Sorting such a mixed list raises a TypeError.
Run directly:

python examples/20_sorting_with_invalid.py

Expected output:

sort raised: '<' not supported between instances of 'Bad' and 'Good'

  1"""Demonstrates how sorting a list containing both valid and invalid
  2:class:`ConstrainedValue` instances results in an error.
  3
  4This example shows:
  5  * Valid constrained values (`Status.OK`) are comparable and sortable.
  6  * Invalid values (`Status.EXCEPTION`) cannot be meaningfully compared.
  7  * Sorting such a mixed list raises a `TypeError`.
  8
  9Run directly:
 10
 11    python examples/20_sorting_with_invalid.py
 12
 13Expected output:
 14
 15    sort raised: '<' not supported between instances of 'Bad' and 'Good'
 16"""
 17
 18import sys
 19import pathlib
 20from typing import Any, List
 21
 22# ---------------------------------------------------------------------------
 23# Make repo root importable when running this file directly
 24# ---------------------------------------------------------------------------
 25sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1]))
 26
 27from constrained_values import Response, Status
 28from constrained_values.value import TransformationStrategy, ConstrainedValue, PipeLineStrategy
 29
 30
 31class Pass(TransformationStrategy[Any, Any]):
 32    """A transformation that always succeeds."""
 33
 34    def transform(self, value: Any) -> Response[Any]:
 35        """Return a successful response with the input value unchanged.
 36
 37        Args:
 38            value: The input to pass through.
 39
 40        Returns:
 41            Response[Any]: Contains:
 42                * `status = Status.OK`
 43                * `details = "ok"`
 44                * `value` equal to the input
 45        """
 46        return Response(status=Status.OK, details="ok", value=value)
 47
 48
 49class Fail(TransformationStrategy[Any, Any]):
 50    """A transformation that always fails."""
 51
 52    def transform(self, value: Any) -> Response[Any]:
 53        """Return a failed response with no usable value.
 54
 55        Args:
 56            value: Any input value (ignored).
 57
 58        Returns:
 59            Response[Any]: Contains:
 60                * `status = Status.EXCEPTION`
 61                * `details = "bad"`
 62                * `value = None`
 63        """
 64        return Response(status=Status.EXCEPTION, details="bad", value=None)
 65
 66
 67class Good(ConstrainedValue[int]):
 68    """A `ConstrainedValue[int]` that always succeeds."""
 69
 70    def get_strategies(self) -> List[PipeLineStrategy]:
 71        """Return a one-step successful pipeline."""
 72        return [Pass()]
 73
 74
 75class Bad(ConstrainedValue[int]):
 76    """A `ConstrainedValue[int]` that always fails."""
 77
 78    def get_strategies(self) -> List[PipeLineStrategy]:
 79        """Return a one-step failing pipeline."""
 80        return [Fail()]
 81
 82
 83def main() -> None:
 84    """Run the sorting demonstration.
 85
 86    Creates a mixed list of valid and invalid constrained values and attempts
 87    to sort it. Because invalid values cannot be compared meaningfully, a
 88    `TypeError` is raised.
 89
 90    Steps:
 91        1. Create `[Good(3), Bad(99), Good(1)]`.
 92        2. Attempt to `list.sort()`.
 93        3. Catch and print the resulting `TypeError`.
 94
 95    Prints:
 96        * `"sort raised: '<' not supported between instances of 'Bad' and 'Good'"`
 97    """
 98    items = [Good(3), Bad(99), Good(1)]
 99    try:
100        items.sort()
101    except TypeError as e:
102        print("sort raised:", e)
103
104
105if __name__ == "__main__":
106    main()
class Pass(constrained_values.value.TransformationStrategy[typing.Any, typing.Any]):
32class Pass(TransformationStrategy[Any, Any]):
33    """A transformation that always succeeds."""
34
35    def transform(self, value: Any) -> Response[Any]:
36        """Return a successful response with the input value unchanged.
37
38        Args:
39            value: The input to pass through.
40
41        Returns:
42            Response[Any]: Contains:
43                * `status = Status.OK`
44                * `details = "ok"`
45                * `value` equal to the input
46        """
47        return Response(status=Status.OK, details="ok", value=value)

A transformation that always succeeds.

def transform(self, value: Any) -> constrained_values.Response[typing.Any]:
35    def transform(self, value: Any) -> Response[Any]:
36        """Return a successful response with the input value unchanged.
37
38        Args:
39            value: The input to pass through.
40
41        Returns:
42            Response[Any]: Contains:
43                * `status = Status.OK`
44                * `details = "ok"`
45                * `value` equal to the input
46        """
47        return Response(status=Status.OK, details="ok", value=value)

Return a successful response with the input value unchanged.

Arguments:
  • value: The input to pass through.
Returns:

Response[Any]: Contains: * status = Status.OK * details = "ok" * value equal to the input

class Fail(constrained_values.value.TransformationStrategy[typing.Any, typing.Any]):
50class Fail(TransformationStrategy[Any, Any]):
51    """A transformation that always fails."""
52
53    def transform(self, value: Any) -> Response[Any]:
54        """Return a failed response with no usable value.
55
56        Args:
57            value: Any input value (ignored).
58
59        Returns:
60            Response[Any]: Contains:
61                * `status = Status.EXCEPTION`
62                * `details = "bad"`
63                * `value = None`
64        """
65        return Response(status=Status.EXCEPTION, details="bad", value=None)

A transformation that always fails.

def transform(self, value: Any) -> constrained_values.Response[typing.Any]:
53    def transform(self, value: Any) -> Response[Any]:
54        """Return a failed response with no usable value.
55
56        Args:
57            value: Any input value (ignored).
58
59        Returns:
60            Response[Any]: Contains:
61                * `status = Status.EXCEPTION`
62                * `details = "bad"`
63                * `value = None`
64        """
65        return Response(status=Status.EXCEPTION, details="bad", value=None)

Return a failed response with no usable value.

Arguments:
  • value: Any input value (ignored).
Returns:

Response[Any]: Contains: * status = Status.EXCEPTION * details = "bad" * value = None

class Good(constrained_values.value.ConstrainedValue[int]):
68class Good(ConstrainedValue[int]):
69    """A `ConstrainedValue[int]` that always succeeds."""
70
71    def get_strategies(self) -> List[PipeLineStrategy]:
72        """Return a one-step successful pipeline."""
73        return [Pass()]

A ConstrainedValue[int] that always succeeds.

def get_strategies(self) -> List[constrained_values.value.PipeLineStrategy]:
71    def get_strategies(self) -> List[PipeLineStrategy]:
72        """Return a one-step successful pipeline."""
73        return [Pass()]

Return a one-step successful pipeline.

Inherited Members
constrained_values.value.ConstrainedValue
ConstrainedValue
status
details
value
unwrap
ok
class Bad(constrained_values.value.ConstrainedValue[int]):
76class Bad(ConstrainedValue[int]):
77    """A `ConstrainedValue[int]` that always fails."""
78
79    def get_strategies(self) -> List[PipeLineStrategy]:
80        """Return a one-step failing pipeline."""
81        return [Fail()]

A ConstrainedValue[int] that always fails.

def get_strategies(self) -> List[constrained_values.value.PipeLineStrategy]:
79    def get_strategies(self) -> List[PipeLineStrategy]:
80        """Return a one-step failing pipeline."""
81        return [Fail()]

Return a one-step failing pipeline.

Inherited Members
constrained_values.value.ConstrainedValue
ConstrainedValue
status
details
value
unwrap
ok
def main() -> None:
 84def main() -> None:
 85    """Run the sorting demonstration.
 86
 87    Creates a mixed list of valid and invalid constrained values and attempts
 88    to sort it. Because invalid values cannot be compared meaningfully, a
 89    `TypeError` is raised.
 90
 91    Steps:
 92        1. Create `[Good(3), Bad(99), Good(1)]`.
 93        2. Attempt to `list.sort()`.
 94        3. Catch and print the resulting `TypeError`.
 95
 96    Prints:
 97        * `"sort raised: '<' not supported between instances of 'Bad' and 'Good'"`
 98    """
 99    items = [Good(3), Bad(99), Good(1)]
100    try:
101        items.sort()
102    except TypeError as e:
103        print("sort raised:", e)

Run the sorting demonstration.

Creates a mixed list of valid and invalid constrained values and attempts to sort it. Because invalid values cannot be compared meaningfully, a TypeError is raised.

Steps:
  1. Create [Good(3), Bad(99), Good(1)].
  2. Attempt to list.sort().
  3. Catch and print the resulting TypeError.
Prints:
  • "sort raised: '<' not supported between instances of 'Bad' and 'Good'"