errortools 3.2.0__tar.gz → 3.4.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.2.0 → errortools-3.4.0}/AUTHORS.txt +2 -1
- {errortools-3.2.0/errortools.egg-info → errortools-3.4.0}/PKG-INFO +2 -1
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/_speedup.c +11 -11
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/classes/abc.py +1 -17
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/decorator/cache.py +1 -2
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/logging/logger.py +1 -1
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/partial.py +4 -10
- errortools-3.4.0/_errortools/plugins.py +134 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/version.py +17 -17
- {errortools-3.2.0 → errortools-3.4.0}/errortools/__init__.py +74 -4
- {errortools-3.2.0 → errortools-3.4.0/errortools.egg-info}/PKG-INFO +2 -1
- {errortools-3.2.0 → errortools-3.4.0}/errortools.egg-info/SOURCES.txt +3 -9
- {errortools-3.2.0 → errortools-3.4.0}/errortools.egg-info/top_level.txt +0 -5
- {errortools-3.2.0 → errortools-3.4.0}/pyproject.toml +4 -1
- {errortools-3.2.0 → errortools-3.4.0}/testing/__init__.py +4 -2
- errortools-3.4.0/testing/benchmark/__init__.py +4 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/test_groups.py +127 -130
- errortools-3.4.0/testing/test_plugins.py +200 -0
- errortools-3.4.0/testing/test_version.py +71 -0
- errortools-3.2.0/_errortools/const.py +0 -12
- errortools-3.2.0/docs/conf.py +0 -56
- errortools-3.2.0/testing/benchmark/__init__.py +0 -1
- errortools-3.2.0/testing/test_abc.py +0 -297
- errortools-3.2.0/testing/test_const.py +0 -28
- errortools-3.2.0/testing/test_errorcodes.py +0 -395
- errortools-3.2.0/testing/test_future.py +0 -296
- errortools-3.2.0/testing/test_logging.py +0 -673
- errortools-3.2.0/testing/test_partials.py +0 -228
- errortools-3.2.0/testing/test_warnings.py +0 -151
- {errortools-3.2.0 → errortools-3.4.0}/LICENSE.txt +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/README.md +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/__init__.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/__main__.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/_cli.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/classes/__init__.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/classes/errorcodes.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/classes/group.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/classes/warn.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/cli.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/decorator/__init__.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/decorator/deprecated.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/decorator/handlers.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/decorator/retry.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/decorator/timeout.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/descriptor/__init__.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/descriptor/base.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/descriptor/errormsg.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/descriptor/nonblankmsg.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/errno.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/future.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/ignore.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/logging/__init__.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/logging/base.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/logging/level.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/logging/record.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/logging/sink.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/metadata.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/py.typed +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/raises.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/typing.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/wrappers/__init__.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/wrappers/cache.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/_errortools/wrappers/ignore.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/errortools/__main__.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/errortools/future.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/errortools/logging.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/errortools/partial.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/errortools.egg-info/dependency_links.txt +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/errortools.egg-info/entry_points.txt +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/errortools.egg-info/requires.txt +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/setup.cfg +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/__main__.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/benchmark/test_future_perf.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/conftest.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/run_tests.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/test_decorator.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/test_descriptor.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/test_errno.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/test_ignore.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/test_raises.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/test_testing/__init__.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/test_testing/test_testing.py +0 -0
- {errortools-3.2.0 → errortools-3.4.0}/testing/test_typing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# (Lines starting with # are comments)
|
|
2
2
|
# Tips:
|
|
3
|
-
# Contributors are not sorted by initials,
|
|
3
|
+
# Contributors are not sorted by initials,
|
|
4
4
|
# but by contribution time.
|
|
5
5
|
# Here are the real contributors
|
|
6
6
|
aiwonderland
|
|
@@ -10,3 +10,4 @@ yangphysics
|
|
|
10
10
|
# And here are bot contributors
|
|
11
11
|
dependabot[bot]
|
|
12
12
|
AbaAbaAba-bot-like[bot]
|
|
13
|
+
pre-commit-ci[bot]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: errortools
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.0
|
|
4
4
|
Summary: errortools - a toolset for working with Python exceptions and warnings and logging.
|
|
5
5
|
Author-email: Evan Yang <quantbit@126.com>
|
|
6
6
|
License: Copyright (c) 2026 authors see AUTHORS.txt
|
|
@@ -25,6 +25,7 @@ License: Copyright (c) 2026 authors see AUTHORS.txt
|
|
|
25
25
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
26
26
|
|
|
27
27
|
Project-URL: Homepage, https://github.com/more-abc/errortools
|
|
28
|
+
Project-URL: Documentation, https://errortools.readthedocs.io/
|
|
28
29
|
Classifier: License :: OSI Approved :: MIT License
|
|
29
30
|
Classifier: Programming Language :: Python :: 3
|
|
30
31
|
Classifier: Programming Language :: Python :: 3.8
|
|
@@ -2,23 +2,23 @@
|
|
|
2
2
|
#include <Python.h>
|
|
3
3
|
|
|
4
4
|
/* Fast exception type checking
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* Optimized check for exception type hierarchy using PyObject_IsSubclass.
|
|
7
7
|
* Returns False immediately if typ is None, otherwise checks if typ is a
|
|
8
8
|
* subclass of excs.
|
|
9
|
-
*
|
|
9
|
+
*
|
|
10
10
|
* Args:
|
|
11
11
|
* typ: The type object to check (or None)
|
|
12
12
|
* excs: The exception class(es) to check against
|
|
13
|
-
*
|
|
13
|
+
*
|
|
14
14
|
* Returns:
|
|
15
15
|
* True if typ is a subclass of excs, False otherwise
|
|
16
16
|
* NULL on error with exception set
|
|
17
17
|
*/
|
|
18
18
|
static PyObject* fast_issubclass_check(PyObject* self, PyObject* const* args, Py_ssize_t nargs) {
|
|
19
19
|
if (nargs != 2) {
|
|
20
|
-
PyErr_Format(PyExc_TypeError,
|
|
21
|
-
"fast_issubclass_check() takes exactly 2 arguments (%zd given)",
|
|
20
|
+
PyErr_Format(PyExc_TypeError,
|
|
21
|
+
"fast_issubclass_check() takes exactly 2 arguments (%zd given)",
|
|
22
22
|
nargs);
|
|
23
23
|
return NULL;
|
|
24
24
|
}
|
|
@@ -33,7 +33,7 @@ static PyObject* fast_issubclass_check(PyObject* self, PyObject* const* args, Py
|
|
|
33
33
|
|
|
34
34
|
/* Validate that excs is a class or tuple of classes */
|
|
35
35
|
if (!PyType_Check(excs) && !PyTuple_Check(excs)) {
|
|
36
|
-
PyErr_SetString(PyExc_TypeError,
|
|
36
|
+
PyErr_SetString(PyExc_TypeError,
|
|
37
37
|
"second argument must be a class or tuple of classes");
|
|
38
38
|
return NULL;
|
|
39
39
|
}
|
|
@@ -52,21 +52,21 @@ static PyObject* fast_issubclass_check(PyObject* self, PyObject* const* args, Py
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/* Fast exception collector append
|
|
55
|
-
*
|
|
55
|
+
*
|
|
56
56
|
* Optimized append operation for adding exceptions to a list.
|
|
57
|
-
*
|
|
57
|
+
*
|
|
58
58
|
* Args:
|
|
59
59
|
* list: The list object to append to
|
|
60
60
|
* exc: The exception object to append
|
|
61
|
-
*
|
|
61
|
+
*
|
|
62
62
|
* Returns:
|
|
63
63
|
* None on success
|
|
64
64
|
* NULL on error with exception set
|
|
65
65
|
*/
|
|
66
66
|
static PyObject* fast_append_exception(PyObject* self, PyObject* const* args, Py_ssize_t nargs) {
|
|
67
67
|
if (nargs != 2) {
|
|
68
|
-
PyErr_Format(PyExc_TypeError,
|
|
69
|
-
"fast_append_exception() takes exactly 2 arguments (%zd given)",
|
|
68
|
+
PyErr_Format(PyExc_TypeError,
|
|
69
|
+
"fast_append_exception() takes exactly 2 arguments (%zd given)",
|
|
70
70
|
nargs);
|
|
71
71
|
return NULL;
|
|
72
72
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from typing import Any, Literal, Union
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
|
+
from _collections_abc import _check_methods # type: ignore[attr-defined]
|
|
3
4
|
import copy
|
|
4
5
|
import shutil
|
|
5
6
|
import csv
|
|
@@ -12,23 +13,6 @@ else:
|
|
|
12
13
|
from typing_extensions import disjoint_base
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
def _check_methods(C: type[Any], *methods: str) -> Union[bool, Literal[NotImplemented]]: # type: ignore
|
|
16
|
-
"""Check methods in `C`. If has, return `True`, else `NotImplemented`."""
|
|
17
|
-
# from `_collections_abc.py`.
|
|
18
|
-
# Copyright 2007 Google, Inc. All Rights Reserved.
|
|
19
|
-
# Licensed to PSF under a Contributor Agreement.
|
|
20
|
-
mro: tuple[type[Any], ...] = C.__mro__ # Added type hints for mro var
|
|
21
|
-
for method in methods:
|
|
22
|
-
for B in mro:
|
|
23
|
-
if method in B.__dict__:
|
|
24
|
-
if B.__dict__[method] is None:
|
|
25
|
-
return NotImplemented
|
|
26
|
-
break
|
|
27
|
-
else:
|
|
28
|
-
return NotImplemented
|
|
29
|
-
return True
|
|
30
|
-
|
|
31
|
-
|
|
32
16
|
# ----------------------------------------------------------------------
|
|
33
17
|
# ErrorCodeable
|
|
34
18
|
# ----------------------------------------------------------------------
|
|
@@ -9,7 +9,6 @@ from typing import (
|
|
|
9
9
|
overload,
|
|
10
10
|
)
|
|
11
11
|
|
|
12
|
-
from ..const import DEFAULT_ERROR_CACHE_SIZE
|
|
13
12
|
from ..wrappers.cache import ErrorCacheWrapper
|
|
14
13
|
|
|
15
14
|
_T = TypeVar("_T", bound=Callable[..., Any])
|
|
@@ -28,7 +27,7 @@ def error_cache(maxsize: Optional[int] = 128) -> Callable[[_T], ErrorCacheWrappe
|
|
|
28
27
|
# fmt: on
|
|
29
28
|
|
|
30
29
|
|
|
31
|
-
def error_cache(func: Optional[_T] = None, maxsize: Optional[int] =
|
|
30
|
+
def error_cache(func: Optional[_T] = None, maxsize: Optional[int] = 128) -> Any: # type: ignore
|
|
32
31
|
"""
|
|
33
32
|
Decorator to cache exceptions raised by a function.
|
|
34
33
|
|
|
@@ -10,4 +10,4 @@ from .level import Level
|
|
|
10
10
|
# Create the default global logger.
|
|
11
11
|
# It ships with a single stderr sink at DEBUG level (mirrors loguru's default).
|
|
12
12
|
logger: BaseLogger = BaseLogger(name="errortools")
|
|
13
|
-
logger.add(sys.stderr, level=Level.
|
|
13
|
+
logger.add(sys.stderr, level=Level.TRACE, colorize=None)
|
|
@@ -14,12 +14,6 @@ from .ignore import (
|
|
|
14
14
|
retry,
|
|
15
15
|
)
|
|
16
16
|
from .decorator.cache import error_cache
|
|
17
|
-
from .const import (
|
|
18
|
-
LARGE_ERROR_CACHE_SIZE,
|
|
19
|
-
SMALL_ERROR_CACHE_SIZE,
|
|
20
|
-
DEFAULT_ERROR_CACHE_SIZE,
|
|
21
|
-
UNLIMITED_ERROR_CACHE,
|
|
22
|
-
)
|
|
23
17
|
|
|
24
18
|
# ------------------------------------------------------------------
|
|
25
19
|
# ignore: Common exception shortcuts
|
|
@@ -114,10 +108,10 @@ retry_5_delay_1s: Callable = partial(retry, times=5, delay=1)
|
|
|
114
108
|
# error cache presets
|
|
115
109
|
# ------------------------------------------------------------------
|
|
116
110
|
|
|
117
|
-
unlimited_error_cache: Callable = partial(error_cache, maxsize=
|
|
118
|
-
lru_error_cache: Callable = partial(error_cache, maxsize=
|
|
119
|
-
small_error_cache: Callable = partial(error_cache, maxsize=
|
|
120
|
-
large_error_cache: Callable = partial(error_cache, maxsize=
|
|
111
|
+
unlimited_error_cache: Callable = partial(error_cache, maxsize=1024)
|
|
112
|
+
lru_error_cache: Callable = partial(error_cache, maxsize=128)
|
|
113
|
+
small_error_cache: Callable = partial(error_cache, maxsize=64)
|
|
114
|
+
large_error_cache: Callable = partial(error_cache, maxsize=None)
|
|
121
115
|
|
|
122
116
|
|
|
123
117
|
# ------------------------------------------------------------------
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Ultra-lightweight plugin system for errortools."""
|
|
2
|
+
|
|
3
|
+
from typing import Callable, Any
|
|
4
|
+
|
|
5
|
+
_REGISTRY: dict[str, Callable[..., Any]] = {}
|
|
6
|
+
_UNSET = object()
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"register",
|
|
10
|
+
"get",
|
|
11
|
+
"has",
|
|
12
|
+
"list_all",
|
|
13
|
+
"run",
|
|
14
|
+
"remove",
|
|
15
|
+
"clear",
|
|
16
|
+
"Registry",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def register(name: str) -> Callable:
|
|
21
|
+
"""Register plugin (decorator).
|
|
22
|
+
|
|
23
|
+
.. versionadded:: 3.2
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def decorator(func: Callable) -> Callable:
|
|
27
|
+
_REGISTRY[name] = func
|
|
28
|
+
return func
|
|
29
|
+
|
|
30
|
+
return decorator
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get(name: str, default: Any = _UNSET) -> Any:
|
|
34
|
+
"""Get registered plugin.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
name: Plugin identifier.
|
|
38
|
+
default: Value returned when the plugin is missing.
|
|
39
|
+
If not provided, a `ValueError` is raised instead.
|
|
40
|
+
|
|
41
|
+
Raises:
|
|
42
|
+
ValueError: If the plugin does not exist and no *default* was supplied.
|
|
43
|
+
|
|
44
|
+
.. versionadded:: 3.2
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
return _REGISTRY[name]
|
|
48
|
+
except KeyError:
|
|
49
|
+
if default is not _UNSET:
|
|
50
|
+
return default
|
|
51
|
+
raise ValueError(f"Plugin {name!r} is not registered")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def has(name: str) -> bool:
|
|
55
|
+
"""Check whether a plugin is registered.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
name: Plugin identifier.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
``True`` if a plugin with the given *name* is registered,
|
|
62
|
+
otherwise ``False``.
|
|
63
|
+
|
|
64
|
+
.. versionadded:: 3.3
|
|
65
|
+
"""
|
|
66
|
+
return name in _REGISTRY
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def remove(name: str) -> None:
|
|
70
|
+
"""Remove a plugin.
|
|
71
|
+
|
|
72
|
+
This is a no-op if the plugin does not exist.
|
|
73
|
+
|
|
74
|
+
.. versionadded:: 3.2
|
|
75
|
+
"""
|
|
76
|
+
_REGISTRY.pop(name, None)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def clear() -> None:
|
|
80
|
+
"""Remove all plugins from the registry.
|
|
81
|
+
|
|
82
|
+
.. versionadded:: 3.3
|
|
83
|
+
"""
|
|
84
|
+
_REGISTRY.clear()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def list_all() -> list[str]:
|
|
88
|
+
"""List all plugin names.
|
|
89
|
+
|
|
90
|
+
.. versionadded:: 3.2
|
|
91
|
+
"""
|
|
92
|
+
return list(_REGISTRY.keys())
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def run(name: str, *args, **kwargs) -> Any:
|
|
96
|
+
"""Run plugin.
|
|
97
|
+
|
|
98
|
+
Raises:
|
|
99
|
+
ValueError: If the plugin does not exist.
|
|
100
|
+
|
|
101
|
+
.. versionadded:: 3.2
|
|
102
|
+
"""
|
|
103
|
+
return get(name)(*args, **kwargs)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class Registry:
|
|
107
|
+
"""Static class providing an alternative API for the plugin registry.
|
|
108
|
+
|
|
109
|
+
.. versionadded:: 3.2
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
@staticmethod
|
|
113
|
+
def register(name: str, func: Callable) -> None:
|
|
114
|
+
_REGISTRY[name] = func
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def list_all() -> list[str]:
|
|
118
|
+
return list_all()
|
|
119
|
+
|
|
120
|
+
@staticmethod
|
|
121
|
+
def get(name: str) -> Any:
|
|
122
|
+
return get(name)
|
|
123
|
+
|
|
124
|
+
@staticmethod
|
|
125
|
+
def has(name: str) -> bool:
|
|
126
|
+
return has(name)
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def remove(name: str) -> None:
|
|
130
|
+
remove(name)
|
|
131
|
+
|
|
132
|
+
@staticmethod
|
|
133
|
+
def clear() -> None:
|
|
134
|
+
clear()
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
def _get_version_tuple(version: str) -> tuple[int, int, int]:
|
|
2
|
-
parts = [int(p) for p in version.split(".")]
|
|
3
|
-
|
|
4
|
-
major = parts[0] if len(parts) >= 1 else 0
|
|
5
|
-
minor = parts[1] if len(parts) >= 2 else 0
|
|
6
|
-
patch = parts[2] if len(parts) >= 3 else 0
|
|
7
|
-
|
|
8
|
-
return (major, minor, patch)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
__version__: str = "3.
|
|
12
|
-
__version_tuple__: tuple[int, int, int] = _get_version_tuple(__version__)
|
|
13
|
-
__commit_id__: str | None = None
|
|
14
|
-
|
|
15
|
-
version = __version__
|
|
16
|
-
version_tuple = __version_tuple__
|
|
17
|
-
commit_id = __commit_id__
|
|
1
|
+
def _get_version_tuple(version: str) -> tuple[int, int, int]:
|
|
2
|
+
parts = [int(p) for p in version.split(".")]
|
|
3
|
+
|
|
4
|
+
major = parts[0] if len(parts) >= 1 else 0
|
|
5
|
+
minor = parts[1] if len(parts) >= 2 else 0
|
|
6
|
+
patch = parts[2] if len(parts) >= 3 else 0
|
|
7
|
+
|
|
8
|
+
return (major, minor, patch)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
__version__: str = "3.4.0"
|
|
12
|
+
__version_tuple__: tuple[int, int, int] = _get_version_tuple(__version__)
|
|
13
|
+
__commit_id__: str | None = None
|
|
14
|
+
|
|
15
|
+
version = __version__
|
|
16
|
+
version_tuple = __version_tuple__
|
|
17
|
+
commit_id = __commit_id__
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
errortools - a toolset for working with Python exceptions and warnings and logging.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import sys
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
5
8
|
from _errortools.raises import raises, assert_raises, raises_all, reraise
|
|
6
9
|
from _errortools.ignore import (
|
|
7
10
|
ignore,
|
|
@@ -16,7 +19,7 @@ from _errortools.errno import (
|
|
|
16
19
|
get_all_errno_codes,
|
|
17
20
|
is_valid_errno,
|
|
18
21
|
)
|
|
19
|
-
from _errortools.classes.group import BaseGroup, GroupErrors
|
|
22
|
+
from _errortools.classes.group import BaseGroup, GroupErrors # noqa: F401
|
|
20
23
|
from _errortools.decorator.cache import error_cache
|
|
21
24
|
from _errortools.decorator.deprecated import deprecated, experimental
|
|
22
25
|
from _errortools.decorator.handlers import suppress, convert
|
|
@@ -45,6 +48,22 @@ from _errortools.classes.abc import (
|
|
|
45
48
|
Raiseable,
|
|
46
49
|
Error,
|
|
47
50
|
)
|
|
51
|
+
from _errortools.classes.protocol import ( # noqa: F401
|
|
52
|
+
ExceptionLike,
|
|
53
|
+
ExceptionGroupLike,
|
|
54
|
+
BaseExceptionGroupLike,
|
|
55
|
+
BlockingIOErrorLike,
|
|
56
|
+
NameErrorLike,
|
|
57
|
+
StopIterationLike,
|
|
58
|
+
SyntaxErrorLike,
|
|
59
|
+
SystemExitLike,
|
|
60
|
+
ImportErrorLike,
|
|
61
|
+
UnicodeDecodeErrorLike,
|
|
62
|
+
UnicodeEncodeErrorLike,
|
|
63
|
+
UnicodeTranslateErrorLike,
|
|
64
|
+
AttributeErrorLike,
|
|
65
|
+
GroupErrorsLike,
|
|
66
|
+
)
|
|
48
67
|
from _errortools.typing import (
|
|
49
68
|
AnyErrorCode,
|
|
50
69
|
BaseErrorCodesType,
|
|
@@ -55,6 +74,7 @@ from _errortools.typing import (
|
|
|
55
74
|
TracebackType,
|
|
56
75
|
FrameType,
|
|
57
76
|
)
|
|
77
|
+
from _errortools.plugins import run, register, list_all, get, has, remove, clear, Registry
|
|
58
78
|
from _errortools.descriptor.errormsg import ErrorMsg
|
|
59
79
|
from _errortools.descriptor.nonblankmsg import NonBlankErrorMsg
|
|
60
80
|
from _errortools.version import (
|
|
@@ -88,6 +108,10 @@ _DEPRECATED_NAMES: dict[str, tuple[str, str]] = {
|
|
|
88
108
|
}
|
|
89
109
|
|
|
90
110
|
|
|
111
|
+
class ErrortoolsDeprecationWarning(DeprecationWarning):
|
|
112
|
+
"""Base class for warnings about deprecated features in errortools module."""
|
|
113
|
+
|
|
114
|
+
|
|
91
115
|
def __getattr__(name: str):
|
|
92
116
|
import importlib
|
|
93
117
|
import warnings
|
|
@@ -96,7 +120,7 @@ def __getattr__(name: str):
|
|
|
96
120
|
attr_name, reason = _DEPRECATED_NAMES[name]
|
|
97
121
|
warnings.warn(
|
|
98
122
|
f"errortools.{attr_name} is deprecated. {reason}",
|
|
99
|
-
|
|
123
|
+
ErrortoolsDeprecationWarning,
|
|
100
124
|
stacklevel=2,
|
|
101
125
|
)
|
|
102
126
|
return globals()[f"_{name}"] if f"_{name}" in globals() else globals().get(name)
|
|
@@ -104,6 +128,11 @@ def __getattr__(name: str):
|
|
|
104
128
|
if name in ("future", "logging", "partial"):
|
|
105
129
|
return importlib.import_module(f"_errortools.{name}")
|
|
106
130
|
|
|
131
|
+
try:
|
|
132
|
+
return get(name)
|
|
133
|
+
except ValueError:
|
|
134
|
+
pass
|
|
135
|
+
|
|
107
136
|
raise AttributeError(f"module 'errortools' has no attribute {name!r}")
|
|
108
137
|
|
|
109
138
|
|
|
@@ -111,6 +140,23 @@ def __dir__() -> list[str]:
|
|
|
111
140
|
return __all__
|
|
112
141
|
|
|
113
142
|
|
|
143
|
+
class PluginNamespace:
|
|
144
|
+
def __getattr__(self, name: str) -> Any:
|
|
145
|
+
plugin = get(name)
|
|
146
|
+
if plugin is None:
|
|
147
|
+
raise AttributeError(f"Plugin {name!r} not found")
|
|
148
|
+
return plugin
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
plugins = PluginNamespace()
|
|
152
|
+
|
|
153
|
+
_PYTHON_3_11_CAN_USE: list[str] = [
|
|
154
|
+
"GroupErrors",
|
|
155
|
+
"BaseGroup",
|
|
156
|
+
"BaseExceptionGroupLike",
|
|
157
|
+
"ExceptionGroupLike",
|
|
158
|
+
"GroupErrorsLike",
|
|
159
|
+
]
|
|
114
160
|
__all__ = [
|
|
115
161
|
# functions
|
|
116
162
|
"raises",
|
|
@@ -135,8 +181,6 @@ __all__ = [
|
|
|
135
181
|
"TracebackType",
|
|
136
182
|
"FrameType",
|
|
137
183
|
# classes
|
|
138
|
-
"GroupErrors",
|
|
139
|
-
"BaseGroup",
|
|
140
184
|
"BaseErrorCodes",
|
|
141
185
|
"InvalidInputError",
|
|
142
186
|
"NotFoundError",
|
|
@@ -158,6 +202,18 @@ __all__ = [
|
|
|
158
202
|
"PureBaseException",
|
|
159
203
|
"ContextException",
|
|
160
204
|
"Error",
|
|
205
|
+
"ExceptionLike",
|
|
206
|
+
"BlockingIOErrorLike",
|
|
207
|
+
"NameErrorLike",
|
|
208
|
+
"StopIterationLike",
|
|
209
|
+
"SystemExitLike",
|
|
210
|
+
"ImportErrorLike",
|
|
211
|
+
"SyntaxErrorLike",
|
|
212
|
+
"UnicodeDecodeErrorLike",
|
|
213
|
+
"UnicodeEncodeErrorLike",
|
|
214
|
+
"UnicodeTranslateErrorLike",
|
|
215
|
+
"AttributeErrorLike",
|
|
216
|
+
"ErrortoolsDeprecationWarning",
|
|
161
217
|
# for type hints
|
|
162
218
|
"PureBaseExceptionType",
|
|
163
219
|
"ContextExceptionType",
|
|
@@ -169,6 +225,15 @@ __all__ = [
|
|
|
169
225
|
"RuntimeError_",
|
|
170
226
|
"ExceptionType",
|
|
171
227
|
"WarningType",
|
|
228
|
+
# plugins
|
|
229
|
+
"register",
|
|
230
|
+
"get",
|
|
231
|
+
"has",
|
|
232
|
+
"list_all",
|
|
233
|
+
"run",
|
|
234
|
+
"remove",
|
|
235
|
+
"clear",
|
|
236
|
+
"Registry",
|
|
172
237
|
# metadata
|
|
173
238
|
"__version__",
|
|
174
239
|
"__version_tuple__",
|
|
@@ -192,3 +257,8 @@ __all__ = [
|
|
|
192
257
|
"logging",
|
|
193
258
|
"partial",
|
|
194
259
|
]
|
|
260
|
+
|
|
261
|
+
__all__.append("plugins")
|
|
262
|
+
|
|
263
|
+
if sys.version_info >= (3, 11):
|
|
264
|
+
__all__.append(_PYTHON_3_11_CAN_USE)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: errortools
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.0
|
|
4
4
|
Summary: errortools - a toolset for working with Python exceptions and warnings and logging.
|
|
5
5
|
Author-email: Evan Yang <quantbit@126.com>
|
|
6
6
|
License: Copyright (c) 2026 authors see AUTHORS.txt
|
|
@@ -25,6 +25,7 @@ License: Copyright (c) 2026 authors see AUTHORS.txt
|
|
|
25
25
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
26
26
|
|
|
27
27
|
Project-URL: Homepage, https://github.com/more-abc/errortools
|
|
28
|
+
Project-URL: Documentation, https://errortools.readthedocs.io/
|
|
28
29
|
Classifier: License :: OSI Approved :: MIT License
|
|
29
30
|
Classifier: Programming Language :: Python :: 3
|
|
30
31
|
Classifier: Programming Language :: Python :: 3.8
|
|
@@ -7,12 +7,12 @@ _errortools/__main__.py
|
|
|
7
7
|
_errortools/_cli.py
|
|
8
8
|
_errortools/_speedup.c
|
|
9
9
|
_errortools/cli.py
|
|
10
|
-
_errortools/const.py
|
|
11
10
|
_errortools/errno.py
|
|
12
11
|
_errortools/future.py
|
|
13
12
|
_errortools/ignore.py
|
|
14
13
|
_errortools/metadata.py
|
|
15
14
|
_errortools/partial.py
|
|
15
|
+
_errortools/plugins.py
|
|
16
16
|
_errortools/py.typed
|
|
17
17
|
_errortools/raises.py
|
|
18
18
|
_errortools/typing.py
|
|
@@ -41,7 +41,6 @@ _errortools/logging/sink.py
|
|
|
41
41
|
_errortools/wrappers/__init__.py
|
|
42
42
|
_errortools/wrappers/cache.py
|
|
43
43
|
_errortools/wrappers/ignore.py
|
|
44
|
-
docs/conf.py
|
|
45
44
|
errortools/__init__.py
|
|
46
45
|
errortools/__main__.py
|
|
47
46
|
errortools/future.py
|
|
@@ -57,20 +56,15 @@ testing/__init__.py
|
|
|
57
56
|
testing/__main__.py
|
|
58
57
|
testing/conftest.py
|
|
59
58
|
testing/run_tests.py
|
|
60
|
-
testing/test_abc.py
|
|
61
|
-
testing/test_const.py
|
|
62
59
|
testing/test_decorator.py
|
|
63
60
|
testing/test_descriptor.py
|
|
64
61
|
testing/test_errno.py
|
|
65
|
-
testing/test_errorcodes.py
|
|
66
|
-
testing/test_future.py
|
|
67
62
|
testing/test_groups.py
|
|
68
63
|
testing/test_ignore.py
|
|
69
|
-
testing/
|
|
70
|
-
testing/test_partials.py
|
|
64
|
+
testing/test_plugins.py
|
|
71
65
|
testing/test_raises.py
|
|
72
66
|
testing/test_typing.py
|
|
73
|
-
testing/
|
|
67
|
+
testing/test_version.py
|
|
74
68
|
testing/benchmark/__init__.py
|
|
75
69
|
testing/benchmark/test_future_perf.py
|
|
76
70
|
testing/test_testing/__init__.py
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "errortools"
|
|
8
|
-
version = "3.
|
|
8
|
+
version = "3.4.0"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Evan Yang", email = "quantbit@126.com" }
|
|
11
11
|
]
|
|
@@ -38,6 +38,7 @@ classifiers = [
|
|
|
38
38
|
|
|
39
39
|
[project.urls]
|
|
40
40
|
Homepage = "https://github.com/more-abc/errortools"
|
|
41
|
+
Documentation = "https://errortools.readthedocs.io/"
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
[project.scripts]
|
|
@@ -50,6 +51,8 @@ _errortools = ["py.typed"]
|
|
|
50
51
|
|
|
51
52
|
[tool.setuptools.packages.find]
|
|
52
53
|
where = ["."]
|
|
54
|
+
include = ["errortools", "_errortools", "testing"]
|
|
55
|
+
exclude = ["htmlcov", ".*", "docs"]
|
|
53
56
|
|
|
54
57
|
|
|
55
58
|
[[tool.setuptools.ext-modules]]
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import warnings
|
|
4
4
|
|
|
5
|
+
from _errortools.version import _get_version_tuple
|
|
6
|
+
|
|
5
7
|
__all__ = [
|
|
6
8
|
"__version__",
|
|
7
9
|
"__version_tuple__",
|
|
8
10
|
"HAS_PYTEST",
|
|
9
11
|
"NO_ONE_CHANGE_VERSION",
|
|
10
12
|
]
|
|
11
|
-
__version__ = "1.
|
|
12
|
-
__version_tuple__ = (
|
|
13
|
+
__version__ = "1.3.5"
|
|
14
|
+
__version_tuple__ = _get_version_tuple(__version__)
|
|
13
15
|
|
|
14
16
|
try:
|
|
15
17
|
import pytest
|