StructResult 0.8.2__tar.gz → 0.8.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {structresult-0.8.2 → structresult-0.8.4}/PKG-INFO +1 -1
- {structresult-0.8.2 → structresult-0.8.4}/pyproject.toml +1 -1
- {structresult-0.8.2 → structresult-0.8.4}/src/StructResult/result.py +41 -27
- {structresult-0.8.2 → structresult-0.8.4}/src/StructResult.egg-info/PKG-INFO +1 -1
- {structresult-0.8.2 → structresult-0.8.4}/test/benchmark.py +1 -1
- {structresult-0.8.2 → structresult-0.8.4}/test/test_formatter.py +9 -9
- {structresult-0.8.2 → structresult-0.8.4}/test/test_result.py +47 -48
- {structresult-0.8.2 → structresult-0.8.4}/README.md +0 -0
- {structresult-0.8.2 → structresult-0.8.4}/setup.cfg +0 -0
- {structresult-0.8.2 → structresult-0.8.4}/src/StructResult/__init__.py +0 -0
- {structresult-0.8.2 → structresult-0.8.4}/src/StructResult/formatter.py +0 -0
- {structresult-0.8.2 → structresult-0.8.4}/src/StructResult/py.typed +0 -0
- {structresult-0.8.2 → structresult-0.8.4}/src/StructResult.egg-info/SOURCES.txt +0 -0
- {structresult-0.8.2 → structresult-0.8.4}/src/StructResult.egg-info/dependency_links.txt +0 -0
- {structresult-0.8.2 → structresult-0.8.4}/src/StructResult.egg-info/requires.txt +0 -0
- {structresult-0.8.2 → structresult-0.8.4}/src/StructResult.egg-info/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
|
-
from typing import Optional, Self, Protocol, Iterator, Any
|
|
2
|
+
from typing import Optional, Self, Protocol, Iterator, Any, Never
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
5
|
Functional error handling system with:
|
|
@@ -19,6 +19,9 @@ class Result(Protocol):
|
|
|
19
19
|
def is_ok(self) -> bool:
|
|
20
20
|
"""Returns True if successful (no errors)"""
|
|
21
21
|
|
|
22
|
+
def unwrap(self) -> Any:
|
|
23
|
+
"""Returns value or raises exception if errors exist"""
|
|
24
|
+
|
|
22
25
|
|
|
23
26
|
class Ok(Result):
|
|
24
27
|
"""Singleton success marker without value"""
|
|
@@ -28,6 +31,14 @@ class Ok(Result):
|
|
|
28
31
|
def __str__(self) -> str:
|
|
29
32
|
return "OK"
|
|
30
33
|
|
|
34
|
+
@property
|
|
35
|
+
def value(self) -> "Ok":
|
|
36
|
+
return OK
|
|
37
|
+
|
|
38
|
+
def unwrap(self) -> "Ok":
|
|
39
|
+
"""Always return OK"""
|
|
40
|
+
return OK
|
|
41
|
+
|
|
31
42
|
|
|
32
43
|
OK = Ok()
|
|
33
44
|
|
|
@@ -35,35 +46,32 @@ OK = Ok()
|
|
|
35
46
|
class ErrorPropagator(Result, Protocol):
|
|
36
47
|
"""Protocol for error-accumulating types"""
|
|
37
48
|
err: Optional[ExceptionGroup]
|
|
38
|
-
msg: str
|
|
39
49
|
|
|
40
50
|
def is_ok(self) -> bool:
|
|
41
51
|
return self.err is None
|
|
42
52
|
|
|
43
|
-
def
|
|
53
|
+
def append_e(self, e: Exception, msg: str = "") -> Self:
|
|
54
|
+
"""adds to existing group or creates new one"""
|
|
55
|
+
if self.err is None:
|
|
56
|
+
self.err = ExceptionGroup(msg, (e,))
|
|
57
|
+
elif msg == self.err.message:
|
|
58
|
+
self.err = ExceptionGroup(msg, (*self.err.exceptions, e))
|
|
59
|
+
else:
|
|
60
|
+
self.err = ExceptionGroup(msg, (e, self.err))
|
|
61
|
+
return self
|
|
62
|
+
|
|
63
|
+
def append_err(self, err: ExceptionGroup) -> Self:
|
|
44
64
|
"""Adds an exception or exception group to the collector.
|
|
45
65
|
Rules:
|
|
46
66
|
- For ExceptionGroup with matching message: merges exceptions
|
|
47
67
|
- For ExceptionGroup with different message: preserves structure
|
|
48
|
-
- For single Exception: adds to existing group or creates new one
|
|
49
68
|
"""
|
|
50
|
-
if
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
elif self.msg == e.message:
|
|
57
|
-
self.err = ExceptionGroup(self.msg, (*self.err.exceptions, *e.exceptions))
|
|
58
|
-
else:
|
|
59
|
-
self.err = ExceptionGroup(self.msg, (*self.err.exceptions, e))
|
|
60
|
-
else: # for Exception
|
|
61
|
-
if self.err is None:
|
|
62
|
-
self.err = ExceptionGroup(self.msg, (e,))
|
|
63
|
-
elif self.msg == self.err.message:
|
|
64
|
-
self.err = ExceptionGroup(self.msg, (*self.err.exceptions, e))
|
|
65
|
-
else:
|
|
66
|
-
self.err = ExceptionGroup(self.msg, (e, self.err))
|
|
69
|
+
if self.err is None:
|
|
70
|
+
self.err = err
|
|
71
|
+
elif self.err.message == err.message:
|
|
72
|
+
self.err = ExceptionGroup(err.message, (*self.err.exceptions, *err.exceptions))
|
|
73
|
+
else:
|
|
74
|
+
self.err = ExceptionGroup(err.message, (*self.err.exceptions, err))
|
|
67
75
|
return self
|
|
68
76
|
|
|
69
77
|
def propagate_err[T](self, res: "Collector[T] | ErrorAccumulator") -> Optional[T]:
|
|
@@ -80,18 +88,26 @@ class ErrorPropagator(Result, Protocol):
|
|
|
80
88
|
class Error(ErrorPropagator):
|
|
81
89
|
"""Error-only result container"""
|
|
82
90
|
err: ExceptionGroup
|
|
83
|
-
msg: str = ""
|
|
84
91
|
|
|
85
92
|
@classmethod
|
|
86
|
-
def from_e(cls, e: Exception, msg: str = "") ->
|
|
87
|
-
return cls(ExceptionGroup(msg, (e,))
|
|
93
|
+
def from_e(cls, e: Exception, msg: str = "") -> "Error":
|
|
94
|
+
return cls(ExceptionGroup(msg, (e,)))
|
|
95
|
+
|
|
96
|
+
def with_msg(self, msg: str) -> "Error":
|
|
97
|
+
"""Returns a new Error instance with updated message context
|
|
98
|
+
while preserving the original exception structure
|
|
99
|
+
"""
|
|
100
|
+
return Error(err=ExceptionGroup(msg, (self.err,)))
|
|
101
|
+
|
|
102
|
+
def unwrap(self) -> Never:
|
|
103
|
+
"""Always raises exception"""
|
|
104
|
+
raise self.err
|
|
88
105
|
|
|
89
106
|
|
|
90
107
|
@dataclass(slots=True)
|
|
91
108
|
class ErrorAccumulator(ErrorPropagator):
|
|
92
109
|
"""Base container for error propagation with status conversion"""
|
|
93
110
|
err: Optional[ExceptionGroup] = field(init=False, default=None)
|
|
94
|
-
msg: str = ""
|
|
95
111
|
|
|
96
112
|
@property
|
|
97
113
|
def result(self) -> Ok | Error:
|
|
@@ -118,7 +134,6 @@ class Collector[T](ErrorPropagator, Protocol):
|
|
|
118
134
|
class Simple[T](Collector[T], Result):
|
|
119
135
|
"""Basic collector for values"""
|
|
120
136
|
value: T
|
|
121
|
-
msg: str = ""
|
|
122
137
|
err: Optional[ExceptionGroup] = field(init=False, default=None)
|
|
123
138
|
|
|
124
139
|
def set(self, res: "Simple[T]") -> T:
|
|
@@ -146,7 +161,6 @@ class Option[T](Simple[Optional[T]], Result):
|
|
|
146
161
|
class List[T](Collector[list[Optional[T | Ok]]], Result):
|
|
147
162
|
"""List collector with error accumulation"""
|
|
148
163
|
value: list[Optional[T] | Ok] = field(init=False, default_factory=list)
|
|
149
|
-
msg: str = ""
|
|
150
164
|
err: Optional[ExceptionGroup] = field(init=False, default=None)
|
|
151
165
|
|
|
152
166
|
def append(self, res: Option[T] | Simple[T] | Error | Ok) -> None:
|
|
@@ -39,4 +39,4 @@ print(f" isinstance(): {time_isinstance_ok:.6f} sec (1M calls)")
|
|
|
39
39
|
|
|
40
40
|
print(f"\nError-res:")
|
|
41
41
|
print(f" is_ok(): {time_is_ok_err:.6f} sec (1M calls)")
|
|
42
|
-
print(f" isinstance(): {time_isinstance_err:.6f} sec (1M calls)")
|
|
42
|
+
print(f" isinstance(): {time_isinstance_err:.6f} sec (1M calls)")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import unittest
|
|
2
|
-
from src.StructResult.result import Option, Error, List
|
|
2
|
+
from src.StructResult.result import Option, Error, List, Simple
|
|
3
3
|
from src.StructResult.formatter import format_eg
|
|
4
4
|
|
|
5
5
|
|
|
@@ -16,11 +16,11 @@ class TestFormatEG(unittest.TestCase):
|
|
|
16
16
|
])
|
|
17
17
|
|
|
18
18
|
# Create test Result objects
|
|
19
|
-
self.simple_result = Option
|
|
19
|
+
self.simple_result = Option("test")
|
|
20
20
|
self.error_result = Error.from_e(self.simple_error, msg="error occurred")
|
|
21
21
|
self.list_result = List[int]()
|
|
22
|
-
self.list_result.append(
|
|
23
|
-
self.list_result.append(Option
|
|
22
|
+
self.list_result.append(Simple(42))
|
|
23
|
+
self.list_result.append(Option())
|
|
24
24
|
|
|
25
25
|
def test_basic_exception_group(self) -> None:
|
|
26
26
|
eg = ExceptionGroup("Test", [self.simple_error])
|
|
@@ -46,7 +46,7 @@ class TestFormatEG(unittest.TestCase):
|
|
|
46
46
|
self.assertEqual(result, expected)
|
|
47
47
|
|
|
48
48
|
def test_with_result_protocol(self) -> None:
|
|
49
|
-
error_result = Option
|
|
49
|
+
error_result: Option[int] = Option()
|
|
50
50
|
error_result.append_err(self.complex_group)
|
|
51
51
|
if error_result.err is not None:
|
|
52
52
|
result = format_eg(error_result.err)
|
|
@@ -74,9 +74,9 @@ class TestFormatEG(unittest.TestCase):
|
|
|
74
74
|
|
|
75
75
|
def test_with_list_result_errors(self) -> None:
|
|
76
76
|
list_result = List[int]()
|
|
77
|
-
list_result.append(
|
|
78
|
-
error_result =
|
|
79
|
-
error_result.
|
|
77
|
+
list_result.append(Simple(1))
|
|
78
|
+
error_result = Simple(2)
|
|
79
|
+
error_result.append_e(self.simple_error)
|
|
80
80
|
list_result.append(error_result)
|
|
81
81
|
|
|
82
82
|
if list_result.err:
|
|
@@ -85,7 +85,7 @@ class TestFormatEG(unittest.TestCase):
|
|
|
85
85
|
self.assertTrue(result.endswith(expected))
|
|
86
86
|
|
|
87
87
|
def test_protocol_compatibility(self) -> None:
|
|
88
|
-
error_result = Error(self.complex_group
|
|
88
|
+
error_result = Error(self.complex_group).with_msg(msg="test")
|
|
89
89
|
|
|
90
90
|
self.assertIsInstance(error_result.err, BaseExceptionGroup)
|
|
91
91
|
if error_result.err is not None:
|
|
@@ -14,35 +14,34 @@ class TestResultSystem(unittest.TestCase):
|
|
|
14
14
|
err = Error.from_e(exc, "context")
|
|
15
15
|
self.assertFalse(err.is_ok())
|
|
16
16
|
self.assertIsNotNone(err.err)
|
|
17
|
-
self.assertEqual(err.msg, "context")
|
|
18
17
|
self.assertEqual(len(err.err.exceptions), 1)
|
|
19
18
|
self.assertIsInstance(err.err.exceptions[0], ValueError)
|
|
20
19
|
|
|
21
20
|
def test_simple_success(self) -> None:
|
|
22
|
-
res
|
|
21
|
+
res: Option[str] = Option("success")
|
|
23
22
|
self.assertTrue(res.is_ok())
|
|
24
23
|
self.assertEqual(res.unwrap(), "success")
|
|
25
24
|
self.assertIsNone(res.err)
|
|
26
25
|
|
|
27
26
|
def test_simple_failure(self) -> None:
|
|
28
27
|
exc = TypeError("type error")
|
|
29
|
-
res
|
|
28
|
+
res: Option[str] = Option("test").append_e(exc)
|
|
30
29
|
self.assertFalse(res.is_ok())
|
|
31
30
|
self.assertIsNotNone(res.err)
|
|
32
31
|
with self.assertRaises(ExceptionGroup):
|
|
33
32
|
res.unwrap()
|
|
34
33
|
|
|
35
34
|
def test_bool_type(self) -> None:
|
|
36
|
-
true_res = Bool(value=True
|
|
37
|
-
false_res = Bool(value=False
|
|
35
|
+
true_res = Bool(value=True)
|
|
36
|
+
false_res = Bool(value=False)
|
|
38
37
|
self.assertTrue(true_res.unwrap())
|
|
39
38
|
self.assertFalse(false_res.unwrap())
|
|
40
39
|
|
|
41
40
|
def test_error_propagation(self) -> None:
|
|
42
41
|
exc1 = RuntimeError("error 1")
|
|
43
42
|
exc2 = KeyError("error 2")
|
|
44
|
-
res1
|
|
45
|
-
res2
|
|
43
|
+
res1: Option[int] = Option().append_e(exc1, "op1")
|
|
44
|
+
res2: Option[int] = Option().append_e(exc2, "op2")
|
|
46
45
|
res1.propagate_err(res2)
|
|
47
46
|
self.assertFalse(res1.is_ok())
|
|
48
47
|
if res1.err is not None:
|
|
@@ -51,21 +50,21 @@ class TestResultSystem(unittest.TestCase):
|
|
|
51
50
|
self.assertIsInstance(res1.err.exceptions[1].exceptions[0], KeyError)
|
|
52
51
|
|
|
53
52
|
def test_list_collector(self) -> None:
|
|
54
|
-
lst
|
|
55
|
-
lst.append(Option
|
|
53
|
+
lst: List[int] = List()
|
|
54
|
+
lst.append(Option(42))
|
|
56
55
|
lst.append(Error.from_e(ValueError("bad value"), "item2"))
|
|
57
56
|
lst.append(OK)
|
|
58
|
-
lst.append(Option
|
|
57
|
+
lst.append(Option(100))
|
|
59
58
|
self.assertEqual(len(lst.value), 4)
|
|
60
59
|
self.assertEqual(lst.value[0], 42)
|
|
61
60
|
self.assertIsInstance(lst.value[2], Ok)
|
|
62
61
|
self.assertEqual(lst.value[3], 100)
|
|
63
62
|
self.assertFalse(lst.is_ok())
|
|
64
63
|
self.assertEqual(len(lst.err.exceptions), 1)
|
|
65
|
-
self.assertIsInstance(lst.err.exceptions[0]
|
|
64
|
+
self.assertIsInstance(lst.err.exceptions[0], ValueError)
|
|
66
65
|
|
|
67
66
|
def test_list_operator_overload(self) -> None:
|
|
68
|
-
lst = List[str](
|
|
67
|
+
lst: List[str] = List[str]() + Option("hello")
|
|
69
68
|
lst += Error.from_e(TypeError("type error"), "second")
|
|
70
69
|
self.assertEqual(len(lst.value), 2)
|
|
71
70
|
self.assertEqual(lst.value[0], "hello")
|
|
@@ -75,8 +74,8 @@ class TestResultSystem(unittest.TestCase):
|
|
|
75
74
|
exc1 = ValueError("val1")
|
|
76
75
|
exc2 = TypeError("type1")
|
|
77
76
|
exc3 = KeyError("key1")
|
|
78
|
-
res1: Option[object] = Option(
|
|
79
|
-
res2: Option[object] = Option(
|
|
77
|
+
res1: Option[object] = Option().append_e(exc1, "group1").append_e(exc2)
|
|
78
|
+
res2: Option[object] = Option().append_e(exc3, "group1")
|
|
80
79
|
res1.propagate_err(res2)
|
|
81
80
|
self.assertEqual(len(res1.err.exceptions), 3)
|
|
82
81
|
self.assertEqual(res1.err.message, "group1")
|
|
@@ -84,35 +83,35 @@ class TestResultSystem(unittest.TestCase):
|
|
|
84
83
|
def test_different_error_groups(self) -> None:
|
|
85
84
|
exc1 = ValueError("val1")
|
|
86
85
|
exc2 = TypeError("type1")
|
|
87
|
-
res1: Option[object] = Option(
|
|
88
|
-
res2: Option[object] = Option(
|
|
86
|
+
res1: Option[object] = Option().append_e(exc1, "group1")
|
|
87
|
+
res2: Option[object] = Option().append_e(exc2, "group2")
|
|
89
88
|
res1.propagate_err(res2)
|
|
90
89
|
self.assertEqual(len(res1.err.exceptions), 2)
|
|
91
90
|
self.assertIsInstance(res1.err.exceptions[1], ExceptionGroup)
|
|
92
91
|
|
|
93
92
|
def test_set_operation(self) -> None:
|
|
94
|
-
main: Option[str] = Option(
|
|
95
|
-
other: Option[str] = Option("data"
|
|
93
|
+
main: Option[str] = Option()
|
|
94
|
+
other: Option[str] = Option("data")
|
|
96
95
|
result = main.set(other)
|
|
97
96
|
self.assertEqual(main.value, "data")
|
|
98
97
|
self.assertEqual(result, "data")
|
|
99
98
|
self.assertTrue(main.is_ok())
|
|
100
99
|
|
|
101
100
|
def test_bool_set_operation(self) -> None:
|
|
102
|
-
main = Bool(
|
|
103
|
-
other = Bool(value=True
|
|
101
|
+
main = Bool()
|
|
102
|
+
other = Bool(value=True)
|
|
104
103
|
result = main.set(other)
|
|
105
104
|
self.assertTrue(main.value)
|
|
106
105
|
self.assertTrue(result)
|
|
107
106
|
|
|
108
107
|
def test_simple_none_value(self) -> None:
|
|
109
|
-
res: Option[int] = Option(
|
|
108
|
+
res: Option[int] = Option()
|
|
110
109
|
self.assertTrue(res.is_ok())
|
|
111
110
|
self.assertIsNone(res.unwrap())
|
|
112
111
|
|
|
113
112
|
def test_bool_false_with_error(self) -> None:
|
|
114
|
-
res = Bool(value=False
|
|
115
|
-
res.
|
|
113
|
+
res = Bool(value=False)
|
|
114
|
+
res.append_e(ValueError("bool error"))
|
|
116
115
|
self.assertFalse(res.value)
|
|
117
116
|
self.assertFalse(res.is_ok())
|
|
118
117
|
with self.assertRaises(ExceptionGroup):
|
|
@@ -121,23 +120,23 @@ class TestResultSystem(unittest.TestCase):
|
|
|
121
120
|
def test_nested_exception_groups(self) -> None:
|
|
122
121
|
inner_group = ExceptionGroup("inner", [ValueError("v1"), TypeError("t1")])
|
|
123
122
|
outer_group = ExceptionGroup("outer", [inner_group, KeyError("k1")])
|
|
124
|
-
res
|
|
123
|
+
res: Option[int] = Option().append_err(outer_group)
|
|
125
124
|
if res.err is not None:
|
|
126
|
-
self.assertEqual(len(res.err.exceptions),
|
|
125
|
+
self.assertEqual(len(res.err.exceptions), 2)
|
|
127
126
|
self.assertIsInstance(res.err.exceptions[0], ExceptionGroup)
|
|
128
|
-
self.assertEqual(res.err.exceptions[0].message, "
|
|
129
|
-
self.assertEqual(res.err.
|
|
127
|
+
self.assertEqual(res.err.exceptions[0].message, "inner")
|
|
128
|
+
self.assertEqual(res.err.message, "outer")
|
|
130
129
|
|
|
131
130
|
def test_list_empty(self) -> None:
|
|
132
|
-
lst
|
|
131
|
+
lst: List[str] = List()
|
|
133
132
|
self.assertTrue(lst.is_ok())
|
|
134
133
|
self.assertEqual(len(lst.value), 0)
|
|
135
134
|
self.assertIsNone(lst.err)
|
|
136
135
|
|
|
137
136
|
def test_list_mixed_types(self) -> None:
|
|
138
|
-
lst: List[str | int] = List(
|
|
139
|
-
lst.append(Option(42
|
|
140
|
-
lst.append(Option("hello"
|
|
137
|
+
lst: List[str | int] = List()
|
|
138
|
+
lst.append(Option(42))
|
|
139
|
+
lst.append(Option("hello"))
|
|
141
140
|
lst.append(Error.from_e(ValueError("error"), "error"))
|
|
142
141
|
self.assertEqual(len(lst.value), 3)
|
|
143
142
|
self.assertEqual(lst.value[0], 42)
|
|
@@ -145,25 +144,25 @@ class TestResultSystem(unittest.TestCase):
|
|
|
145
144
|
self.assertIsInstance(lst.value[2], type(None))
|
|
146
145
|
|
|
147
146
|
def test_propagate_none(self) -> None:
|
|
148
|
-
res
|
|
149
|
-
res.propagate_err(Option
|
|
147
|
+
res: Option[int] = Option(42)
|
|
148
|
+
res.propagate_err(Option())
|
|
150
149
|
self.assertTrue(res.is_ok())
|
|
151
150
|
self.assertEqual(res.unwrap(), 42)
|
|
152
151
|
|
|
153
152
|
def test_type_hints(self) -> None:
|
|
154
153
|
def processor() -> Option[str]:
|
|
155
|
-
return Option
|
|
154
|
+
return Option("result")
|
|
156
155
|
|
|
157
156
|
result = processor()
|
|
158
157
|
value: str | None = result.unwrap()
|
|
159
158
|
self.assertEqual(value, "result")
|
|
160
159
|
|
|
161
160
|
def test_combined_workflow(self) -> None:
|
|
162
|
-
main
|
|
163
|
-
main += Option
|
|
164
|
-
main += Option
|
|
161
|
+
main: List[int] = List()
|
|
162
|
+
main += Option(10)
|
|
163
|
+
main += Option(20)
|
|
165
164
|
main += Error.from_e(ValueError("invalid value"), "op3")
|
|
166
|
-
main += Option
|
|
165
|
+
main += Option(30)
|
|
167
166
|
self.assertEqual(len(main.value), 4)
|
|
168
167
|
self.assertEqual(main.value[0], 10)
|
|
169
168
|
self.assertEqual(main.value[1], 20)
|
|
@@ -174,10 +173,10 @@ class TestResultSystem(unittest.TestCase):
|
|
|
174
173
|
main.unwrap()
|
|
175
174
|
|
|
176
175
|
def test_multiple_propagations(self) -> None:
|
|
177
|
-
res1: Option[int] = Option(
|
|
178
|
-
res2: Option[int] = Option(
|
|
179
|
-
res3: Option[int] = Option(
|
|
180
|
-
main: Option[int] = Option(
|
|
176
|
+
res1: Option[int] = Option().append_e(ValueError("v1"), msg="first")
|
|
177
|
+
res2: Option[int] = Option().append_e(TypeError("t1"), msg="second")
|
|
178
|
+
res3: Option[int] = Option().append_e(KeyError("k1"), msg="third")
|
|
179
|
+
main: Option[int] = Option()
|
|
181
180
|
main.propagate_err(res1)
|
|
182
181
|
main.propagate_err(res2)
|
|
183
182
|
main.propagate_err(res3)
|
|
@@ -185,29 +184,29 @@ class TestResultSystem(unittest.TestCase):
|
|
|
185
184
|
|
|
186
185
|
@patch.object(Option, "append_err")
|
|
187
186
|
def test_propagate_err_calls(self, mock_append: Any) -> None:
|
|
188
|
-
err_res
|
|
187
|
+
err_res: Option[int] = Option()
|
|
189
188
|
err_res.err = ExceptionGroup("error", [ValueError("test")])
|
|
190
|
-
main
|
|
189
|
+
main: Option[int] = Option()
|
|
191
190
|
main.propagate_err(err_res)
|
|
192
191
|
mock_append.assert_called_once_with(err_res.err)
|
|
193
192
|
|
|
194
193
|
def test_iterator_protocol(self) -> None:
|
|
195
|
-
res
|
|
194
|
+
res: Option[str] = Option("test")
|
|
196
195
|
values = list(res)
|
|
197
196
|
self.assertEqual(len(values), 2)
|
|
198
197
|
self.assertEqual(values[0], "test")
|
|
199
198
|
self.assertIsNone(values[1])
|
|
200
199
|
|
|
201
200
|
def test_bool_truthiness(self) -> None:
|
|
202
|
-
true_res = Bool(value=True
|
|
203
|
-
false_res = Bool(value=False
|
|
201
|
+
true_res = Bool(value=True)
|
|
202
|
+
false_res = Bool(value=False)
|
|
204
203
|
self.assertTrue(true_res.value)
|
|
205
204
|
self.assertFalse(false_res.value)
|
|
206
205
|
self.assertTrue(bool(true_res.unwrap()))
|
|
207
206
|
self.assertFalse(bool(false_res.unwrap()))
|
|
208
207
|
|
|
209
208
|
def test_equal(self) -> None:
|
|
210
|
-
res: Option[str] = Option(
|
|
209
|
+
res: Option[str] = Option()
|
|
211
210
|
group = ExceptionGroup("1", (ValueError("1"),))
|
|
212
211
|
res.append_err(group)
|
|
213
212
|
self.assertEqual(res.err, group)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|