errortools 2.5.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-2.5.0/errortools.egg-info → errortools-3.1.0}/PKG-INFO +6 -4
- {errortools-2.5.0 → errortools-3.1.0}/README.md +2 -2
- errortools-3.1.0/_errortools/_speedup.c +127 -0
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/cli.py +1 -1
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/future.py +24 -10
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/ignore.py +8 -0
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/raises.py +42 -39
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/typing.py +23 -5
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/version.py +2 -2
- {errortools-2.5.0 → errortools-3.1.0}/errortools/__init__.py +0 -12
- {errortools-2.5.0 → errortools-3.1.0/errortools.egg-info}/PKG-INFO +6 -4
- errortools-3.1.0/errortools.egg-info/SOURCES.txt +47 -0
- {errortools-2.5.0 → errortools-3.1.0}/errortools.egg-info/entry_points.txt +0 -1
- {errortools-2.5.0 → errortools-3.1.0}/errortools.egg-info/top_level.txt +1 -1
- errortools-3.1.0/setup.py +58 -0
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/__init__.py +1 -2
- errortools-3.1.0/testing/__main__.py +4 -0
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_abc.py +0 -7
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_const.py +0 -5
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_decorator.py +0 -5
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_descriptor.py +0 -5
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_errno.py +0 -5
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_errorcodes.py +0 -5
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_future.py +0 -6
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_groups.py +6 -5
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_ignore.py +0 -5
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_logging.py +0 -5
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_partials.py +0 -5
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_raises.py +36 -37
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_typing.py +0 -5
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/test_warnings.py +0 -5
- errortools-2.5.0/AUTHORS.txt +0 -3
- errortools-2.5.0/_errortools/classes/__init__.py +0 -1
- errortools-2.5.0/_errortools/classes/abc.py +0 -359
- errortools-2.5.0/_errortools/classes/errorcodes.py +0 -273
- errortools-2.5.0/_errortools/classes/group.py +0 -118
- errortools-2.5.0/_errortools/classes/warn.py +0 -124
- errortools-2.5.0/_errortools/decorator/__init__.py +0 -1
- errortools-2.5.0/_errortools/decorator/cache.py +0 -82
- errortools-2.5.0/_errortools/decorator/deprecated.py +0 -61
- errortools-2.5.0/_errortools/descriptor/__init__.py +0 -2
- errortools-2.5.0/_errortools/descriptor/errormsg.py +0 -37
- errortools-2.5.0/_errortools/descriptor/nonblankmsg.py +0 -52
- errortools-2.5.0/_errortools/logging/__init__.py +0 -43
- errortools-2.5.0/_errortools/logging/base.py +0 -467
- errortools-2.5.0/_errortools/logging/level.py +0 -85
- errortools-2.5.0/_errortools/logging/logger.py +0 -13
- errortools-2.5.0/_errortools/logging/record.py +0 -109
- errortools-2.5.0/_errortools/logging/sink.py +0 -236
- errortools-2.5.0/_errortools/methods/__init__.py +0 -11
- errortools-2.5.0/_errortools/methods/errorattr.py +0 -37
- errortools-2.5.0/_errortools/methods/errordelattr.py +0 -35
- errortools-2.5.0/_errortools/methods/errorhasattr.py +0 -27
- errortools-2.5.0/_errortools/methods/errorsetattr.py +0 -40
- errortools-2.5.0/_errortools/wrappers/__init__.py +0 -2
- errortools-2.5.0/_errortools/wrappers/cache.py +0 -95
- errortools-2.5.0/_errortools/wrappers/ignore.py +0 -115
- errortools-2.5.0/errortools.egg-info/SOURCES.txt +0 -71
- errortools-2.5.0/setup.py +0 -79
- errortools-2.5.0/tests/test_mixins.py +0 -256
- {errortools-2.5.0 → errortools-3.1.0}/LICENSE.txt +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/__init__.py +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/_cli.py +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/const.py +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/errno.py +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/metadata.py +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/partial.py +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/_errortools/py.typed +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/errortools/__main__.py +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/errortools/future.py +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/errortools/logging.py +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/errortools/partial.py +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/errortools.egg-info/dependency_links.txt +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/errortools.egg-info/requires.txt +0 -0
- {errortools-2.5.0 → errortools-3.1.0}/setup.cfg +0 -0
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/conftest.py +0 -0
- {errortools-2.5.0/tests → errortools-3.1.0/testing}/run_tests.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
|
+
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
|
|
@@ -8,6 +8,8 @@ Author-email: quantbit@126.com
|
|
|
8
8
|
License: MIT
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -16,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
16
18
|
Classifier: Programming Language :: Python :: 3.15
|
|
17
19
|
Classifier: Operating System :: OS Independent
|
|
18
20
|
Classifier: Typing :: Typed
|
|
19
|
-
Requires-Python: >=3.
|
|
21
|
+
Requires-Python: >=3.8
|
|
20
22
|
Description-Content-Type: text/markdown
|
|
21
23
|
License-File: LICENSE.txt
|
|
22
24
|
License-File: AUTHORS.txt
|
|
@@ -44,6 +46,7 @@ A lightweight Python exception handling utility library.
|
|
|
44
46
|

|
|
45
47
|

|
|
46
48
|

|
|
49
|
+

|
|
47
50
|
|
|
48
51
|
## Features
|
|
49
52
|
- **Raise Exceptions**: `raises()`, `raises_all()`, `reraise()` — batch raising and exception conversion
|
|
@@ -51,7 +54,6 @@ A lightweight Python exception handling utility library.
|
|
|
51
54
|
- **Future Utilities**: `super_fast_catch()`, `super_fast_reraise()`, `ExceptionCollector` — lightweight exception handling for high-performance scenarios
|
|
52
55
|
- **Exception Caching**: `error_cache` — cache exceptions raised by functions (similar to `lru_cache`)
|
|
53
56
|
- **Custom Exceptions**: `PureBaseException`, `ContextException`, `BaseErrorCodes`, `BaseWarning` — structured exception classes with error codes, trace IDs, and context
|
|
54
|
-
- **Attribute Error Mixin**: Customize error behavior for attribute access, assignment, and deletion
|
|
55
57
|
- **Type Aliases**: `ExceptionType`, `AnyErrorCode`, `BaseErrorCodesType`, and more
|
|
56
58
|
- **Logging**: `logger` — loguru-inspired structured logger with leveled output, multiple sinks, context binding, and exception capture
|
|
57
59
|
|
|
@@ -95,7 +97,7 @@ assert err.traceback # full formatted traceback string
|
|
|
95
97
|
| `exception` | `Exception \| None` | The original exception instance |
|
|
96
98
|
| `traceback` | `str \| None` | Formatted traceback string for debugging |
|
|
97
99
|
|
|
98
|
-
##
|
|
100
|
+
## Sorry, but there was more code examples!
|
|
99
101
|
|
|
100
102
|
```python
|
|
101
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
|
|
@@ -15,7 +16,6 @@ A lightweight Python exception handling utility library.
|
|
|
15
16
|
- **Future Utilities**: `super_fast_catch()`, `super_fast_reraise()`, `ExceptionCollector` — lightweight exception handling for high-performance scenarios
|
|
16
17
|
- **Exception Caching**: `error_cache` — cache exceptions raised by functions (similar to `lru_cache`)
|
|
17
18
|
- **Custom Exceptions**: `PureBaseException`, `ContextException`, `BaseErrorCodes`, `BaseWarning` — structured exception classes with error codes, trace IDs, and context
|
|
18
|
-
- **Attribute Error Mixin**: Customize error behavior for attribute access, assignment, and deletion
|
|
19
19
|
- **Type Aliases**: `ExceptionType`, `AnyErrorCode`, `BaseErrorCodesType`, and more
|
|
20
20
|
- **Logging**: `logger` — loguru-inspired structured logger with leveled output, multiple sinks, context binding, and exception capture
|
|
21
21
|
|
|
@@ -59,7 +59,7 @@ assert err.traceback # full formatted traceback string
|
|
|
59
59
|
| `exception` | `Exception \| None` | The original exception instance |
|
|
60
60
|
| `traceback` | `str \| None` | Formatted traceback string for debugging |
|
|
61
61
|
|
|
62
|
-
##
|
|
62
|
+
## Sorry, but there was more code examples!
|
|
63
63
|
|
|
64
64
|
```python
|
|
65
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
|
+
}
|
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
"""Future-focused lightweight exception handling utilities."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
if sys.version_info <= (3, 10):
|
|
7
|
+
from typing_extensions import TypeAlias
|
|
8
|
+
else:
|
|
9
|
+
from typing import TypeAlias
|
|
10
|
+
from typing import cast, Literal
|
|
11
|
+
|
|
12
|
+
# Try to import C speedup
|
|
13
|
+
try:
|
|
14
|
+
from _errortools._speedup import fast_issubclass_check, fast_append_exception # type: ignore[import-not-found]
|
|
15
|
+
except ImportError:
|
|
16
|
+
|
|
17
|
+
def fast_issubclass_check(typ, excs) -> bool:
|
|
18
|
+
return typ is not None and issubclass(typ, excs)
|
|
19
|
+
|
|
20
|
+
def fast_append_exception(lst, exc) -> None:
|
|
21
|
+
lst.append(exc)
|
|
4
22
|
|
|
5
|
-
from typing import TypeAlias, cast, Literal
|
|
6
23
|
|
|
7
24
|
__all__ = [
|
|
8
25
|
"super_fast_ignore",
|
|
@@ -26,10 +43,7 @@ class super_fast_ignore:
|
|
|
26
43
|
return
|
|
27
44
|
|
|
28
45
|
def __exit__(self, typ: _ExcType | None, *_) -> bool:
|
|
29
|
-
|
|
30
|
-
return False
|
|
31
|
-
excs = self.excs
|
|
32
|
-
return issubclass(typ, excs)
|
|
46
|
+
return cast(bool, fast_issubclass_check(typ, self.excs))
|
|
33
47
|
|
|
34
48
|
|
|
35
49
|
class super_fast_catch:
|
|
@@ -50,11 +64,11 @@ class super_fast_catch:
|
|
|
50
64
|
self.excs = excs if excs else (BaseException,)
|
|
51
65
|
self.exception: BaseException | None = None
|
|
52
66
|
|
|
53
|
-
def __enter__(self) ->
|
|
67
|
+
def __enter__(self) -> super_fast_catch:
|
|
54
68
|
return self
|
|
55
69
|
|
|
56
70
|
def __exit__(self, typ: _ExcType | None, val, *_) -> bool:
|
|
57
|
-
if
|
|
71
|
+
if not fast_issubclass_check(typ, self.excs):
|
|
58
72
|
return False
|
|
59
73
|
self.exception = val
|
|
60
74
|
return True
|
|
@@ -117,7 +131,7 @@ class ExceptionCollector:
|
|
|
117
131
|
|
|
118
132
|
def __exit__(self, exc_typ, exc_val, *_) -> bool:
|
|
119
133
|
if exc_typ is not None:
|
|
120
|
-
self._exceptions
|
|
134
|
+
fast_append_exception(self._exceptions, exc_val)
|
|
121
135
|
if self._stop_on_first:
|
|
122
136
|
return False
|
|
123
137
|
return True
|
|
@@ -129,14 +143,14 @@ class ExceptionCollector:
|
|
|
129
143
|
func(*args, **kwargs)
|
|
130
144
|
return False
|
|
131
145
|
except BaseException as exc:
|
|
132
|
-
self._exceptions
|
|
146
|
+
fast_append_exception(self._exceptions, exc)
|
|
133
147
|
if self._stop_on_first:
|
|
134
148
|
raise
|
|
135
149
|
return True
|
|
136
150
|
|
|
137
151
|
def add(self, exc: BaseException) -> None:
|
|
138
152
|
"""Manually add an exception."""
|
|
139
|
-
self._exceptions
|
|
153
|
+
fast_append_exception(self._exceptions, exc)
|
|
140
154
|
if self._stop_on_first:
|
|
141
155
|
raise exc
|
|
142
156
|
|
|
@@ -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}")
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Utilities for raising exceptions."""
|
|
2
2
|
|
|
3
|
+
import sys
|
|
3
4
|
from contextlib import contextmanager
|
|
4
5
|
from itertools import product
|
|
5
6
|
from typing import Callable, Any
|
|
@@ -107,45 +108,47 @@ def assert_raises(
|
|
|
107
108
|
)
|
|
108
109
|
|
|
109
110
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
111
|
+
if sys.version_info >= (3, 11):
|
|
112
|
+
|
|
113
|
+
def raises_all(
|
|
114
|
+
errors: Iterable[type[Exception]],
|
|
115
|
+
msgs: Iterable[str],
|
|
116
|
+
baseerror: type[Exception] = Exception,
|
|
117
|
+
group_msg: str = "multiple errors",
|
|
118
|
+
) -> None:
|
|
119
|
+
"""Validate exception types and raise all (error, message) combinations as an ExceptionGroup.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
errors: An iterable of exception types to include in the group.
|
|
123
|
+
msgs: An iterable of message strings to pair with each exception type.
|
|
124
|
+
baseerror: The base exception class that every type in *errors* must
|
|
125
|
+
inherit from. Defaults to `Exception`.
|
|
126
|
+
group_msg: The message attached to the `ExceptionGroup` itself.
|
|
127
|
+
Defaults to ``"multiple errors"``.
|
|
128
|
+
|
|
129
|
+
Raises:
|
|
130
|
+
TypeError: If any type in *errors* is not a subclass of *baseerror*.
|
|
131
|
+
ExceptionGroup: Containing one ``errors[i](msgs[j])`` instance for
|
|
132
|
+
every ``(i, j)`` pair in the Cartesian product.
|
|
133
|
+
|
|
134
|
+
Example:
|
|
135
|
+
>>> raises_all([ValueError, TypeError], ["bad input"])
|
|
136
|
+
Traceback (most recent call last):
|
|
137
|
+
...
|
|
138
|
+
ExceptionGroup: multiple errors (2 sub-exceptions)
|
|
139
|
+
"""
|
|
140
|
+
# NOTE: Computes the Cartesian product of *errors* x *msgs*, validates that every
|
|
141
|
+
# error type is a subclass of *baseerror*, then raises a single
|
|
142
|
+
# `ExceptionGroup` containing one instantiated exception per pair.
|
|
143
|
+
# If the product is empty (either iterable is empty) the function returns
|
|
144
|
+
# without raising.
|
|
145
|
+
pairs = _warp_list_product(errors, msgs)
|
|
146
|
+
if not pairs:
|
|
147
|
+
return
|
|
148
|
+
for error, _ in pairs:
|
|
149
|
+
if not _is_base_subclass(error=error, baseerror=baseerror):
|
|
150
|
+
raise TypeError(f"{error!r} is not a subclass of {baseerror.__name__}")
|
|
151
|
+
raise ExceptionGroup(group_msg, [error(msg) for error, msg in pairs])
|
|
149
152
|
|
|
150
153
|
|
|
151
154
|
@contextmanager
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"""Public type aliases for errortools exception classes."""
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
if sys.version_info <= (3, 10):
|
|
6
|
+
from typing_extensions import TypeAlias
|
|
7
|
+
else:
|
|
8
|
+
from typing import TypeAlias
|
|
9
|
+
from typing import Union
|
|
4
10
|
|
|
5
11
|
from .classes.errorcodes import (
|
|
6
12
|
PureBaseException,
|
|
@@ -57,16 +63,28 @@ AnyErrorCode: TypeAlias = Union[
|
|
|
57
63
|
"""Union of all predefined error-code subclasses."""
|
|
58
64
|
|
|
59
65
|
InputError: TypeAlias = InvalidInputError
|
|
60
|
-
"""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."""
|
|
61
70
|
|
|
62
71
|
AccessError: TypeAlias = AccessDeniedError
|
|
63
|
-
"""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."""
|
|
64
76
|
|
|
65
77
|
LookupError_: TypeAlias = NotFoundError
|
|
66
|
-
"""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."""
|
|
67
82
|
|
|
68
83
|
RuntimeError_: TypeAlias = Union[RuntimeFailure, TimeoutFailure]
|
|
69
|
-
"""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."""
|
|
70
88
|
|
|
71
89
|
# ---------------------------------------------------------------------------
|
|
72
90
|
# More type aliases
|
|
@@ -39,14 +39,7 @@ from _errortools.classes.warn import (
|
|
|
39
39
|
RuntimeBehaviourWarning,
|
|
40
40
|
ConfigurationWarning,
|
|
41
41
|
)
|
|
42
|
-
from _errortools.methods import (
|
|
43
|
-
ErrorSetAttrMixin,
|
|
44
|
-
ErrorAttrCheckMixin,
|
|
45
|
-
ErrorAttrDeletionMixin,
|
|
46
|
-
ErrorAttrMixin,
|
|
47
|
-
)
|
|
48
42
|
from _errortools.classes.abc import (
|
|
49
|
-
ErrorAttrable,
|
|
50
43
|
ErrorCodeable,
|
|
51
44
|
Warnable,
|
|
52
45
|
Raiseable,
|
|
@@ -130,11 +123,6 @@ __all__ = [
|
|
|
130
123
|
"ResourceUsageWarning",
|
|
131
124
|
"RuntimeBehaviourWarning",
|
|
132
125
|
"ConfigurationWarning",
|
|
133
|
-
"ErrorAttrMixin",
|
|
134
|
-
"ErrorAttrDeletionMixin",
|
|
135
|
-
"ErrorAttrCheckMixin",
|
|
136
|
-
"ErrorSetAttrMixin",
|
|
137
|
-
"ErrorAttrable",
|
|
138
126
|
"ErrorCodeable",
|
|
139
127
|
"Warnable",
|
|
140
128
|
"Raiseable",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: errortools
|
|
3
|
-
Version:
|
|
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
|
|
@@ -8,6 +8,8 @@ Author-email: quantbit@126.com
|
|
|
8
8
|
License: MIT
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -16,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
16
18
|
Classifier: Programming Language :: Python :: 3.15
|
|
17
19
|
Classifier: Operating System :: OS Independent
|
|
18
20
|
Classifier: Typing :: Typed
|
|
19
|
-
Requires-Python: >=3.
|
|
21
|
+
Requires-Python: >=3.8
|
|
20
22
|
Description-Content-Type: text/markdown
|
|
21
23
|
License-File: LICENSE.txt
|
|
22
24
|
License-File: AUTHORS.txt
|
|
@@ -44,6 +46,7 @@ A lightweight Python exception handling utility library.
|
|
|
44
46
|

|
|
45
47
|

|
|
46
48
|

|
|
49
|
+

|
|
47
50
|
|
|
48
51
|
## Features
|
|
49
52
|
- **Raise Exceptions**: `raises()`, `raises_all()`, `reraise()` — batch raising and exception conversion
|
|
@@ -51,7 +54,6 @@ A lightweight Python exception handling utility library.
|
|
|
51
54
|
- **Future Utilities**: `super_fast_catch()`, `super_fast_reraise()`, `ExceptionCollector` — lightweight exception handling for high-performance scenarios
|
|
52
55
|
- **Exception Caching**: `error_cache` — cache exceptions raised by functions (similar to `lru_cache`)
|
|
53
56
|
- **Custom Exceptions**: `PureBaseException`, `ContextException`, `BaseErrorCodes`, `BaseWarning` — structured exception classes with error codes, trace IDs, and context
|
|
54
|
-
- **Attribute Error Mixin**: Customize error behavior for attribute access, assignment, and deletion
|
|
55
57
|
- **Type Aliases**: `ExceptionType`, `AnyErrorCode`, `BaseErrorCodesType`, and more
|
|
56
58
|
- **Logging**: `logger` — loguru-inspired structured logger with leveled output, multiple sinks, context binding, and exception capture
|
|
57
59
|
|
|
@@ -95,7 +97,7 @@ assert err.traceback # full formatted traceback string
|
|
|
95
97
|
| `exception` | `Exception \| None` | The original exception instance |
|
|
96
98
|
| `traceback` | `str \| None` | Formatted traceback string for debugging |
|
|
97
99
|
|
|
98
|
-
##
|
|
100
|
+
## Sorry, but there was more code examples!
|
|
99
101
|
|
|
100
102
|
```python
|
|
101
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
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
from setuptools import setup, Extension
|
|
4
|
+
|
|
5
|
+
_VERSION: str = "3.1.0"
|
|
6
|
+
_CLI_INFO: dict[str, list[str]] = {
|
|
7
|
+
"console_scripts": [
|
|
8
|
+
# "python -m errortools = _errortools.cli:main",
|
|
9
|
+
"logger = _errortools.cli:main",
|
|
10
|
+
]
|
|
11
|
+
}
|
|
12
|
+
_DESCRIPTION: str = (
|
|
13
|
+
"errortools - a toolset for working with Python exceptions and warnings and logging."
|
|
14
|
+
)
|
|
15
|
+
_URL: str = "https://github.com/more-abc/errortools"
|
|
16
|
+
_AUTHOR: str = "Evan Yang"
|
|
17
|
+
_AUTHOR_EMAIL: str = "quantbit@126.com"
|
|
18
|
+
_LICENSE: str = "MIT"
|
|
19
|
+
|
|
20
|
+
# C extension for performance
|
|
21
|
+
_speedup_module = Extension(
|
|
22
|
+
"_errortools._speedup",
|
|
23
|
+
sources=["_errortools/_speedup.c"],
|
|
24
|
+
extra_compile_args=["/O2"] if sys.platform == "win32" else ["-O3", "-march=native"],
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
setup(
|
|
28
|
+
name="errortools",
|
|
29
|
+
version=_VERSION,
|
|
30
|
+
description=_DESCRIPTION,
|
|
31
|
+
long_description=open("README.md", encoding="utf-8").read(),
|
|
32
|
+
long_description_content_type="text/markdown",
|
|
33
|
+
url=_URL,
|
|
34
|
+
author=_AUTHOR,
|
|
35
|
+
author_email=_AUTHOR_EMAIL,
|
|
36
|
+
license=_LICENSE,
|
|
37
|
+
classifiers=[
|
|
38
|
+
"License :: OSI Approved :: MIT License",
|
|
39
|
+
"Programming Language :: Python :: 3",
|
|
40
|
+
"Programming Language :: Python :: 3.8",
|
|
41
|
+
"Programming Language :: Python :: 3.9",
|
|
42
|
+
"Programming Language :: Python :: 3.10",
|
|
43
|
+
"Programming Language :: Python :: 3.11",
|
|
44
|
+
"Programming Language :: Python :: 3.12",
|
|
45
|
+
"Programming Language :: Python :: 3.13",
|
|
46
|
+
"Programming Language :: Python :: 3.14",
|
|
47
|
+
"Programming Language :: Python :: 3.15",
|
|
48
|
+
"Operating System :: OS Independent",
|
|
49
|
+
"Typing :: Typed",
|
|
50
|
+
],
|
|
51
|
+
packages=["_errortools", "errortools", "testing"],
|
|
52
|
+
package_data={"errortools": ["py.typed"]},
|
|
53
|
+
include_package_data=True,
|
|
54
|
+
python_requires=">=3.8",
|
|
55
|
+
install_requires=["namebyauthor==1.0.0", "typing_extensions>=4.8.0"],
|
|
56
|
+
entry_points=_CLI_INFO,
|
|
57
|
+
ext_modules=[_speedup_module],
|
|
58
|
+
)
|