errortools 3.0.0__tar.gz → 3.1.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.
- errortools-3.1.0/AUTHORS.txt +12 -0
- {errortools-3.0.0/errortools.egg-info → errortools-3.1.0}/PKG-INFO +3 -2
- {errortools-3.0.0 → errortools-3.1.0}/README.md +2 -1
- errortools-3.1.0/_errortools/_speedup.c +127 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/cli.py +1 -1
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/ignore.py +8 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/typing.py +16 -4
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/version.py +2 -2
- {errortools-3.0.0 → errortools-3.1.0/errortools.egg-info}/PKG-INFO +3 -2
- errortools-3.1.0/errortools.egg-info/SOURCES.txt +47 -0
- {errortools-3.0.0 → errortools-3.1.0}/errortools.egg-info/entry_points.txt +0 -1
- {errortools-3.0.0 → errortools-3.1.0}/errortools.egg-info/top_level.txt +1 -1
- {errortools-3.0.0 → errortools-3.1.0}/setup.py +4 -4
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/__init__.py +1 -2
- errortools-3.1.0/testing/__main__.py +4 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_abc.py +0 -3
- errortools-3.1.0/testing/test_groups.py +130 -0
- errortools-3.0.0/AUTHORS.txt +0 -3
- errortools-3.0.0/_errortools/_speedup.c +0 -58
- errortools-3.0.0/_errortools/classes/__init__.py +0 -1
- errortools-3.0.0/_errortools/classes/abc.py +0 -211
- errortools-3.0.0/_errortools/classes/errorcodes.py +0 -273
- errortools-3.0.0/_errortools/classes/group.py +0 -121
- errortools-3.0.0/_errortools/classes/warn.py +0 -124
- errortools-3.0.0/_errortools/decorator/__init__.py +0 -1
- errortools-3.0.0/_errortools/decorator/cache.py +0 -82
- errortools-3.0.0/_errortools/decorator/deprecated.py +0 -61
- errortools-3.0.0/_errortools/descriptor/__init__.py +0 -2
- errortools-3.0.0/_errortools/descriptor/errormsg.py +0 -37
- errortools-3.0.0/_errortools/descriptor/nonblankmsg.py +0 -52
- errortools-3.0.0/_errortools/logging/__init__.py +0 -43
- errortools-3.0.0/_errortools/logging/base.py +0 -467
- errortools-3.0.0/_errortools/logging/level.py +0 -85
- errortools-3.0.0/_errortools/logging/logger.py +0 -13
- errortools-3.0.0/_errortools/logging/record.py +0 -116
- errortools-3.0.0/_errortools/logging/sink.py +0 -243
- errortools-3.0.0/_errortools/wrappers/__init__.py +0 -2
- errortools-3.0.0/_errortools/wrappers/cache.py +0 -101
- errortools-3.0.0/_errortools/wrappers/ignore.py +0 -122
- errortools-3.0.0/errortools.egg-info/SOURCES.txt +0 -66
- errortools-3.0.0/tests/test_groups.py +0 -128
- {errortools-3.0.0 → errortools-3.1.0}/LICENSE.txt +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/__init__.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/_cli.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/const.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/errno.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/future.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/metadata.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/partial.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/py.typed +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/_errortools/raises.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/errortools/__init__.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/errortools/__main__.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/errortools/future.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/errortools/logging.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/errortools/partial.py +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/errortools.egg-info/dependency_links.txt +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/errortools.egg-info/requires.txt +0 -0
- {errortools-3.0.0 → errortools-3.1.0}/setup.cfg +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/conftest.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/run_tests.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_const.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_decorator.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_descriptor.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_errno.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_errorcodes.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_future.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_ignore.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_logging.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_partials.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_raises.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_typing.py +0 -0
- {errortools-3.0.0/tests → errortools-3.1.0/testing}/test_warnings.py +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# (Lines starting with # are comments)
|
|
2
|
+
# Tips:
|
|
3
|
+
# Contributors are not sorted by initials,
|
|
4
|
+
# but by contribution time.
|
|
5
|
+
# Here are the real contributors
|
|
6
|
+
aiwonderland
|
|
7
|
+
qorexdev
|
|
8
|
+
vgauraha62
|
|
9
|
+
yangphysics
|
|
10
|
+
# And here are bot contributors
|
|
11
|
+
dependabot[bot]
|
|
12
|
+
AbaAbaAba-bot-like[bot]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: errortools
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: errortools - a toolset for working with Python exceptions and warnings and logging.
|
|
5
5
|
Home-page: https://github.com/more-abc/errortools
|
|
6
6
|
Author: Evan Yang
|
|
@@ -46,6 +46,7 @@ A lightweight Python exception handling utility library.
|
|
|
46
46
|

|
|
47
47
|

|
|
48
48
|

|
|
49
|
+

|
|
49
50
|
|
|
50
51
|
## Features
|
|
51
52
|
- **Raise Exceptions**: `raises()`, `raises_all()`, `reraise()` — batch raising and exception conversion
|
|
@@ -96,7 +97,7 @@ assert err.traceback # full formatted traceback string
|
|
|
96
97
|
| `exception` | `Exception \| None` | The original exception instance |
|
|
97
98
|
| `traceback` | `str \| None` | Formatted traceback string for debugging |
|
|
98
99
|
|
|
99
|
-
##
|
|
100
|
+
## Sorry, but there was more code examples!
|
|
100
101
|
|
|
101
102
|
```python
|
|
102
103
|
# ── ignore as a decorator ──
|
|
@@ -8,6 +8,7 @@ A lightweight Python exception handling utility library.
|
|
|
8
8
|

|
|
9
9
|

|
|
10
10
|

|
|
11
|
+

|
|
11
12
|
|
|
12
13
|
## Features
|
|
13
14
|
- **Raise Exceptions**: `raises()`, `raises_all()`, `reraise()` — batch raising and exception conversion
|
|
@@ -58,7 +59,7 @@ assert err.traceback # full formatted traceback string
|
|
|
58
59
|
| `exception` | `Exception \| None` | The original exception instance |
|
|
59
60
|
| `traceback` | `str \| None` | Formatted traceback string for debugging |
|
|
60
61
|
|
|
61
|
-
##
|
|
62
|
+
## Sorry, but there was more code examples!
|
|
62
63
|
|
|
63
64
|
```python
|
|
64
65
|
# ── ignore as a decorator ──
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#define PY_SSIZE_T_CLEAN
|
|
2
|
+
#include <Python.h>
|
|
3
|
+
|
|
4
|
+
/* Fast exception type checking
|
|
5
|
+
*
|
|
6
|
+
* Optimized check for exception type hierarchy using PyObject_IsSubclass.
|
|
7
|
+
* Returns False immediately if typ is None, otherwise checks if typ is a
|
|
8
|
+
* subclass of excs.
|
|
9
|
+
*
|
|
10
|
+
* Args:
|
|
11
|
+
* typ: The type object to check (or None)
|
|
12
|
+
* excs: The exception class(es) to check against
|
|
13
|
+
*
|
|
14
|
+
* Returns:
|
|
15
|
+
* True if typ is a subclass of excs, False otherwise
|
|
16
|
+
* NULL on error with exception set
|
|
17
|
+
*/
|
|
18
|
+
static PyObject* fast_issubclass_check(PyObject* self, PyObject* const* args, Py_ssize_t nargs) {
|
|
19
|
+
if (nargs != 2) {
|
|
20
|
+
PyErr_Format(PyExc_TypeError,
|
|
21
|
+
"fast_issubclass_check() takes exactly 2 arguments (%zd given)",
|
|
22
|
+
nargs);
|
|
23
|
+
return NULL;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
PyObject *typ = args[0];
|
|
27
|
+
PyObject *excs = args[1];
|
|
28
|
+
|
|
29
|
+
/* Handle None case explicitly */
|
|
30
|
+
if (typ == Py_None) {
|
|
31
|
+
Py_RETURN_FALSE;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Validate that excs is a class or tuple of classes */
|
|
35
|
+
if (!PyType_Check(excs) && !PyTuple_Check(excs)) {
|
|
36
|
+
PyErr_SetString(PyExc_TypeError,
|
|
37
|
+
"second argument must be a class or tuple of classes");
|
|
38
|
+
return NULL;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
int result = PyObject_IsSubclass(typ, excs);
|
|
42
|
+
if (result == -1) {
|
|
43
|
+
return NULL; /* Exception already set by PyObject_IsSubclass */
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Return bool directly instead of going through PyBool_FromLong */
|
|
47
|
+
if (result == 1) {
|
|
48
|
+
Py_RETURN_TRUE;
|
|
49
|
+
} else {
|
|
50
|
+
Py_RETURN_FALSE;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Fast exception collector append
|
|
55
|
+
*
|
|
56
|
+
* Optimized append operation for adding exceptions to a list.
|
|
57
|
+
*
|
|
58
|
+
* Args:
|
|
59
|
+
* list: The list object to append to
|
|
60
|
+
* exc: The exception object to append
|
|
61
|
+
*
|
|
62
|
+
* Returns:
|
|
63
|
+
* None on success
|
|
64
|
+
* NULL on error with exception set
|
|
65
|
+
*/
|
|
66
|
+
static PyObject* fast_append_exception(PyObject* self, PyObject* const* args, Py_ssize_t nargs) {
|
|
67
|
+
if (nargs != 2) {
|
|
68
|
+
PyErr_Format(PyExc_TypeError,
|
|
69
|
+
"fast_append_exception() takes exactly 2 arguments (%zd given)",
|
|
70
|
+
nargs);
|
|
71
|
+
return NULL;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
PyObject *list = args[0];
|
|
75
|
+
PyObject *exc = args[1];
|
|
76
|
+
|
|
77
|
+
/* Validate that first argument is actually a list */
|
|
78
|
+
if (!PyList_Check(list)) {
|
|
79
|
+
PyErr_SetString(PyExc_TypeError, "first argument must be a list");
|
|
80
|
+
return NULL;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (PyList_Append(list, exc) == -1) {
|
|
84
|
+
return NULL; /* Exception already set by PyList_Append */
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
Py_RETURN_NONE;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Method definitions */
|
|
91
|
+
static PyMethodDef SpeedupMethods[] = {
|
|
92
|
+
{
|
|
93
|
+
"fast_issubclass_check",
|
|
94
|
+
(PyCFunction)fast_issubclass_check,
|
|
95
|
+
METH_FASTCALL,
|
|
96
|
+
"fast_issubclass_check(typ, excs) -> bool\n\n"
|
|
97
|
+
"Check if typ is a subclass of excs exception type(s).\n"
|
|
98
|
+
"Returns False if typ is None, otherwise uses PyObject_IsSubclass.\n"
|
|
99
|
+
"Optimized for exception handling performance."
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"fast_append_exception",
|
|
103
|
+
(PyCFunction)fast_append_exception,
|
|
104
|
+
METH_FASTCALL,
|
|
105
|
+
"fast_append_exception(list, exc) -> None\n\n"
|
|
106
|
+
"Append an exception to a list with minimal overhead.\n"
|
|
107
|
+
"Validates that the first argument is a list."
|
|
108
|
+
},
|
|
109
|
+
{NULL, NULL, 0, NULL} /* Sentinel */
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/* Module definition */
|
|
113
|
+
static struct PyModuleDef speedupmodule = {
|
|
114
|
+
PyModuleDef_HEAD_INIT,
|
|
115
|
+
"_speedup", /* name */
|
|
116
|
+
"C speedup module for errortools\n\n"
|
|
117
|
+
"Provides optimized implementations of exception handling operations:\n"
|
|
118
|
+
" - fast_issubclass_check: Quick exception type hierarchy checking\n"
|
|
119
|
+
" - fast_append_exception: Efficient exception list append operations",
|
|
120
|
+
-1, /* size */
|
|
121
|
+
SpeedupMethods /* methods */
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/* Module initialization */
|
|
125
|
+
PyMODINIT_FUNC PyInit__speedup(void) {
|
|
126
|
+
return PyModule_Create(&speedupmodule);
|
|
127
|
+
}
|
|
@@ -107,11 +107,19 @@ class fast_ignore:
|
|
|
107
107
|
>>> with fast_ignore(KeyError):
|
|
108
108
|
... d = {}
|
|
109
109
|
... _ = d["missing"]
|
|
110
|
+
|
|
111
|
+
.. deprecated:: 3.0.0
|
|
112
|
+
This class is deprecated as it is functionally redundant.
|
|
110
113
|
"""
|
|
111
114
|
|
|
112
115
|
__slots__ = ("_excs",)
|
|
113
116
|
|
|
114
117
|
def __init__(self, *excs: ExceptionType) -> None:
|
|
118
|
+
warnings.warn(
|
|
119
|
+
"fast_ignore is deprecated as it is functionally redundant.",
|
|
120
|
+
DeprecationWarning,
|
|
121
|
+
stacklevel=2,
|
|
122
|
+
)
|
|
115
123
|
for exc in excs:
|
|
116
124
|
if not isinstance(exc, type) or not issubclass(exc, BaseException):
|
|
117
125
|
raise TypeError(f"Expected Exception subclass, got {exc!r}")
|
|
@@ -63,16 +63,28 @@ AnyErrorCode: TypeAlias = Union[
|
|
|
63
63
|
"""Union of all predefined error-code subclasses."""
|
|
64
64
|
|
|
65
65
|
InputError: TypeAlias = InvalidInputError
|
|
66
|
-
"""Alias for `InvalidInputError` (1001).
|
|
66
|
+
"""Alias for `InvalidInputError` (1001).
|
|
67
|
+
|
|
68
|
+
.. deprecated:: 3.0.0
|
|
69
|
+
This type alias is deprecated as it is redundant."""
|
|
67
70
|
|
|
68
71
|
AccessError: TypeAlias = AccessDeniedError
|
|
69
|
-
"""Alias for `AccessDeniedError` (2001).
|
|
72
|
+
"""Alias for `AccessDeniedError` (2001).
|
|
73
|
+
|
|
74
|
+
.. deprecated:: 3.0.0
|
|
75
|
+
This type alias is deprecated as it is redundant."""
|
|
70
76
|
|
|
71
77
|
LookupError_: TypeAlias = NotFoundError
|
|
72
|
-
"""Alias for `NotFoundError` (3001). Trailing underscore avoids shadowing builtins.
|
|
78
|
+
"""Alias for `NotFoundError` (3001). Trailing underscore avoids shadowing builtins.
|
|
79
|
+
|
|
80
|
+
.. deprecated:: 3.0.0
|
|
81
|
+
This type alias is deprecated as it is redundant."""
|
|
73
82
|
|
|
74
83
|
RuntimeError_: TypeAlias = Union[RuntimeFailure, TimeoutFailure]
|
|
75
|
-
"""Union of runtime-related errors: `RuntimeFailure` (4001) and `TimeoutFailure` (4002).
|
|
84
|
+
"""Union of runtime-related errors: `RuntimeFailure` (4001) and `TimeoutFailure` (4002).
|
|
85
|
+
|
|
86
|
+
.. deprecated:: 3.0.0
|
|
87
|
+
This type alias is deprecated as it is redundant."""
|
|
76
88
|
|
|
77
89
|
# ---------------------------------------------------------------------------
|
|
78
90
|
# More type aliases
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: errortools
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: errortools - a toolset for working with Python exceptions and warnings and logging.
|
|
5
5
|
Home-page: https://github.com/more-abc/errortools
|
|
6
6
|
Author: Evan Yang
|
|
@@ -46,6 +46,7 @@ A lightweight Python exception handling utility library.
|
|
|
46
46
|

|
|
47
47
|

|
|
48
48
|

|
|
49
|
+

|
|
49
50
|
|
|
50
51
|
## Features
|
|
51
52
|
- **Raise Exceptions**: `raises()`, `raises_all()`, `reraise()` — batch raising and exception conversion
|
|
@@ -96,7 +97,7 @@ assert err.traceback # full formatted traceback string
|
|
|
96
97
|
| `exception` | `Exception \| None` | The original exception instance |
|
|
97
98
|
| `traceback` | `str \| None` | Formatted traceback string for debugging |
|
|
98
99
|
|
|
99
|
-
##
|
|
100
|
+
## Sorry, but there was more code examples!
|
|
100
101
|
|
|
101
102
|
```python
|
|
102
103
|
# ── ignore as a decorator ──
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
AUTHORS.txt
|
|
2
|
+
LICENSE.txt
|
|
3
|
+
README.md
|
|
4
|
+
setup.py
|
|
5
|
+
_errortools/__init__.py
|
|
6
|
+
_errortools/_cli.py
|
|
7
|
+
_errortools/_speedup.c
|
|
8
|
+
_errortools/cli.py
|
|
9
|
+
_errortools/const.py
|
|
10
|
+
_errortools/errno.py
|
|
11
|
+
_errortools/future.py
|
|
12
|
+
_errortools/ignore.py
|
|
13
|
+
_errortools/metadata.py
|
|
14
|
+
_errortools/partial.py
|
|
15
|
+
_errortools/py.typed
|
|
16
|
+
_errortools/raises.py
|
|
17
|
+
_errortools/typing.py
|
|
18
|
+
_errortools/version.py
|
|
19
|
+
errortools/__init__.py
|
|
20
|
+
errortools/__main__.py
|
|
21
|
+
errortools/future.py
|
|
22
|
+
errortools/logging.py
|
|
23
|
+
errortools/partial.py
|
|
24
|
+
errortools.egg-info/PKG-INFO
|
|
25
|
+
errortools.egg-info/SOURCES.txt
|
|
26
|
+
errortools.egg-info/dependency_links.txt
|
|
27
|
+
errortools.egg-info/entry_points.txt
|
|
28
|
+
errortools.egg-info/requires.txt
|
|
29
|
+
errortools.egg-info/top_level.txt
|
|
30
|
+
testing/__init__.py
|
|
31
|
+
testing/__main__.py
|
|
32
|
+
testing/conftest.py
|
|
33
|
+
testing/run_tests.py
|
|
34
|
+
testing/test_abc.py
|
|
35
|
+
testing/test_const.py
|
|
36
|
+
testing/test_decorator.py
|
|
37
|
+
testing/test_descriptor.py
|
|
38
|
+
testing/test_errno.py
|
|
39
|
+
testing/test_errorcodes.py
|
|
40
|
+
testing/test_future.py
|
|
41
|
+
testing/test_groups.py
|
|
42
|
+
testing/test_ignore.py
|
|
43
|
+
testing/test_logging.py
|
|
44
|
+
testing/test_partials.py
|
|
45
|
+
testing/test_raises.py
|
|
46
|
+
testing/test_typing.py
|
|
47
|
+
testing/test_warnings.py
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
|
|
3
|
-
from setuptools import setup,
|
|
3
|
+
from setuptools import setup, Extension
|
|
4
4
|
|
|
5
|
-
_VERSION: str = "3.
|
|
5
|
+
_VERSION: str = "3.1.0"
|
|
6
6
|
_CLI_INFO: dict[str, list[str]] = {
|
|
7
7
|
"console_scripts": [
|
|
8
|
-
"python -m errortools = _errortools.cli:main",
|
|
8
|
+
# "python -m errortools = _errortools.cli:main",
|
|
9
9
|
"logger = _errortools.cli:main",
|
|
10
10
|
]
|
|
11
11
|
}
|
|
@@ -48,7 +48,7 @@ setup(
|
|
|
48
48
|
"Operating System :: OS Independent",
|
|
49
49
|
"Typing :: Typed",
|
|
50
50
|
],
|
|
51
|
-
packages=
|
|
51
|
+
packages=["_errortools", "errortools", "testing"],
|
|
52
52
|
package_data={"errortools": ["py.typed"]},
|
|
53
53
|
include_package_data=True,
|
|
54
54
|
python_requires=">=3.8",
|
|
@@ -17,9 +17,6 @@ import configparser
|
|
|
17
17
|
# Import the ABC classes to test
|
|
18
18
|
from _errortools.classes.abc import ErrorCodeable, Warnable, Raiseable, Error
|
|
19
19
|
|
|
20
|
-
# NOTE: Tests for `ErrorAttrable` was in `test_mixin.py`.
|
|
21
|
-
|
|
22
|
-
|
|
23
20
|
# =============================================================================
|
|
24
21
|
# ErrorCodeable ABC Tests
|
|
25
22
|
# =============================================================================
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""Tests for _errortools/classes/group.py — GroupErrors and BaseGroup."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from _errortools.classes.group import GroupErrors, BaseGroup
|
|
8
|
+
|
|
9
|
+
# =============================================================================
|
|
10
|
+
# GroupErrors — collect / raise_group / clear
|
|
11
|
+
# =============================================================================
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestGroupErrors:
|
|
15
|
+
def test_starts_empty(self):
|
|
16
|
+
g = GroupErrors()
|
|
17
|
+
assert len(g) == 0
|
|
18
|
+
assert not g
|
|
19
|
+
|
|
20
|
+
def test_collect_adds_exception(self):
|
|
21
|
+
g = GroupErrors()
|
|
22
|
+
g.collect(ValueError("v"))
|
|
23
|
+
assert len(g) == 1
|
|
24
|
+
|
|
25
|
+
def test_collect_multiple(self):
|
|
26
|
+
g = GroupErrors()
|
|
27
|
+
g.collect(ValueError("v"))
|
|
28
|
+
g.collect(TypeError("t"))
|
|
29
|
+
g.collect(KeyError("k"))
|
|
30
|
+
assert len(g) == 3
|
|
31
|
+
|
|
32
|
+
def test_bool_true_when_not_empty(self):
|
|
33
|
+
g = GroupErrors()
|
|
34
|
+
g.collect(RuntimeError("r"))
|
|
35
|
+
assert bool(g) is True
|
|
36
|
+
|
|
37
|
+
def test_bool_false_when_empty(self):
|
|
38
|
+
assert bool(GroupErrors()) is False
|
|
39
|
+
|
|
40
|
+
def test_errors_returns_copy(self):
|
|
41
|
+
g = GroupErrors()
|
|
42
|
+
e = ValueError("v")
|
|
43
|
+
g.collect(e)
|
|
44
|
+
snapshot = g.errors
|
|
45
|
+
snapshot.clear() # mutating the copy must not affect the group
|
|
46
|
+
assert len(g) == 1
|
|
47
|
+
|
|
48
|
+
def test_raise_group_raises_exception_group(self):
|
|
49
|
+
g = GroupErrors()
|
|
50
|
+
g.collect(ValueError("v"))
|
|
51
|
+
g.collect(TypeError("t"))
|
|
52
|
+
with pytest.raises(ExceptionGroup) as exc_info:
|
|
53
|
+
g.raise_group()
|
|
54
|
+
assert len(exc_info.value.exceptions) == 2
|
|
55
|
+
|
|
56
|
+
def test_raise_group_uses_group_msg(self):
|
|
57
|
+
g = GroupErrors("my errors")
|
|
58
|
+
g.collect(ValueError("v"))
|
|
59
|
+
with pytest.raises(ExceptionGroup) as exc_info:
|
|
60
|
+
g.raise_group()
|
|
61
|
+
assert exc_info.value.message == "my errors"
|
|
62
|
+
|
|
63
|
+
def test_raise_group_default_msg(self):
|
|
64
|
+
g = GroupErrors()
|
|
65
|
+
g.collect(ValueError("v"))
|
|
66
|
+
with pytest.raises(ExceptionGroup) as exc_info:
|
|
67
|
+
g.raise_group()
|
|
68
|
+
assert exc_info.value.message == "multiple errors"
|
|
69
|
+
|
|
70
|
+
def test_raise_group_does_nothing_when_empty(self):
|
|
71
|
+
g = GroupErrors()
|
|
72
|
+
g.raise_group() # should not raise
|
|
73
|
+
|
|
74
|
+
def test_clear_removes_all_exceptions(self):
|
|
75
|
+
g = GroupErrors()
|
|
76
|
+
g.collect(ValueError("v"))
|
|
77
|
+
g.collect(TypeError("t"))
|
|
78
|
+
g.clear()
|
|
79
|
+
assert len(g) == 0
|
|
80
|
+
|
|
81
|
+
def test_clear_then_raise_group_noop(self):
|
|
82
|
+
g = GroupErrors()
|
|
83
|
+
g.collect(ValueError("v"))
|
|
84
|
+
g.clear()
|
|
85
|
+
g.raise_group() # no raise — nothing collected
|
|
86
|
+
|
|
87
|
+
def test_repr_contains_msg_and_count(self):
|
|
88
|
+
g = GroupErrors("test group")
|
|
89
|
+
g.collect(ValueError("v"))
|
|
90
|
+
r = repr(g)
|
|
91
|
+
assert "GroupErrors" in r
|
|
92
|
+
assert "test group" in r
|
|
93
|
+
|
|
94
|
+
def test_sub_exception_types_preserved(self):
|
|
95
|
+
g = GroupErrors()
|
|
96
|
+
v = ValueError("val")
|
|
97
|
+
t = TypeError("type")
|
|
98
|
+
g.collect(v)
|
|
99
|
+
g.collect(t)
|
|
100
|
+
with pytest.raises(ExceptionGroup) as exc_info:
|
|
101
|
+
g.raise_group()
|
|
102
|
+
exc_types = {type(e) for e in exc_info.value.exceptions}
|
|
103
|
+
assert exc_types == {ValueError, TypeError}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
if sys.version_info <= (3, 10):
|
|
107
|
+
del TestGroupErrors
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# =============================================================================
|
|
111
|
+
# BaseGroup — abstract interface
|
|
112
|
+
# =============================================================================
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class TestBaseGroupAbstract:
|
|
116
|
+
def test_base_group_has_abstract_methods(self):
|
|
117
|
+
abstract = BaseGroup.__abstractmethods__
|
|
118
|
+
assert "errors" in abstract
|
|
119
|
+
assert "collect" in abstract
|
|
120
|
+
assert "clear" in abstract
|
|
121
|
+
assert "raise_group" in abstract
|
|
122
|
+
|
|
123
|
+
def test_concrete_subclass_is_valid(self):
|
|
124
|
+
g = GroupErrors()
|
|
125
|
+
assert isinstance(g, BaseGroup)
|
|
126
|
+
|
|
127
|
+
def test_group_errors_satisfies_abstract_interface(self):
|
|
128
|
+
abstract = BaseGroup.__abstractmethods__
|
|
129
|
+
for method in abstract:
|
|
130
|
+
assert hasattr(GroupErrors, method), f"GroupErrors missing: {method}"
|
errortools-3.0.0/AUTHORS.txt
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#define PY_SSIZE_T_CLEAN
|
|
2
|
-
#include <Python.h>
|
|
3
|
-
|
|
4
|
-
/* Fast exception type checking */
|
|
5
|
-
static PyObject* fast_issubclass_check(PyObject* self, PyObject* args) {
|
|
6
|
-
PyObject *typ, *excs;
|
|
7
|
-
if (!PyArg_ParseTuple(args, "OO", &typ, &excs)) {
|
|
8
|
-
return NULL;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
if (typ == Py_None) {
|
|
12
|
-
Py_RETURN_FALSE;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
int result = PyObject_IsSubclass(typ, excs);
|
|
16
|
-
if (result == -1) {
|
|
17
|
-
return NULL;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return PyBool_FromLong(result);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/* Fast exception collector append */
|
|
24
|
-
static PyObject* fast_append_exception(PyObject* self, PyObject* args) {
|
|
25
|
-
PyObject *list, *exc;
|
|
26
|
-
if (!PyArg_ParseTuple(args, "OO", &list, &exc)) {
|
|
27
|
-
return NULL;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (PyList_Append(list, exc) == -1) {
|
|
31
|
-
return NULL;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
Py_RETURN_NONE;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/* Method definitions */
|
|
38
|
-
static PyMethodDef SpeedupMethods[] = {
|
|
39
|
-
{"fast_issubclass_check", fast_issubclass_check, METH_VARARGS,
|
|
40
|
-
"Fast exception type checking"},
|
|
41
|
-
{"fast_append_exception", fast_append_exception, METH_VARARGS,
|
|
42
|
-
"Fast exception list append"},
|
|
43
|
-
{NULL, NULL, 0, NULL}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/* Module definition */
|
|
47
|
-
static struct PyModuleDef speedupmodule = {
|
|
48
|
-
PyModuleDef_HEAD_INIT,
|
|
49
|
-
"_speedup",
|
|
50
|
-
"C speedup for errortools",
|
|
51
|
-
-1,
|
|
52
|
-
SpeedupMethods
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
/* Module initialization */
|
|
56
|
-
PyMODINIT_FUNC PyInit__speedup(void) {
|
|
57
|
-
return PyModule_Create(&speedupmodule);
|
|
58
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""Base classes."""
|