catchlib 0.0.0.dev0__py3-none-any.whl → 1.0.0__py3-none-any.whl
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.
- catchlib/__init__.py +0 -3
- catchlib/core/__init__.py +28 -4
- catchlib/tests/test_0.py +70 -0
- {catchlib-0.0.0.dev0.dist-info → catchlib-1.0.0.dist-info}/METADATA +5 -36
- catchlib-1.0.0.dist-info/RECORD +9 -0
- catchlib/__main__.py +0 -4
- catchlib/tests/test_1984.py +0 -11
- catchlib-0.0.0.dev0.dist-info/RECORD +0 -10
- {catchlib-0.0.0.dev0.dist-info → catchlib-1.0.0.dist-info}/WHEEL +0 -0
- {catchlib-0.0.0.dev0.dist-info → catchlib-1.0.0.dist-info}/licenses/LICENSE.txt +0 -0
- {catchlib-0.0.0.dev0.dist-info → catchlib-1.0.0.dist-info}/top_level.txt +0 -0
catchlib/__init__.py
CHANGED
catchlib/core/__init__.py
CHANGED
|
@@ -1,8 +1,32 @@
|
|
|
1
|
+
from contextlib import contextmanager
|
|
1
2
|
from typing import *
|
|
2
3
|
|
|
3
|
-
__all__ = ["
|
|
4
|
+
__all__ = ["Catcher"]
|
|
4
5
|
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
class Catcher:
|
|
8
|
+
|
|
9
|
+
"This class catches exceptions."
|
|
10
|
+
|
|
11
|
+
__slots__ = ("_caught",)
|
|
12
|
+
|
|
13
|
+
caught: Optional[BaseException]
|
|
14
|
+
|
|
15
|
+
def __init__(self: Self) -> None:
|
|
16
|
+
"This magic method initializes the current instance."
|
|
17
|
+
self._caught = None
|
|
18
|
+
|
|
19
|
+
@contextmanager
|
|
20
|
+
def catch(self: Self, *args: type[BaseException]) -> Generator[Self, None, None]:
|
|
21
|
+
"This contextmanager catches exceptions."
|
|
22
|
+
self._caught = None
|
|
23
|
+
exc: BaseException
|
|
24
|
+
try:
|
|
25
|
+
yield self
|
|
26
|
+
except args as exc:
|
|
27
|
+
self._caught = exc
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def caught(self: Self) -> Optional[BaseException]:
|
|
31
|
+
"This property stores the caught exception."
|
|
32
|
+
return self._caught
|
catchlib/tests/test_0.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from typing import *
|
|
3
|
+
|
|
4
|
+
from catchlib.core import Catcher
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestCatcher(unittest.TestCase):
|
|
8
|
+
def test_captures_matching_exception(self: Self) -> None:
|
|
9
|
+
catcher: Catcher = Catcher()
|
|
10
|
+
with catcher.catch(ValueError):
|
|
11
|
+
raise ValueError("bad value")
|
|
12
|
+
self.assertIsNotNone(catcher.caught)
|
|
13
|
+
self.assertIsInstance(catcher.caught, ValueError)
|
|
14
|
+
self.assertEqual(str(catcher.caught), "bad value")
|
|
15
|
+
|
|
16
|
+
def test_no_exception_leaves_caught_none(self: Self) -> None:
|
|
17
|
+
catcher: Catcher = Catcher()
|
|
18
|
+
with catcher.catch(ValueError):
|
|
19
|
+
pass
|
|
20
|
+
self.assertIsNone(catcher.caught)
|
|
21
|
+
|
|
22
|
+
def test_captures_one_of_multiple_types(self: Self) -> None:
|
|
23
|
+
catcher: Catcher = Catcher()
|
|
24
|
+
with catcher.catch(ValueError, KeyError):
|
|
25
|
+
raise KeyError("missing")
|
|
26
|
+
self.assertIsNotNone(catcher.caught)
|
|
27
|
+
self.assertIsInstance(catcher.caught, KeyError)
|
|
28
|
+
self.assertEqual(
|
|
29
|
+
str(catcher.caught), "'missing'"
|
|
30
|
+
) # KeyError stringifies with quotes
|
|
31
|
+
|
|
32
|
+
def test_non_matching_exception_propagates_and_does_not_set_caught(
|
|
33
|
+
self: Self,
|
|
34
|
+
) -> None:
|
|
35
|
+
catcher: Catcher = Catcher()
|
|
36
|
+
with self.assertRaises(ZeroDivisionError):
|
|
37
|
+
with catcher.catch(ValueError, KeyError):
|
|
38
|
+
1 / 0 # ZeroDivisionError not in capture set
|
|
39
|
+
# Since the exception propagated out, Catcher should not have recorded anything
|
|
40
|
+
self.assertIsNone(catcher.caught)
|
|
41
|
+
|
|
42
|
+
def test_reuse_and_reset_semantics(self: Self) -> None:
|
|
43
|
+
catcher: Catcher = Catcher()
|
|
44
|
+
|
|
45
|
+
# First, capture an exception
|
|
46
|
+
with catcher.catch(RuntimeError):
|
|
47
|
+
raise RuntimeError("first")
|
|
48
|
+
self.assertIsInstance(catcher.caught, RuntimeError)
|
|
49
|
+
|
|
50
|
+
# Next, a clean block should reset caught to None
|
|
51
|
+
with catcher.catch(RuntimeError):
|
|
52
|
+
pass
|
|
53
|
+
self.assertIsNone(catcher.caught)
|
|
54
|
+
|
|
55
|
+
# Finally, capture another (different) exception type by passing multiple
|
|
56
|
+
with catcher.catch(RuntimeError, TypeError):
|
|
57
|
+
raise TypeError("second")
|
|
58
|
+
self.assertIsInstance(catcher.caught, TypeError)
|
|
59
|
+
|
|
60
|
+
def test_empty_type_tuple_never_catches(self: Self) -> None:
|
|
61
|
+
catcher: Catcher = Catcher()
|
|
62
|
+
# Passing no types should behave like catching nothing: exception propagates
|
|
63
|
+
with self.assertRaises(ValueError):
|
|
64
|
+
with catcher.catch():
|
|
65
|
+
raise ValueError("won't be caught")
|
|
66
|
+
self.assertIsNone(catcher.caught)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
if __name__ == "__main__":
|
|
70
|
+
unittest.main()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: catchlib
|
|
3
|
-
Version:
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: This project allows to catch exceptions easily.
|
|
5
5
|
Author-email: Johannes <johannes.programming@gmail.com>
|
|
6
6
|
License: The MIT License (MIT)
|
|
7
7
|
|
|
@@ -27,7 +27,8 @@ License: The MIT License (MIT)
|
|
|
27
27
|
Project-URL: Download, https://pypi.org/project/catchlib/#files
|
|
28
28
|
Project-URL: Index, https://pypi.org/project/catchlib/
|
|
29
29
|
Project-URL: Source, https://github.com/johannes-programming/catchlib/
|
|
30
|
-
|
|
30
|
+
Project-URL: Website, https://catchlib.johannes-programming.online/
|
|
31
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
31
32
|
Classifier: License :: OSI Approved :: MIT License
|
|
32
33
|
Classifier: Natural Language :: English
|
|
33
34
|
Classifier: Operating System :: OS Independent
|
|
@@ -44,36 +45,4 @@ Dynamic: license-file
|
|
|
44
45
|
catchlib
|
|
45
46
|
========
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
--------
|
|
49
|
-
|
|
50
|
-
catchlib
|
|
51
|
-
|
|
52
|
-
Installation
|
|
53
|
-
------------
|
|
54
|
-
|
|
55
|
-
To install ``catchlib``, you can use ``pip``. Open your terminal and run:
|
|
56
|
-
|
|
57
|
-
.. code-block:: bash
|
|
58
|
-
|
|
59
|
-
pip install catchlib
|
|
60
|
-
|
|
61
|
-
License
|
|
62
|
-
-------
|
|
63
|
-
|
|
64
|
-
This project is licensed under the MIT License.
|
|
65
|
-
|
|
66
|
-
Links
|
|
67
|
-
-----
|
|
68
|
-
|
|
69
|
-
* `Download <https://pypi.org/project/catchlib/#files>`_
|
|
70
|
-
* `Index <https://pypi.org/project/catchlib/>`_
|
|
71
|
-
* `Source <https://github.com/johannes-programming/catchlib/>`_
|
|
72
|
-
|
|
73
|
-
Credits
|
|
74
|
-
-------
|
|
75
|
-
|
|
76
|
-
* Author: Johannes
|
|
77
|
-
* Email: `johannes.programming@gmail.com <mailto:johannes.programming@gmail.com>`_
|
|
78
|
-
|
|
79
|
-
Thank you for using ``catchlib``!
|
|
48
|
+
Visit the website `https://catchlib.johannes-programming.online/ <https://catchlib.johannes-programming.online/>`_ for more information.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
catchlib/__init__.py,sha256=LmWT7JBQPWFiRLTuaTqgduz9WH_4q2EyEtZMaBLIWe8,57
|
|
2
|
+
catchlib/core/__init__.py,sha256=RGJlPffKlyWeES0noN2qHrJeDXNXv0QVLNpk-Fe_jG8,791
|
|
3
|
+
catchlib/tests/__init__.py,sha256=F79E9ssYcoufZpYJ4I6XSvZTR0wkvc9r-5K3XpYvXsY,387
|
|
4
|
+
catchlib/tests/test_0.py,sha256=3GfPlhQRfGxj5fxKtMd--_HwAeE_7RbuRtrltnPHGDQ,2588
|
|
5
|
+
catchlib-1.0.0.dist-info/licenses/LICENSE.txt,sha256=fOh9FHccUt9OcJPBaVJ482GX4yrl_FxCUk9YRZ53JOI,1074
|
|
6
|
+
catchlib-1.0.0.dist-info/METADATA,sha256=U_agBbPRK5aLHGgzH5qGaGg1uuUyIDZOgtfLsDEpd0g,2311
|
|
7
|
+
catchlib-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
+
catchlib-1.0.0.dist-info/top_level.txt,sha256=pZsP_Y2Suk_fAyIQrw4g81DUtgZBRIWzb-5Bk-0jmZs,9
|
|
9
|
+
catchlib-1.0.0.dist-info/RECORD,,
|
catchlib/__main__.py
DELETED
catchlib/tests/test_1984.py
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
catchlib/__init__.py,sha256=cQbMQNae02UxVtDduzj3ZCzH87hbyJGbR5oXA_B0oCw,96
|
|
2
|
-
catchlib/__main__.py,sha256=dN8d0Nu8AGoONqnHvThcjtCb9E9YcNFGlaVHYYTeK4w,65
|
|
3
|
-
catchlib/core/__init__.py,sha256=Tr3CwIPY695IbF4DrKHrDes1AKd_iJgddUP46jxKHSw,163
|
|
4
|
-
catchlib/tests/__init__.py,sha256=F79E9ssYcoufZpYJ4I6XSvZTR0wkvc9r-5K3XpYvXsY,387
|
|
5
|
-
catchlib/tests/test_1984.py,sha256=_ami0cAP8vU0C8RpQhP1tLWnLFGTaeHlOG5O60RVKv8,222
|
|
6
|
-
catchlib-0.0.0.dev0.dist-info/licenses/LICENSE.txt,sha256=fOh9FHccUt9OcJPBaVJ482GX4yrl_FxCUk9YRZ53JOI,1074
|
|
7
|
-
catchlib-0.0.0.dev0.dist-info/METADATA,sha256=75xWXIpQsdmWirkcj_HaJpuMasBk7NDuoWrb-e4K5aA,2645
|
|
8
|
-
catchlib-0.0.0.dev0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
-
catchlib-0.0.0.dev0.dist-info/top_level.txt,sha256=pZsP_Y2Suk_fAyIQrw4g81DUtgZBRIWzb-5Bk-0jmZs,9
|
|
10
|
-
catchlib-0.0.0.dev0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|