StructResult 0.6.0__tar.gz → 0.6.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.
- {structresult-0.6.0 → structresult-0.6.2}/PKG-INFO +1 -1
- {structresult-0.6.0 → structresult-0.6.2}/pyproject.toml +2 -1
- {structresult-0.6.0 → structresult-0.6.2}/src/StructResult/formatter.py +6 -3
- {structresult-0.6.0 → structresult-0.6.2}/src/StructResult.egg-info/PKG-INFO +1 -1
- {structresult-0.6.0 → structresult-0.6.2}/src/StructResult.egg-info/SOURCES.txt +1 -1
- {structresult-0.6.0 → structresult-0.6.2}/test/test_formatter.py +24 -23
- {structresult-0.6.0 → structresult-0.6.2}/test/test_result.py +29 -23
- {structresult-0.6.0 → structresult-0.6.2}/README.md +0 -0
- {structresult-0.6.0 → structresult-0.6.2}/setup.cfg +0 -0
- {structresult-0.6.0 → structresult-0.6.2}/src/StructResult/__init__.py +0 -0
- /structresult-0.6.0/src/StructResult/py.typed.py → /structresult-0.6.2/src/StructResult/py.typed +0 -0
- {structresult-0.6.0 → structresult-0.6.2}/src/StructResult/result.py +0 -0
- {structresult-0.6.0 → structresult-0.6.2}/src/StructResult.egg-info/dependency_links.txt +0 -0
- {structresult-0.6.0 → structresult-0.6.2}/src/StructResult.egg-info/requires.txt +0 -0
- {structresult-0.6.0 → structresult-0.6.2}/src/StructResult.egg-info/top_level.txt +0 -0
|
@@ -9,7 +9,7 @@ where = ["src"]
|
|
|
9
9
|
|
|
10
10
|
[project]
|
|
11
11
|
name = "StructResult"
|
|
12
|
-
version = "0.6.
|
|
12
|
+
version = "0.6.2"
|
|
13
13
|
requires-python = ">= 3.12"
|
|
14
14
|
authors = [
|
|
15
15
|
{name="Serj Kotilevski", email="youserj@outlook.com"}
|
|
@@ -51,6 +51,7 @@ explicit_package_bases = true
|
|
|
51
51
|
[tool.ruff]
|
|
52
52
|
src = ["src"]
|
|
53
53
|
line-length = 150
|
|
54
|
+
preview = true
|
|
54
55
|
exclude = [
|
|
55
56
|
".git",
|
|
56
57
|
".mypy_cache",
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
from typing import Callable
|
|
2
|
+
|
|
3
|
+
|
|
1
4
|
def format_eg(
|
|
2
|
-
eg:
|
|
5
|
+
eg: ExceptionGroup,
|
|
3
6
|
indent: int = 0,
|
|
4
7
|
*,
|
|
5
8
|
prefix: str = " ",
|
|
6
9
|
bullet: str = "- ",
|
|
7
10
|
show_count: bool = True,
|
|
8
|
-
repr_fn:
|
|
11
|
+
repr_fn: Callable[[BaseException], str] = repr,
|
|
9
12
|
) -> str:
|
|
10
13
|
"""
|
|
11
14
|
Formats an ExceptionGroup into a readable tree-like string representation.
|
|
@@ -35,7 +38,7 @@ def format_eg(
|
|
|
35
38
|
- TypeError('Bad type')
|
|
36
39
|
"""
|
|
37
40
|
current_prefix = prefix * indent
|
|
38
|
-
count_info = f" ({len(eg.exceptions)} sub-exception{'s'[:len(eg.exceptions)!=1]})" if show_count else ""
|
|
41
|
+
count_info = f" ({len(eg.exceptions)} sub-exception{'s'[:len(eg.exceptions) != 1]})" if show_count else ""
|
|
39
42
|
msg = [f"{current_prefix}{eg.message}{count_info}:"]
|
|
40
43
|
|
|
41
44
|
for exc in eg.exceptions:
|
|
@@ -4,7 +4,7 @@ from src.StructResult.formatter import format_eg
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class TestFormatEG(unittest.TestCase):
|
|
7
|
-
def setUp(self):
|
|
7
|
+
def setUp(self) -> None:
|
|
8
8
|
self.simple_error = ValueError("Simple error")
|
|
9
9
|
self.nested_group = ExceptionGroup("Nested", [TypeError("Type error")])
|
|
10
10
|
|
|
@@ -23,18 +23,18 @@ class TestFormatEG(unittest.TestCase):
|
|
|
23
23
|
self.list_result.append(Simple[int](value=42))
|
|
24
24
|
self.list_result.append(Simple[int](value=None))
|
|
25
25
|
|
|
26
|
-
def test_basic_exception_group(self):
|
|
26
|
+
def test_basic_exception_group(self) -> None:
|
|
27
27
|
eg = ExceptionGroup("Test", [self.simple_error])
|
|
28
28
|
result = format_eg(eg)
|
|
29
29
|
expected = "Test (1 sub-exception):\n - ValueError('Simple error')"
|
|
30
30
|
self.assertEqual(result, expected)
|
|
31
31
|
|
|
32
|
-
def test_nested_exception_group(self):
|
|
32
|
+
def test_nested_exception_group(self) -> None:
|
|
33
33
|
result = format_eg(self.nested_group)
|
|
34
34
|
expected = "Nested (1 sub-exception):\n - TypeError('Type error')"
|
|
35
35
|
self.assertEqual(result, expected)
|
|
36
36
|
|
|
37
|
-
def test_complex_exception_group(self):
|
|
37
|
+
def test_complex_exception_group(self) -> None:
|
|
38
38
|
result = format_eg(self.complex_group)
|
|
39
39
|
expected = (
|
|
40
40
|
"Complex (3 sub-exceptions):\n"
|
|
@@ -46,22 +46,22 @@ class TestFormatEG(unittest.TestCase):
|
|
|
46
46
|
)
|
|
47
47
|
self.assertEqual(result, expected)
|
|
48
48
|
|
|
49
|
-
def test_with_result_protocol(self):
|
|
49
|
+
def test_with_result_protocol(self) -> None:
|
|
50
50
|
error_result = Simple[str](value=None)
|
|
51
51
|
error_result.append_err(self.complex_group)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def test_custom_formatting(self):
|
|
52
|
+
if error_result.err is not None:
|
|
53
|
+
result = format_eg(error_result.err)
|
|
54
|
+
expected = (
|
|
55
|
+
"Complex (3 sub-exceptions):\n"
|
|
56
|
+
" - ValueError('Simple error')\n"
|
|
57
|
+
" Nested (1 sub-exception):\n"
|
|
58
|
+
" - TypeError('Type error')\n"
|
|
59
|
+
" With content (1 sub-exception):\n"
|
|
60
|
+
" - ValueError('Placeholder')"
|
|
61
|
+
)
|
|
62
|
+
self.assertEqual(result, expected)
|
|
63
|
+
|
|
64
|
+
def test_custom_formatting(self) -> None:
|
|
65
65
|
eg = ExceptionGroup("Custom", [self.simple_error])
|
|
66
66
|
result = format_eg(
|
|
67
67
|
eg,
|
|
@@ -73,7 +73,7 @@ class TestFormatEG(unittest.TestCase):
|
|
|
73
73
|
expected = "Custom:\n * ValueError: Simple error"
|
|
74
74
|
self.assertEqual(result, expected)
|
|
75
75
|
|
|
76
|
-
def test_with_list_result_errors(self):
|
|
76
|
+
def test_with_list_result_errors(self) -> None:
|
|
77
77
|
list_result = List[int]()
|
|
78
78
|
list_result.append(Simple[int](value=1))
|
|
79
79
|
error_result = Simple[int](value=2)
|
|
@@ -85,15 +85,16 @@ class TestFormatEG(unittest.TestCase):
|
|
|
85
85
|
expected = " (1 sub-exception):\n - ValueError('Simple error')"
|
|
86
86
|
self.assertTrue(result.endswith(expected))
|
|
87
87
|
|
|
88
|
-
def test_protocol_compatibility(self):
|
|
88
|
+
def test_protocol_compatibility(self) -> None:
|
|
89
89
|
error_result = Error(msg="test")
|
|
90
90
|
error_result.append_err(self.complex_group)
|
|
91
91
|
|
|
92
92
|
self.assertIsInstance(error_result.err, BaseExceptionGroup)
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
if error_result.err is not None:
|
|
94
|
+
formatted = format_eg(error_result.err)
|
|
95
|
+
self.assertIn("Complex (3 sub-exceptions)", formatted)
|
|
95
96
|
|
|
96
|
-
def test_multiple_nesting_levels(self):
|
|
97
|
+
def test_multiple_nesting_levels(self) -> None:
|
|
97
98
|
level3 = ExceptionGroup("Level3", [RuntimeError("Deep error")])
|
|
98
99
|
level2 = ExceptionGroup("Level2", [level3])
|
|
99
100
|
level1 = ExceptionGroup("Level1", [level2])
|
|
@@ -4,12 +4,12 @@ from src.StructResult.result import Simple, NONE, Error, List
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class TestResultProtocols(unittest.TestCase):
|
|
7
|
-
def setUp(self):
|
|
7
|
+
def setUp(self) -> None:
|
|
8
8
|
self.exception1 = ValueError("Error 1")
|
|
9
9
|
self.exception2 = TypeError("Error 2")
|
|
10
10
|
self.exception_group = ExceptionGroup("msg", [self.exception1, self.exception2])
|
|
11
11
|
|
|
12
|
-
def test_simple_ok(self):
|
|
12
|
+
def test_simple_ok(self) -> None:
|
|
13
13
|
res = Simple[int](value=42)
|
|
14
14
|
self.assertEqual(res.value, 42)
|
|
15
15
|
self.assertIsNone(res.err)
|
|
@@ -17,7 +17,7 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
17
17
|
self.assertEqual(res.unwrap(), 42)
|
|
18
18
|
self.assertEqual(list(res), [42, None])
|
|
19
19
|
|
|
20
|
-
def test_simple_err(self):
|
|
20
|
+
def test_simple_err(self) -> None:
|
|
21
21
|
res = Simple[int](value=42)
|
|
22
22
|
res.append_err(self.exception1)
|
|
23
23
|
self.assertEqual(res.value, 42)
|
|
@@ -27,14 +27,14 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
27
27
|
res.unwrap()
|
|
28
28
|
self.assertEqual(list(res), [42, res.err])
|
|
29
29
|
|
|
30
|
-
def test_null(self):
|
|
30
|
+
def test_null(self) -> None:
|
|
31
31
|
self.assertIsNone(NONE.value)
|
|
32
32
|
self.assertIsNone(NONE.err)
|
|
33
33
|
self.assertTrue(NONE.is_ok())
|
|
34
34
|
self.assertIsNone(NONE.unwrap())
|
|
35
35
|
self.assertEqual(list(NONE), [None, None])
|
|
36
36
|
|
|
37
|
-
def test_error(self):
|
|
37
|
+
def test_error(self) -> None:
|
|
38
38
|
err = Error(msg="test")
|
|
39
39
|
err.append_err(self.exception1)
|
|
40
40
|
self.assertIsNone(err.value)
|
|
@@ -43,7 +43,7 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
43
43
|
with self.assertRaises(ExceptionGroup):
|
|
44
44
|
err.unwrap()
|
|
45
45
|
|
|
46
|
-
def test_list_append(self):
|
|
46
|
+
def test_list_append(self) -> None:
|
|
47
47
|
lst = List[int]()
|
|
48
48
|
lst.append(Simple[int](value=1))
|
|
49
49
|
lst.append(Simple[int](value=2))
|
|
@@ -51,7 +51,7 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
51
51
|
self.assertIsNone(lst.err)
|
|
52
52
|
self.assertTrue(lst.is_ok())
|
|
53
53
|
|
|
54
|
-
def test_list_append_with_errors(self):
|
|
54
|
+
def test_list_append_with_errors(self) -> None:
|
|
55
55
|
lst = List[int]()
|
|
56
56
|
res1 = Simple[int](value=1)
|
|
57
57
|
res1.append_err(self.exception1)
|
|
@@ -63,10 +63,11 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
63
63
|
|
|
64
64
|
self.assertEqual(lst.value, [1, 2])
|
|
65
65
|
self.assertIsNotNone(lst.err)
|
|
66
|
-
|
|
66
|
+
if lst.err is not None:
|
|
67
|
+
self.assertEqual(len(lst.err.exceptions), 2)
|
|
67
68
|
self.assertFalse(lst.is_ok())
|
|
68
69
|
|
|
69
|
-
def test_list_add_operator(self):
|
|
70
|
+
def test_list_add_operator(self) -> None:
|
|
70
71
|
lst = List[int]()
|
|
71
72
|
res1 = Simple[int](value=1)
|
|
72
73
|
res2 = Simple[int](value=2)
|
|
@@ -74,7 +75,7 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
74
75
|
lst += res2
|
|
75
76
|
self.assertEqual(lst.value, [1, 2])
|
|
76
77
|
|
|
77
|
-
def test_propagate_err(self):
|
|
78
|
+
def test_propagate_err(self) -> None:
|
|
78
79
|
target = Simple[str](msg="target")
|
|
79
80
|
source_ok = Simple[str](value="ok")
|
|
80
81
|
source_err = Simple[str](value="err")
|
|
@@ -89,18 +90,20 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
89
90
|
result = target.propagate_err(source_err)
|
|
90
91
|
self.assertEqual(result, "err")
|
|
91
92
|
self.assertIsNotNone(target.err)
|
|
92
|
-
|
|
93
|
+
if target.err is not None:
|
|
94
|
+
self.assertEqual(len(target.err.exceptions), 1)
|
|
93
95
|
|
|
94
|
-
def test_error_grouping(self):
|
|
96
|
+
def test_error_grouping(self) -> None:
|
|
95
97
|
grouper = Simple[Any](msg="group")
|
|
96
98
|
grouper.append_err(self.exception1)
|
|
97
99
|
grouper.append_err(self.exception2)
|
|
98
100
|
|
|
99
101
|
self.assertIsNotNone(grouper.err)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
if grouper.err is not None:
|
|
103
|
+
self.assertEqual(len(grouper.err.exceptions), 2)
|
|
104
|
+
self.assertEqual(grouper.err.message, "group")
|
|
102
105
|
|
|
103
|
-
def test_exception_group_merging(self):
|
|
106
|
+
def test_exception_group_merging(self) -> None:
|
|
104
107
|
grouper = Simple[Any](msg="group")
|
|
105
108
|
group1 = ExceptionGroup("group", [self.exception1])
|
|
106
109
|
group2 = ExceptionGroup("group", [self.exception2])
|
|
@@ -109,10 +112,11 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
109
112
|
grouper.append_err(group2)
|
|
110
113
|
|
|
111
114
|
self.assertIsNotNone(grouper.err)
|
|
112
|
-
|
|
113
|
-
|
|
115
|
+
if grouper.err is not None:
|
|
116
|
+
self.assertEqual(len(grouper.err.exceptions), 2)
|
|
117
|
+
self.assertEqual(grouper.err.message, "group")
|
|
114
118
|
|
|
115
|
-
def test_different_message_groups(self):
|
|
119
|
+
def test_different_message_groups(self) -> None:
|
|
116
120
|
grouper = Simple[Any](msg="main")
|
|
117
121
|
group = ExceptionGroup("other", [self.exception1])
|
|
118
122
|
|
|
@@ -120,11 +124,12 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
120
124
|
|
|
121
125
|
self.assertIsNotNone(grouper.err)
|
|
122
126
|
# Should be wrapped in a new group with "main" message
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
if grouper.err is not None:
|
|
128
|
+
self.assertEqual(grouper.err.message, "other")
|
|
129
|
+
self.assertEqual(len(grouper.err.exceptions), 1)
|
|
125
130
|
self.assertIsInstance(grouper.err, ExceptionGroup)
|
|
126
131
|
|
|
127
|
-
def test_simple_append(self):
|
|
132
|
+
def test_simple_append(self) -> None:
|
|
128
133
|
simple = Simple[Any]()
|
|
129
134
|
res_ok = Simple[int](value=42)
|
|
130
135
|
res_err = Simple[int](value=0)
|
|
@@ -140,7 +145,7 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
140
145
|
self.assertEqual(simple.value, 0)
|
|
141
146
|
self.assertIsNotNone(simple.err)
|
|
142
147
|
|
|
143
|
-
def test_list_multiple_appends(self):
|
|
148
|
+
def test_list_multiple_appends(self) -> None:
|
|
144
149
|
lst = List[int]()
|
|
145
150
|
res1 = Simple[int](value=1)
|
|
146
151
|
res2 = Simple[int](value=2)
|
|
@@ -153,4 +158,5 @@ class TestResultProtocols(unittest.TestCase):
|
|
|
153
158
|
|
|
154
159
|
self.assertEqual(lst.value, [1, 2, 3])
|
|
155
160
|
self.assertIsNotNone(lst.err)
|
|
156
|
-
|
|
161
|
+
if lst.err is not None:
|
|
162
|
+
self.assertEqual(len(lst.err.exceptions), 1)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/structresult-0.6.0/src/StructResult/py.typed.py → /structresult-0.6.2/src/StructResult/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|