StructResult 0.8.0__tar.gz → 0.8.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: StructResult
3
- Version: 0.8.0
3
+ Version: 0.8.2
4
4
  Summary: structural result with ExceptionGroup
5
5
  Author-email: Serj Kotilevski <youserj@outlook.com>
6
6
  Project-URL: Source, https://github.com/youserj/Result_prj
@@ -9,7 +9,7 @@ where = ["src"]
9
9
 
10
10
  [project]
11
11
  name = "StructResult"
12
- version = "0.8.0"
12
+ version = "0.8.2"
13
13
  requires-python = ">= 3.12"
14
14
  authors = [
15
15
  {name="Serj Kotilevski", email="youserj@outlook.com"}
@@ -1,9 +1,10 @@
1
1
  from dataclasses import dataclass, field
2
2
  from typing import Optional, Self, Protocol, Iterator, Any
3
+
3
4
  """
4
5
  Functional error handling system with:
5
6
  - Result composition
6
- - Error accumulation
7
+ - Error accumulation
7
8
  - Type-safe operations
8
9
 
9
10
  Core concepts:
@@ -19,6 +20,18 @@ class Result(Protocol):
19
20
  """Returns True if successful (no errors)"""
20
21
 
21
22
 
23
+ class Ok(Result):
24
+ """Singleton success marker without value"""
25
+ def is_ok(self) -> bool:
26
+ return True
27
+
28
+ def __str__(self) -> str:
29
+ return "OK"
30
+
31
+
32
+ OK = Ok()
33
+
34
+
22
35
  class ErrorPropagator(Result, Protocol):
23
36
  """Protocol for error-accumulating types"""
24
37
  err: Optional[ExceptionGroup]
@@ -53,7 +66,7 @@ class ErrorPropagator(Result, Protocol):
53
66
  self.err = ExceptionGroup(self.msg, (e, self.err))
54
67
  return self
55
68
 
56
- def propagate_err[T](self, res: "Collector[T]") -> Optional[T]:
69
+ def propagate_err[T](self, res: "Collector[T] | ErrorAccumulator") -> Optional[T]:
57
70
  """Merges errors from another result and returns its value:
58
71
  1. If res has errors - merges them into current
59
72
  2. Returns res's value (if exists)
@@ -63,6 +76,30 @@ class ErrorPropagator(Result, Protocol):
63
76
  return res.value if hasattr(res, "value") else None
64
77
 
65
78
 
79
+ @dataclass(slots=True)
80
+ class Error(ErrorPropagator):
81
+ """Error-only result container"""
82
+ err: ExceptionGroup
83
+ msg: str = ""
84
+
85
+ @classmethod
86
+ def from_e(cls, e: Exception, msg: str = "") -> Self:
87
+ return cls(ExceptionGroup(msg, (e,)), msg)
88
+
89
+
90
+ @dataclass(slots=True)
91
+ class ErrorAccumulator(ErrorPropagator):
92
+ """Base container for error propagation with status conversion"""
93
+ err: Optional[ExceptionGroup] = field(init=False, default=None)
94
+ msg: str = ""
95
+
96
+ @property
97
+ def result(self) -> Ok | Error:
98
+ if self.err is None:
99
+ return OK
100
+ return Error(self.err)
101
+
102
+
66
103
  class Collector[T](ErrorPropagator, Protocol):
67
104
  """Protocol for value containers with error handling"""
68
105
  value: T
@@ -78,64 +115,41 @@ class Collector[T](ErrorPropagator, Protocol):
78
115
 
79
116
 
80
117
  @dataclass(slots=True)
81
- class Simple[T](Collector[Optional[T]], Result):
82
- """Basic collector for optional values"""
118
+ class Simple[T](Collector[T], Result):
119
+ """Basic collector for values"""
120
+ value: T
83
121
  msg: str = ""
84
- value: Optional[T] = field(default=None)
85
122
  err: Optional[ExceptionGroup] = field(init=False, default=None)
86
123
 
87
- def set(self, res: "Simple[T]") -> Optional[T]:
124
+ def set(self, res: "Simple[T]") -> T:
88
125
  """set value and append errors"""
89
126
  self.value = res.value
90
- return self.propagate_err(res)
127
+ if res.err is not None:
128
+ self.append_err(res.err)
129
+ return res.value
91
130
 
92
131
 
93
132
  @dataclass(slots=True)
94
- class Bool(Collector[bool], Result):
133
+ class Bool(Simple[bool], Result):
95
134
  """Specialized collector for boolean results"""
96
- msg: str = ""
97
135
  value: bool = field(default=False)
98
136
  err: Optional[ExceptionGroup] = field(init=False, default=None)
99
137
 
100
- def set(self, res: "Bool") -> bool:
101
- """set value and append errors"""
102
- self.value = res.value
103
- self.propagate_err(res)
104
- return res.value
105
-
106
-
107
- class Ok(Result):
108
- """Singleton success marker without value"""
109
- __slots__ = ()
110
-
111
- def is_ok(self) -> bool:
112
- return True
113
-
114
- def __str__(self) -> str:
115
- return "OK"
116
-
117
-
118
- OK = Ok()
119
-
120
138
 
121
- class Error(ErrorPropagator):
122
- """Error-only result container"""
123
- __slots__ = ("msg", "err")
124
- err: ExceptionGroup
125
-
126
- def __init__(self, e: Exception, msg: str = "") -> None:
127
- self.msg = msg
128
- self.err = ExceptionGroup(self.msg, (e,))
139
+ @dataclass(slots=True)
140
+ class Option[T](Simple[Optional[T]], Result):
141
+ """Basic collector for optional values"""
142
+ value: Optional[T] = field(default=None)
129
143
 
130
144
 
131
145
  @dataclass(slots=True)
132
146
  class List[T](Collector[list[Optional[T | Ok]]], Result):
133
147
  """List collector with error accumulation"""
134
- msg: str = ""
135
148
  value: list[Optional[T] | Ok] = field(init=False, default_factory=list)
149
+ msg: str = ""
136
150
  err: Optional[ExceptionGroup] = field(init=False, default=None)
137
151
 
138
- def append(self, res: Collector[Optional[T]] | Error | Ok) -> None:
152
+ def append(self, res: Option[T] | Simple[T] | Error | Ok) -> None:
139
153
  """Appends result with rules:
140
154
  - For OK: adds OK marker
141
155
  - For Error: adds None and merges errors
@@ -151,6 +165,6 @@ class List[T](Collector[list[Optional[T | Ok]]], Result):
151
165
  else:
152
166
  self.value.append(res.value)
153
167
 
154
- def __add__(self, other: Collector[Optional[T]] | Error | Ok) -> Self:
168
+ def __add__(self, other: Option[T] | Simple[T] | Error | Ok) -> Self:
155
169
  self.append(other)
156
170
  return self
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: StructResult
3
- Version: 0.8.0
3
+ Version: 0.8.2
4
4
  Summary: structural result with ExceptionGroup
5
5
  Author-email: Serj Kotilevski <youserj@outlook.com>
6
6
  Project-URL: Source, https://github.com/youserj/Result_prj
@@ -1,19 +1,27 @@
1
1
  import timeit
2
- from src.StructResult.result import OK, Error, Simple
2
+ from typing import Any, TypeGuard
3
+ from src.StructResult import result
4
+ from src.StructResult.result import Ok, Error, Simple, Result, Collector
3
5
 
4
6
  # test data
5
7
  ok_result = Simple(value=1)
6
- error_result = Error(ValueError("fail"))
8
+ error_result = Error.from_e(ValueError("fail"))
7
9
 
8
10
 
9
11
  # var 1: if not result.is_ok()
10
- def check_is_ok(result):
11
- return not result.is_ok()
12
+ def check_is_ok[T](res: Collector[T] | Error | Ok) -> TypeGuard[Collector[T] | Ok]:
13
+ return not res.is_ok()
12
14
 
13
15
 
14
16
  # var 2: if not isinstance(result, Error)
15
- def check_isinstance(result):
16
- return not isinstance(result, Error)
17
+ def check_isinstance(res: Result) -> bool:
18
+ return not isinstance(res, Error)
19
+
20
+
21
+ def foo(res: Simple[Any] | Error) -> None:
22
+ if not check_is_ok(res):
23
+ raise ValueError()
24
+ print(res.value)
17
25
 
18
26
 
19
27
  # OK_result speed
@@ -1,11 +1,11 @@
1
1
  import unittest
2
- from src.StructResult.result import Simple, Error, List
2
+ from src.StructResult.result import Option, Error, List
3
3
  from src.StructResult.formatter import format_eg
4
4
 
5
5
 
6
6
  class TestFormatEG(unittest.TestCase):
7
7
  def setUp(self) -> None:
8
- self.simple_error = ValueError("Simple error")
8
+ self.simple_error = ValueError("Option error")
9
9
  self.nested_group = ExceptionGroup("Nested", [TypeError("Type error")])
10
10
 
11
11
  # Create a complex group with at least one exception in each subgroup
@@ -16,16 +16,16 @@ class TestFormatEG(unittest.TestCase):
16
16
  ])
17
17
 
18
18
  # Create test Result objects
19
- self.simple_result = Simple[str](value="test")
20
- self.error_result = Error(self.simple_error, msg="error occurred")
19
+ self.simple_result = Option[str](value="test")
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(Simple[int](value=42))
23
- self.list_result.append(Simple[int](value=None))
22
+ self.list_result.append(Option[int](value=42))
23
+ self.list_result.append(Option[int](value=None))
24
24
 
25
25
  def test_basic_exception_group(self) -> None:
26
26
  eg = ExceptionGroup("Test", [self.simple_error])
27
27
  result = format_eg(eg)
28
- expected = "Test (1 sub-exception):\n - ValueError('Simple error')"
28
+ expected = "Test (1 sub-exception):\n - ValueError('Option error')"
29
29
  self.assertEqual(result, expected)
30
30
 
31
31
  def test_nested_exception_group(self) -> None:
@@ -37,7 +37,7 @@ class TestFormatEG(unittest.TestCase):
37
37
  result = format_eg(self.complex_group)
38
38
  expected = (
39
39
  "Complex (3 sub-exceptions):\n"
40
- " - ValueError('Simple error')\n"
40
+ " - ValueError('Option error')\n"
41
41
  " Nested (1 sub-exception):\n"
42
42
  " - TypeError('Type error')\n"
43
43
  " With content (1 sub-exception):\n"
@@ -46,13 +46,13 @@ class TestFormatEG(unittest.TestCase):
46
46
  self.assertEqual(result, expected)
47
47
 
48
48
  def test_with_result_protocol(self) -> None:
49
- error_result = Simple[str]()
49
+ error_result = Option[str]()
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)
53
53
  expected = (
54
54
  "Complex (3 sub-exceptions):\n"
55
- " - ValueError('Simple error')\n"
55
+ " - ValueError('Option error')\n"
56
56
  " Nested (1 sub-exception):\n"
57
57
  " - TypeError('Type error')\n"
58
58
  " With content (1 sub-exception):\n"
@@ -69,19 +69,19 @@ class TestFormatEG(unittest.TestCase):
69
69
  show_count=False,
70
70
  repr_fn=lambda e: f"{type(e).__name__}: {str(e)}"
71
71
  )
72
- expected = "Custom:\n * ValueError: Simple error"
72
+ expected = "Custom:\n * ValueError: Option error"
73
73
  self.assertEqual(result, expected)
74
74
 
75
75
  def test_with_list_result_errors(self) -> None:
76
76
  list_result = List[int]()
77
- list_result.append(Simple[int](value=1))
78
- error_result = Simple[int](value=2)
77
+ list_result.append(Option[int](value=1))
78
+ error_result = Option[int](value=2)
79
79
  error_result.append_err(self.simple_error)
80
80
  list_result.append(error_result)
81
81
 
82
82
  if list_result.err:
83
83
  result = format_eg(list_result.err)
84
- expected = " (1 sub-exception):\n - ValueError('Simple error')"
84
+ expected = " (1 sub-exception):\n - ValueError('Option error')"
85
85
  self.assertTrue(result.endswith(expected))
86
86
 
87
87
  def test_protocol_compatibility(self) -> None:
@@ -1,7 +1,7 @@
1
1
  import unittest
2
2
  from unittest.mock import patch
3
- from typing import Optional, Any
4
- from src.StructResult.result import Simple, Bool, Ok, OK, Error, List
3
+ from typing import Any
4
+ from src.StructResult.result import Option, Bool, Ok, OK, Error, List
5
5
 
6
6
 
7
7
  class TestResultSystem(unittest.TestCase):
@@ -11,7 +11,7 @@ class TestResultSystem(unittest.TestCase):
11
11
 
12
12
  def test_error_creation(self) -> None:
13
13
  exc = ValueError("test error")
14
- err = Error(exc, "context")
14
+ err = Error.from_e(exc, "context")
15
15
  self.assertFalse(err.is_ok())
16
16
  self.assertIsNotNone(err.err)
17
17
  self.assertEqual(err.msg, "context")
@@ -19,30 +19,30 @@ class TestResultSystem(unittest.TestCase):
19
19
  self.assertIsInstance(err.err.exceptions[0], ValueError)
20
20
 
21
21
  def test_simple_success(self) -> None:
22
- res = Simple[str]("test", value="success")
22
+ res = Option[str]("success", "test")
23
23
  self.assertTrue(res.is_ok())
24
24
  self.assertEqual(res.unwrap(), "success")
25
25
  self.assertIsNone(res.err)
26
26
 
27
27
  def test_simple_failure(self) -> None:
28
28
  exc = TypeError("type error")
29
- res = Simple[str]("test").append_err(exc)
29
+ res = Option[str]("test").append_err(exc)
30
30
  self.assertFalse(res.is_ok())
31
31
  self.assertIsNotNone(res.err)
32
32
  with self.assertRaises(ExceptionGroup):
33
33
  res.unwrap()
34
34
 
35
35
  def test_bool_type(self) -> None:
36
- true_res = Bool("test", value=True)
37
- false_res = Bool("test", value=False)
36
+ true_res = Bool(value=True, msg="test")
37
+ false_res = Bool(value=False, msg="test")
38
38
  self.assertTrue(true_res.unwrap())
39
39
  self.assertFalse(false_res.unwrap())
40
40
 
41
41
  def test_error_propagation(self) -> None:
42
42
  exc1 = RuntimeError("error 1")
43
43
  exc2 = KeyError("error 2")
44
- res1 = Simple[int]("op1").append_err(exc1)
45
- res2 = Simple[int]("op2").append_err(exc2)
44
+ res1 = Option[int](msg="op1").append_err(exc1)
45
+ res2 = Option[int](msg="op2").append_err(exc2)
46
46
  res1.propagate_err(res2)
47
47
  self.assertFalse(res1.is_ok())
48
48
  if res1.err is not None:
@@ -52,10 +52,10 @@ class TestResultSystem(unittest.TestCase):
52
52
 
53
53
  def test_list_collector(self) -> None:
54
54
  lst = List[int]("collection")
55
- lst.append(Simple[int]("item1", value=42))
56
- lst.append(Error(ValueError("bad value"), "item2"))
55
+ lst.append(Option[int](42, "item1"))
56
+ lst.append(Error.from_e(ValueError("bad value"), "item2"))
57
57
  lst.append(OK)
58
- lst.append(Simple[int]("item3", value=100))
58
+ lst.append(Option[int](100, "item3"))
59
59
  self.assertEqual(len(lst.value), 4)
60
60
  self.assertEqual(lst.value[0], 42)
61
61
  self.assertIsInstance(lst.value[2], Ok)
@@ -65,8 +65,8 @@ class TestResultSystem(unittest.TestCase):
65
65
  self.assertIsInstance(lst.err.exceptions[0].exceptions[0], ValueError)
66
66
 
67
67
  def test_list_operator_overload(self) -> None:
68
- lst = List[str]("test") + Simple[str]("first", value="hello")
69
- lst += Error(TypeError("type error"), "second")
68
+ lst = List[str]("test") + Option[str]("hello", "first")
69
+ lst += Error.from_e(TypeError("type error"), "second")
70
70
  self.assertEqual(len(lst.value), 2)
71
71
  self.assertEqual(lst.value[0], "hello")
72
72
  self.assertFalse(lst.is_ok())
@@ -75,8 +75,8 @@ class TestResultSystem(unittest.TestCase):
75
75
  exc1 = ValueError("val1")
76
76
  exc2 = TypeError("type1")
77
77
  exc3 = KeyError("key1")
78
- res1 = Simple[None]("group1").append_err(exc1).append_err(exc2)
79
- res2 = Simple[None]("group1").append_err(exc3)
78
+ res1: Option[object] = Option(msg="group1").append_err(exc1).append_err(exc2)
79
+ res2: Option[object] = Option(msg="group1").append_err(exc3)
80
80
  res1.propagate_err(res2)
81
81
  self.assertEqual(len(res1.err.exceptions), 3)
82
82
  self.assertEqual(res1.err.message, "group1")
@@ -84,34 +84,34 @@ class TestResultSystem(unittest.TestCase):
84
84
  def test_different_error_groups(self) -> None:
85
85
  exc1 = ValueError("val1")
86
86
  exc2 = TypeError("type1")
87
- res1 = Simple[None]("group1").append_err(exc1)
88
- res2 = Simple[None]("group2").append_err(exc2)
87
+ res1: Option[object] = Option(msg="group1").append_err(exc1)
88
+ res2: Option[object] = Option(msg="group2").append_err(exc2)
89
89
  res1.propagate_err(res2)
90
90
  self.assertEqual(len(res1.err.exceptions), 2)
91
91
  self.assertIsInstance(res1.err.exceptions[1], ExceptionGroup)
92
92
 
93
93
  def test_set_operation(self) -> None:
94
- main = Simple[str]("main")
95
- other = Simple[str]("other", value="data")
94
+ main: Option[str] = Option(msg="main")
95
+ other: Option[str] = Option("data", "other")
96
96
  result = main.set(other)
97
97
  self.assertEqual(main.value, "data")
98
98
  self.assertEqual(result, "data")
99
99
  self.assertTrue(main.is_ok())
100
100
 
101
101
  def test_bool_set_operation(self) -> None:
102
- main = Bool("main")
103
- other = Bool("other", value=True)
102
+ main = Bool(msg="main")
103
+ other = Bool(value=True, msg="other")
104
104
  result = main.set(other)
105
105
  self.assertTrue(main.value)
106
106
  self.assertTrue(result)
107
107
 
108
108
  def test_simple_none_value(self) -> None:
109
- res = Simple[Optional[int]]("test", value=None)
109
+ res: Option[int] = Option(msg="test")
110
110
  self.assertTrue(res.is_ok())
111
111
  self.assertIsNone(res.unwrap())
112
112
 
113
113
  def test_bool_false_with_error(self) -> None:
114
- res = Bool("test", value=False)
114
+ res = Bool(value=False, msg="test")
115
115
  res.append_err(ValueError("bool error"))
116
116
  self.assertFalse(res.value)
117
117
  self.assertFalse(res.is_ok())
@@ -121,7 +121,7 @@ class TestResultSystem(unittest.TestCase):
121
121
  def test_nested_exception_groups(self) -> None:
122
122
  inner_group = ExceptionGroup("inner", [ValueError("v1"), TypeError("t1")])
123
123
  outer_group = ExceptionGroup("outer", [inner_group, KeyError("k1")])
124
- res = Simple[int]("test").append_err(outer_group)
124
+ res = Option[int](msg="test").append_err(outer_group)
125
125
  if res.err is not None:
126
126
  self.assertEqual(len(res.err.exceptions), 1)
127
127
  self.assertIsInstance(res.err.exceptions[0], ExceptionGroup)
@@ -135,35 +135,35 @@ class TestResultSystem(unittest.TestCase):
135
135
  self.assertIsNone(lst.err)
136
136
 
137
137
  def test_list_mixed_types(self) -> None:
138
- lst = List[object]("mixed")
139
- lst.append(Simple[int]("int", value=42))
140
- lst.append(Simple[str]("str", value="hello"))
141
- lst.append(Error(ValueError("error"), "error"))
138
+ lst: List[str | int] = List("mixed")
139
+ lst.append(Option(42, "int"))
140
+ lst.append(Option("hello", "str"))
141
+ lst.append(Error.from_e(ValueError("error"), "error"))
142
142
  self.assertEqual(len(lst.value), 3)
143
143
  self.assertEqual(lst.value[0], 42)
144
144
  self.assertEqual(lst.value[1], "hello")
145
145
  self.assertIsInstance(lst.value[2], type(None))
146
146
 
147
147
  def test_propagate_none(self) -> None:
148
- res = Simple[int]("main", value=42)
149
- res.propagate_err(Simple[int]("other"))
148
+ res = Option[int](42, "main")
149
+ res.propagate_err(Option[int](msg="other"))
150
150
  self.assertTrue(res.is_ok())
151
151
  self.assertEqual(res.unwrap(), 42)
152
152
 
153
153
  def test_type_hints(self) -> None:
154
- def processor() -> Simple[str]:
155
- return Simple[str]("processor", value="result")
154
+ def processor() -> Option[str]:
155
+ return Option[str]("result", "processor")
156
156
 
157
157
  result = processor()
158
- value: str = result.unwrap()
158
+ value: str | None = result.unwrap()
159
159
  self.assertEqual(value, "result")
160
160
 
161
161
  def test_combined_workflow(self) -> None:
162
162
  main = List[int]("combined workflow")
163
- main += Simple[int]("op1", value=10)
164
- main += Simple[int]("op2", value=20)
165
- main += Error(ValueError("invalid value"), "op3")
166
- main += Simple[int]("op4", value=30)
163
+ main += Option[int](10, "op1")
164
+ main += Option[int](20, "op2")
165
+ main += Error.from_e(ValueError("invalid value"), "op3")
166
+ main += Option[int](30, "op4")
167
167
  self.assertEqual(len(main.value), 4)
168
168
  self.assertEqual(main.value[0], 10)
169
169
  self.assertEqual(main.value[1], 20)
@@ -174,42 +174,40 @@ class TestResultSystem(unittest.TestCase):
174
174
  main.unwrap()
175
175
 
176
176
  def test_multiple_propagations(self) -> None:
177
- res1 = Simple[int]("first").append_err(ValueError("v1"))
178
- res2 = Simple[int]("second").append_err(TypeError("t1"))
179
- res3 = Simple[int]("third").append_err(KeyError("k1"))
180
-
181
- main = Simple[int]("main")
177
+ res1: Option[int] = Option(msg="first").append_err(ValueError("v1"))
178
+ res2: Option[int] = Option(msg="second").append_err(TypeError("t1"))
179
+ res3: Option[int] = Option(msg="third").append_err(KeyError("k1"))
180
+ main: Option[int] = Option(msg="main")
182
181
  main.propagate_err(res1)
183
182
  main.propagate_err(res2)
184
183
  main.propagate_err(res3)
185
-
186
184
  self.assertEqual(len(main.err.exceptions), 3)
187
185
 
188
- @patch.object(Simple, "append_err")
186
+ @patch.object(Option, "append_err")
189
187
  def test_propagate_err_calls(self, mock_append: Any) -> None:
190
- err_res = Simple[int]("error")
188
+ err_res = Option[int](msg="error")
191
189
  err_res.err = ExceptionGroup("error", [ValueError("test")])
192
- main = Simple[int]("main")
190
+ main = Option[int](msg="main")
193
191
  main.propagate_err(err_res)
194
192
  mock_append.assert_called_once_with(err_res.err)
195
193
 
196
194
  def test_iterator_protocol(self) -> None:
197
- res = Simple[str]("iter", value="test")
195
+ res = Option[str]("test", "iter")
198
196
  values = list(res)
199
197
  self.assertEqual(len(values), 2)
200
198
  self.assertEqual(values[0], "test")
201
199
  self.assertIsNone(values[1])
202
200
 
203
201
  def test_bool_truthiness(self) -> None:
204
- true_res = Bool("true", value=True)
205
- false_res = Bool("false", value=False)
202
+ true_res = Bool(value=True, msg="true")
203
+ false_res = Bool(value=False, msg="false")
206
204
  self.assertTrue(true_res.value)
207
205
  self.assertFalse(false_res.value)
208
206
  self.assertTrue(bool(true_res.unwrap()))
209
207
  self.assertFalse(bool(false_res.unwrap()))
210
208
 
211
- def test_equal(self):
212
- res = Simple("1")
209
+ def test_equal(self) -> None:
210
+ res: Option[str] = Option(msg="1")
213
211
  group = ExceptionGroup("1", (ValueError("1"),))
214
212
  res.append_err(group)
215
213
  self.assertEqual(res.err, group)
File without changes
File without changes