StructResult 0.6.2__tar.gz → 0.7.0__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.6.2
3
+ Version: 0.7.0
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.6.2"
12
+ version = "0.7.0"
13
13
  requires-python = ">= 3.12"
14
14
  authors = [
15
15
  {name="Serj Kotilevski", email="youserj@outlook.com"}
@@ -64,8 +64,7 @@ exclude = [
64
64
  "venv",
65
65
  ]
66
66
  include = [
67
- "src/*/*.py",
68
- "examples/*/*.py",
67
+ "src/**/*.py",
69
68
  "test/test_*.py"
70
69
  ]
71
70
 
@@ -1,28 +1,19 @@
1
1
  from dataclasses import dataclass, field
2
- from typing import Optional, Self, Any, Protocol, Iterator, Final
2
+ from typing import Optional, Self, Protocol, Iterator, Any
3
3
 
4
4
 
5
- class Result[T](Protocol):
6
- value: Optional[T]
7
- err: Optional[ExceptionGroup]
8
- msg: str = ""
5
+ class Result(Protocol):
6
+ msg: str
9
7
 
10
- def __iter__(self) -> Iterator[T | ExceptionGroup[Exception] | None]:
11
- return iter((self.value, self.err))
8
+ def is_ok(self) -> bool: ...
12
9
 
13
- def unwrap(self) -> Optional[T]:
14
- if self.err:
15
- raise self.err
16
- return self.value
10
+
11
+ class ErrorPropagator(Result, Protocol):
12
+ err: Optional[ExceptionGroup]
17
13
 
18
14
  def is_ok(self) -> bool:
19
15
  return self.err is None
20
16
 
21
-
22
- class ErrorGrouper(Protocol):
23
- err: Optional[ExceptionGroup]
24
- msg: str = ""
25
-
26
17
  def append_err(self, e: Exception | ExceptionGroup) -> Self:
27
18
  """append except"""
28
19
  if isinstance(e, ExceptionGroup):
@@ -41,61 +32,66 @@ class ErrorGrouper(Protocol):
41
32
  self.err = ExceptionGroup(self.msg, (e, self.err))
42
33
  return self
43
34
 
44
-
45
- class ErrorPropagator(ErrorGrouper, Protocol):
46
- def propagate_err[T](self, res: Result[T]) -> Optional[T]:
35
+ def propagate_err[T](self, res: "Collector[T]") -> Optional[T]:
47
36
  """Propagates (merges) the error from another Result into this one, returning its value"""
48
37
  if res.err is not None:
49
38
  self.append_err(res.err)
50
- return res.value
39
+ return res.value if hasattr(res, "value") else None
51
40
 
52
41
 
53
- class Appender[T](ErrorPropagator, Protocol):
54
- def append(self, res: Result[T]) -> Optional[T]: ...
42
+ class Collector[T](ErrorPropagator, Protocol):
43
+ value: T
44
+
45
+ def __iter__(self) -> Iterator[Any]:
46
+ return iter((self.value, self.err))
47
+
48
+ def unwrap(self) -> T:
49
+ if self.err:
50
+ raise self.err
51
+ return self.value
55
52
 
56
53
 
57
54
  @dataclass(slots=True)
58
- class Simple[T](Result[T], Appender[T]):
55
+ class Simple[T](Collector[Optional[T]], Result):
56
+ msg: str = ""
59
57
  value: Optional[T] = field(default=None)
60
- msg: str = field(default="")
61
58
  err: Optional[ExceptionGroup] = field(init=False, default=None)
62
59
 
63
- def append(self, res: Result[T]) -> Optional[T]:
60
+ def set(self, res: "Simple[T]") -> Optional[T]:
64
61
  """set value and append errors"""
65
62
  self.value = res.value
66
63
  return self.propagate_err(res)
67
64
 
68
65
 
69
- @dataclass(frozen=True)
70
- class Null(Result[Any]):
71
- value: Final[None] = None
72
- err: None = None
66
+ @dataclass(slots=True)
67
+ class Null(Result):
68
+ msg: str = ""
73
69
 
70
+ def is_ok(self) -> bool:
71
+ return True
74
72
 
75
- NONE = Null()
76
- """None result"""
77
73
 
74
+ class Error(ErrorPropagator):
75
+ __slots__ = ("msg", "err")
78
76
 
79
- @dataclass(slots=True)
80
- class Error(ErrorPropagator, Result[Any]):
81
- value: Final[None] = field(default=None)
82
- msg: str = field(default="")
83
- err: Optional[ExceptionGroup] = field(init=False, default=None)
77
+ def __init__(self, e: Exception, msg: str = "") -> None:
78
+ self.msg = msg
79
+ self.err = ExceptionGroup(self.msg, (e,))
84
80
 
85
81
 
86
82
  @dataclass(slots=True)
87
- class List[T](Appender[T], Result[list[Optional[T]]]):
88
- msg: str = field(default="")
89
- value: Optional[list[Optional[T]]] = field(init=False, default=None)
83
+ class List[T](Collector[list[Optional[T]]], Result):
84
+ msg: str = ""
85
+ value: list[Optional[T]] = field(init=False, default_factory=list)
90
86
  err: Optional[ExceptionGroup] = field(init=False, default=None)
91
87
 
92
- def append(self, res: Result[T]) -> Optional[T]:
88
+ def append(self, res: Simple[T]) -> Optional[T]:
93
89
  """append value and errors"""
94
90
  if self.value is None:
95
91
  self.value = []
96
92
  self.value.append(res.value)
97
93
  return self.propagate_err(res)
98
94
 
99
- def __add__(self, other: Result[T]) -> Self:
95
+ def __add__(self, other: Simple[T]) -> Self:
100
96
  self.append(other)
101
97
  return self
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: StructResult
3
- Version: 0.6.2
3
+ Version: 0.7.0
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
@@ -17,8 +17,7 @@ class TestFormatEG(unittest.TestCase):
17
17
 
18
18
  # Create test Result objects
19
19
  self.simple_result = Simple[str](value="test")
20
- self.error_result = Error(msg="error occurred")
21
- self.error_result.append_err(self.simple_error)
20
+ self.error_result = Error(self.simple_error, msg="error occurred")
22
21
  self.list_result = List[int]()
23
22
  self.list_result.append(Simple[int](value=42))
24
23
  self.list_result.append(Simple[int](value=None))
@@ -86,8 +85,7 @@ class TestFormatEG(unittest.TestCase):
86
85
  self.assertTrue(result.endswith(expected))
87
86
 
88
87
  def test_protocol_compatibility(self) -> None:
89
- error_result = Error(msg="test")
90
- error_result.append_err(self.complex_group)
88
+ error_result = Error(self.complex_group, msg="test")
91
89
 
92
90
  self.assertIsInstance(error_result.err, BaseExceptionGroup)
93
91
  if error_result.err is not None:
@@ -1,6 +1,6 @@
1
1
  import unittest
2
2
  from typing import Any
3
- from src.StructResult.result import Simple, NONE, Error, List
3
+ from src.StructResult.result import Simple, Error, List, Null
4
4
 
5
5
 
6
6
  class TestResultProtocols(unittest.TestCase):
@@ -28,20 +28,12 @@ class TestResultProtocols(unittest.TestCase):
28
28
  self.assertEqual(list(res), [42, res.err])
29
29
 
30
30
  def test_null(self) -> None:
31
- self.assertIsNone(NONE.value)
32
- self.assertIsNone(NONE.err)
33
- self.assertTrue(NONE.is_ok())
34
- self.assertIsNone(NONE.unwrap())
35
- self.assertEqual(list(NONE), [None, None])
31
+ self.assertTrue(Null().is_ok())
36
32
 
37
33
  def test_error(self) -> None:
38
- err = Error(msg="test")
39
- err.append_err(self.exception1)
40
- self.assertIsNone(err.value)
34
+ err = Error(self.exception1, msg="test")
41
35
  self.assertIsNotNone(err.err)
42
36
  self.assertFalse(err.is_ok())
43
- with self.assertRaises(ExceptionGroup):
44
- err.unwrap()
45
37
 
46
38
  def test_list_append(self) -> None:
47
39
  lst = List[int]()
@@ -136,12 +128,12 @@ class TestResultProtocols(unittest.TestCase):
136
128
  res_err.append_err(self.exception1)
137
129
 
138
130
  # Append OK result
139
- simple.append(res_ok)
131
+ simple.set(res_ok)
140
132
  self.assertEqual(simple.value, 42)
141
133
  self.assertIsNone(simple.err)
142
134
 
143
135
  # Append error result
144
- simple.append(res_err)
136
+ simple.set(res_err)
145
137
  self.assertEqual(simple.value, 0)
146
138
  self.assertIsNotNone(simple.err)
147
139
 
File without changes
File without changes