python-custom-exceptions 0.0.2__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.
@@ -1,15 +1,37 @@
1
1
  from python_custom_exceptions.base_custom_exception import BaseCustomException, DiagnosticInfo, serialize_data
2
+ from python_custom_exceptions.comparison_exception import ComparisonException
2
3
  from python_custom_exceptions.connection_exceptions import ConnectionException
4
+ from python_custom_exceptions.execution_exception import TimedExecutionException
3
5
  from python_custom_exceptions.is_exist_exception import (
6
+ IsExistAfterOperationException,
4
7
  IsExistException,
8
+ IsNotExistAfterOperationException,
5
9
  IsNotExistException,
6
10
  )
11
+ from python_custom_exceptions.operation_exception import (
12
+ NotOperationalException,
13
+ OperationException,
14
+ UnexpectedlySucceededOperationException,
15
+ )
16
+ from python_custom_exceptions.os_exceptions import UnsupportedOSExceptions
17
+ from python_custom_exceptions.unsupported_exception import UnsupportedExceptions
18
+ from python_custom_exceptions.wrong_exception import WrongUsageException
7
19
 
8
20
  __all__ = [
9
21
  "BaseCustomException",
10
22
  "DiagnosticInfo",
11
23
  "serialize_data",
12
24
  "ConnectionException",
25
+ "ComparisonException",
26
+ "IsExistAfterOperationException",
13
27
  "IsExistException",
14
28
  "IsNotExistException",
29
+ "IsNotExistAfterOperationException",
30
+ "NotOperationalException",
31
+ "OperationException",
32
+ "TimedExecutionException",
33
+ "UnexpectedlySucceededOperationException",
34
+ "UnsupportedExceptions",
35
+ "WrongUsageException",
36
+ "UnsupportedOSExceptions",
15
37
  ]
@@ -0,0 +1,20 @@
1
+ from python_custom_exceptions.base_custom_exception import BaseCustomException, DiagnosticInfo
2
+
3
+
4
+ class ComparisonException(BaseCustomException):
5
+ def __init__(
6
+ self,
7
+ expected_value: int,
8
+ actual_value: int,
9
+ subject: str | None = None,
10
+ diagnostic_info: dict | DiagnosticInfo | None = None,
11
+ ) -> None:
12
+ message = (
13
+ f"Expected {subject} to be [{expected_value}], but got [{actual_value}]"
14
+ if subject
15
+ else f"Expected [{expected_value}], but got [{actual_value}]"
16
+ )
17
+ super().__init__(
18
+ message_with_marking_dynamic_variables=message,
19
+ diagnostic_info=diagnostic_info,
20
+ )
@@ -0,0 +1,15 @@
1
+ from python_custom_exceptions.base_custom_exception import BaseCustomException, DiagnosticInfo
2
+
3
+
4
+ class TimedExecutionException(BaseCustomException):
5
+ def __init__(
6
+ self,
7
+ operation: str,
8
+ timeout: str | int,
9
+ diagnostic_info: dict | DiagnosticInfo | None = None,
10
+ ) -> None:
11
+ message = f"Operation {operation} did not succeed within [{timeout}] seconds"
12
+ super().__init__(
13
+ message_with_marking_dynamic_variables=message,
14
+ diagnostic_info=diagnostic_info,
15
+ )
@@ -25,3 +25,31 @@ class IsNotExistException(BaseCustomException):
25
25
  message_with_marking_dynamic_variables=message,
26
26
  diagnostic_info=diagnostic_info,
27
27
  )
28
+
29
+
30
+ class IsExistAfterOperationException(BaseCustomException):
31
+ def __init__(
32
+ self,
33
+ subject: str,
34
+ operation: str,
35
+ diagnostic_info: dict | DiagnosticInfo | None = None,
36
+ ) -> None:
37
+ message = f"{subject} exists after trying to {operation}"
38
+ super().__init__(
39
+ message_with_marking_dynamic_variables=message,
40
+ diagnostic_info=diagnostic_info,
41
+ )
42
+
43
+
44
+ class IsNotExistAfterOperationException(BaseCustomException):
45
+ def __init__(
46
+ self,
47
+ subject: str,
48
+ operation: str,
49
+ diagnostic_info: dict | DiagnosticInfo | None = None,
50
+ ) -> None:
51
+ message = f"{subject} does not exist after trying to {operation}"
52
+ super().__init__(
53
+ message_with_marking_dynamic_variables=message,
54
+ diagnostic_info=diagnostic_info,
55
+ )
@@ -0,0 +1,40 @@
1
+ from python_custom_exceptions.base_custom_exception import BaseCustomException, DiagnosticInfo
2
+
3
+
4
+ class OperationException(BaseCustomException):
5
+ def __init__(
6
+ self,
7
+ operation: str,
8
+ diagnostic_info: dict | DiagnosticInfo | None = None,
9
+ ) -> None:
10
+ message = f"Operation {operation} failed"
11
+ super().__init__(
12
+ message_with_marking_dynamic_variables=message,
13
+ diagnostic_info=diagnostic_info,
14
+ )
15
+
16
+
17
+ class NotOperationalException(BaseCustomException):
18
+ def __init__(
19
+ self,
20
+ subject: str,
21
+ diagnostic_info: dict | DiagnosticInfo | None = None,
22
+ ) -> None:
23
+ message = f"{subject} is not Operational"
24
+ super().__init__(
25
+ message_with_marking_dynamic_variables=message,
26
+ diagnostic_info=diagnostic_info,
27
+ )
28
+
29
+
30
+ class UnexpectedlySucceededOperationException(BaseCustomException):
31
+ def __init__(
32
+ self,
33
+ operation: str,
34
+ diagnostic_info: dict | DiagnosticInfo | None = None,
35
+ ) -> None:
36
+ message = f"Operation {operation} unexpectedly succeeded"
37
+ super().__init__(
38
+ message_with_marking_dynamic_variables=message,
39
+ diagnostic_info=diagnostic_info,
40
+ )
@@ -0,0 +1,14 @@
1
+ from python_custom_exceptions.base_custom_exception import BaseCustomException, DiagnosticInfo
2
+
3
+
4
+ class UnsupportedOSExceptions(BaseCustomException):
5
+ def __init__(
6
+ self,
7
+ os_name: str,
8
+ diagnostic_info: dict | DiagnosticInfo | None = None,
9
+ ) -> None:
10
+ message = f'Unsupported OS: ["{os_name}"]'
11
+ super().__init__(
12
+ message_with_marking_dynamic_variables=message,
13
+ diagnostic_info=diagnostic_info,
14
+ )
@@ -0,0 +1,14 @@
1
+ from python_custom_exceptions.base_custom_exception import BaseCustomException, DiagnosticInfo
2
+
3
+
4
+ class UnsupportedExceptions(BaseCustomException):
5
+ def __init__(
6
+ self,
7
+ unsupported_subject: str,
8
+ diagnostic_info: dict | DiagnosticInfo | None = None,
9
+ ) -> None:
10
+ message = f"{unsupported_subject} is unsupported"
11
+ super().__init__(
12
+ message_with_marking_dynamic_variables=message,
13
+ diagnostic_info=diagnostic_info,
14
+ )
@@ -0,0 +1,14 @@
1
+ from python_custom_exceptions.base_custom_exception import BaseCustomException, DiagnosticInfo
2
+
3
+
4
+ class WrongUsageException(BaseCustomException):
5
+ def __init__(
6
+ self,
7
+ message: str,
8
+ diagnostic_info: dict | DiagnosticInfo | None = None,
9
+ ) -> None:
10
+ message = f"Wrong usage: {message}"
11
+ super().__init__(
12
+ message_with_marking_dynamic_variables=message,
13
+ diagnostic_info=diagnostic_info,
14
+ )
@@ -0,0 +1,154 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-custom-exceptions
3
+ Version: 1.0.0
4
+ Summary: A collection of custom exceptions for Python projects.
5
+ Author: Avi Zaguri
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/aviz92/python-custom-exceptions
8
+ Project-URL: Repository, https://github.com/aviz92/python-custom-exceptions
9
+ Project-URL: Issues, https://github.com/aviz92/python-custom-exceptions/issues
10
+ Keywords: development,python,exceptions,error-handling
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Python: >=3.12
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: python-base-toolkit>=1.1.3
20
+ Dynamic: license-file
21
+
22
+ # Python Custom Exceptions
23
+ A collection of structured, ready-to-use exception classes for Python projects. <br>
24
+ Every exception renders as JSON with its type, a human-readable message, and optional diagnostic info,
25
+ so errors are easy to read in logs and easy to parse by tools. <br>
26
+
27
+ ---
28
+
29
+ ### Features
30
+ - ✅ Specific Exception Classes: Ready-made exceptions for common error scenarios.
31
+ - ✅ Structured Output: `str(exception)` is a JSON document with type, message and diagnostic info.
32
+ - ✅ Diagnostic Info: Attach typed context (`TypedDict`, `dict` or dataclass) to any exception.
33
+ - ✅ Single Base Class: Everything inherits from `BaseCustomException`, so one `except` catches them all.
34
+ - ✅ Easy Extension: Subclass `BaseCustomException` to add your own exceptions.
35
+
36
+ ---
37
+
38
+ ### Installation
39
+ ```bash
40
+ uv add python-custom-exceptions
41
+ ```
42
+ or with pip:
43
+ ```bash
44
+ pip install python-custom-exceptions
45
+ ```
46
+ Requires Python 3.12+.
47
+
48
+ ---
49
+
50
+ ### Available Exceptions
51
+ | Exception | Arguments | Message |
52
+ |-----------|-----------|---------|
53
+ | `BaseCustomException` | `message_with_marking_dynamic_variables` | `<message>` |
54
+ | `ComparisonException` | `expected_value`, `actual_value`, `subject=None` | `Expected <subject> to be [<expected>], but got [<actual>]` |
55
+ | `ConnectionException` | `host`, `message=None` | `Connection failed: Unable to establish a connection to the remote host ["<host>"]. ...` |
56
+ | `IsExistException` | `subject` | `[<subject>] is exists` |
57
+ | `IsNotExistException` | `subject` | `[<subject>] is not exists` |
58
+ | `IsExistAfterOperationException` | `subject`, `operation` | `<subject> exists after trying to <operation>` |
59
+ | `IsNotExistAfterOperationException` | `subject`, `operation` | `<subject> does not exist after trying to <operation>` |
60
+ | `OperationException` | `operation` | `Operation <operation> failed` |
61
+ | `NotOperationalException` | `subject` | `<subject> is not Operational` |
62
+ | `UnexpectedlySucceededOperationException` | `operation` | `Operation <operation> unexpectedly succeeded` |
63
+ | `TimedExecutionException` | `operation`, `timeout` | `Operation <operation> did not succeed within [<timeout>] seconds` |
64
+ | `UnsupportedExceptions` | `unsupported_subject` | `<unsupported_subject> is unsupported` |
65
+ | `UnsupportedOSExceptions` | `os_name` | `Unsupported OS: ["<os_name>"]` |
66
+ | `WrongUsageException` | `message` | `Wrong usage: <message>` |
67
+
68
+ All exceptions also accept an optional `diagnostic_info` argument.
69
+
70
+ ---
71
+
72
+ ### Usage Examples
73
+
74
+ #### Raise an exception with diagnostic info
75
+ ```python
76
+ from pathlib import Path
77
+
78
+ from python_custom_exceptions import DiagnosticInfo, IsNotExistException
79
+
80
+
81
+ class PathDiagnosticInfo(DiagnosticInfo):
82
+ path: str
83
+
84
+
85
+ path = Path("/tmp/missing")
86
+ if not path.exists():
87
+ raise IsNotExistException(
88
+ subject="Directory",
89
+ diagnostic_info=PathDiagnosticInfo(path=str(path)),
90
+ )
91
+ ```
92
+ Output:
93
+ ```json
94
+ {
95
+ "exception_type": "IsNotExistException",
96
+ "message": "[Directory] is not exists",
97
+ "diagnostic_info": {
98
+ "path": "/tmp/missing"
99
+ }
100
+ }
101
+ ```
102
+
103
+ #### Catch any custom exception
104
+ ```python
105
+ from python_custom_exceptions import BaseCustomException, ComparisonException
106
+
107
+ try:
108
+ raise ComparisonException(expected_value=200, actual_value=500, subject="status code")
109
+ except BaseCustomException as exc:
110
+ print(exc.exception_type) # ComparisonException
111
+ print(exc.message) # Expected status code to be [200], but got [500]
112
+ print(exc.diagnostic_info) # {}
113
+ ```
114
+
115
+ #### Define your own exception
116
+ ```python
117
+ from python_custom_exceptions import BaseCustomException, DiagnosticInfo
118
+
119
+
120
+ class QuotaExceededException(BaseCustomException):
121
+ def __init__(self, resource: str, limit: int, diagnostic_info: dict | DiagnosticInfo | None = None) -> None:
122
+ super().__init__(
123
+ message_with_marking_dynamic_variables=f"Quota for [{resource}] exceeded the limit of [{limit}]",
124
+ diagnostic_info=diagnostic_info,
125
+ )
126
+ ```
127
+
128
+ ---
129
+
130
+ ### Development
131
+ ```bash
132
+ git clone https://github.com/aviz92/python-custom-exceptions.git
133
+ cd python-custom-exceptions
134
+ uv sync # create .venv and install runtime + dev dependencies
135
+ uv run pre-commit install # enable git hooks
136
+ uv run pytest # run the tests
137
+ uv build # build sdist + wheel into dist/
138
+ ```
139
+
140
+ ---
141
+
142
+ ### 🤝 Contributing
143
+ If you have a helpful exception, pattern, or improvement to suggest:
144
+ 1. Fork the repo
145
+ 2. Create a new branch
146
+ 3. Submit a pull request
147
+
148
+ I welcome additions that promote clean, productive, and maintainable development. <br>
149
+
150
+ ---
151
+
152
+ ### 🙏 Thanks
153
+ Thanks for exploring this repository! <br>
154
+ Happy coding! <br>
@@ -0,0 +1,15 @@
1
+ python_custom_exceptions/__init__.py,sha256=JX-P0mYY-z16Aqe3ELepizFbkPIfFebLdgo8WDwmMkc,1411
2
+ python_custom_exceptions/base_custom_exception.py,sha256=9fMv4EqSujbu6SyF9-UEevqN2FWvf4pBu2xqU2m3g1I,1412
3
+ python_custom_exceptions/comparison_exception.py,sha256=0dRXDfFVlSflrKEAyDJCj3gmbsC5mpf-YPdjXD_RhzE,699
4
+ python_custom_exceptions/connection_exceptions.py,sha256=AjOX7_P4bKi7Nm61mk0I7mP5A_YhQ3H55I3iiJ6BxVg,760
5
+ python_custom_exceptions/execution_exception.py,sha256=KkSbvHvNvB-qqbEXoj_QHfCxa5bR7_G11eHUK6RlVGA,537
6
+ python_custom_exceptions/is_exist_exception.py,sha256=38b9HxHcrXytdlN8J8lf6gVSID936UITVgl_1lXKJ8s,1683
7
+ python_custom_exceptions/operation_exception.py,sha256=AxrCnpEuUMTGdPkl41bStZjxgU1TOdoXgDV246NiRTE,1254
8
+ python_custom_exceptions/os_exceptions.py,sha256=826rmNcSdeJv7ZbdVNdyL8IqHQwFNTJn83l7nraWkXM,472
9
+ python_custom_exceptions/unsupported_exception.py,sha256=f44xg_1MKS2_5tq7ahtWygj3yj_tiFdfarN-FR9q9gk,489
10
+ python_custom_exceptions/wrong_exception.py,sha256=9BMp5bIo-NDp-unChsRpSusv-PC0CEn-cZxwVjoWoJ4,461
11
+ python_custom_exceptions-1.0.0.dist-info/licenses/LICENSE,sha256=cSikHY6SZFsPZSBizCDAJ0-Bjjzxt-JtX6TVbKxwimo,1067
12
+ python_custom_exceptions-1.0.0.dist-info/METADATA,sha256=ZQlzEY5ZA6LorGcUvfHNQZv8DJrYpbotP4Kzn6Gr9JI,5484
13
+ python_custom_exceptions-1.0.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
14
+ python_custom_exceptions-1.0.0.dist-info/top_level.txt,sha256=_dIQhOUJyiSda1cdPIziqTOHW4_ge023lo3kpj7j3kE,25
15
+ python_custom_exceptions-1.0.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (84.2.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,89 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: python-custom-exceptions
3
- Version: 0.0.2
4
- Summary: A collection of custom exceptions for Python projects.
5
- Home-page: https://github.com/aviz92/python-custom-exceptions
6
- Author: Avi Zaguri
7
- Author-email:
8
- Project-URL: Repository, https://github.com/aviz92/python-custom-exceptions
9
- Requires-Python: >=3.11
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: setuptools
13
- Requires-Dist: wheel
14
- Requires-Dist: python-dotenv
15
- Requires-Dist: pre-commit
16
- Requires-Dist: colorlog
17
- Requires-Dist: pytest
18
- Requires-Dist: pathlib
19
- Requires-Dist: pytest-plugins
20
- Requires-Dist: custom-python-logger
21
- Requires-Dist: python-base-toolkit
22
- Dynamic: author
23
- Dynamic: description
24
- Dynamic: description-content-type
25
- Dynamic: home-page
26
- Dynamic: license-file
27
- Dynamic: project-url
28
- Dynamic: requires-dist
29
- Dynamic: requires-python
30
- Dynamic: summary
31
-
32
- # Python Custom Exceptions
33
- A repository containing custom exception classes for Python projects. <br>
34
- These exceptions are designed to provide more specific error handling and improve code readability.
35
- They can be easily integrated into any Python application to enhance error management. <br>
36
-
37
- ---
38
-
39
- ### Features
40
- - ✅ Specific Exception Classes: Custom exceptions for various error scenarios.
41
- - ✅ Improved Readability: Clearer error handling in code.
42
- - ✅ Easy Integration: Simple to add to existing Python projects.
43
- - ✅ Standardized Error Handling: Consistent approach to managing exceptions.
44
- - ✅ Structured Hierarchy: Organized exception classes for better maintainability.
45
-
46
- ---
47
-
48
- ### Installation
49
- ```bash
50
- pip install python-custom-exceptions
51
- ```
52
-
53
- ---
54
-
55
- ### Usage Examples
56
- ```python
57
- import os
58
- from python_custom_exceptions import DiagnosticInfo, IsNotExistException
59
-
60
-
61
- class DiagnosticInfoTest(DiagnosticInfo):
62
- file_path: str
63
-
64
-
65
- file_path = "test_dir"
66
- os.mkdir(file_path)
67
- if not os.path.exists(file_path):
68
- raise IsNotExistException(
69
- subject="Directory",
70
- diagnostic_info=DiagnosticInfoTest(
71
- file_path=file_path
72
- )
73
- )
74
- ```
75
-
76
- ---
77
-
78
- ### 🤝 Contributing
79
- If you have a helpful tool, pattern, or improvement to suggest:
80
- Fork the repo <br>
81
- Create a new branch <br>
82
- Submit a pull request <br>
83
- I welcome additions that promote clean, productive, and maintainable development. <br>
84
-
85
- ---
86
-
87
- ### 🙏 Thanks
88
- Thanks for exploring this repository! <br>
89
- Happy coding! <br>
@@ -1,9 +0,0 @@
1
- python_custom_exceptions/__init__.py,sha256=RKeL20-rZvdru3S7LOiNBLwMpeMVOS_-N6ZQSvrJTa8,461
2
- python_custom_exceptions/base_custom_exception.py,sha256=9fMv4EqSujbu6SyF9-UEevqN2FWvf4pBu2xqU2m3g1I,1412
3
- python_custom_exceptions/connection_exceptions.py,sha256=AjOX7_P4bKi7Nm61mk0I7mP5A_YhQ3H55I3iiJ6BxVg,760
4
- python_custom_exceptions/is_exist_exception.py,sha256=WEMCXxdbZbx1zZTudoB8MKI2i2qoo3VHH9ss4knuEBY,826
5
- python_custom_exceptions-0.0.2.dist-info/licenses/LICENSE,sha256=cSikHY6SZFsPZSBizCDAJ0-Bjjzxt-JtX6TVbKxwimo,1067
6
- python_custom_exceptions-0.0.2.dist-info/METADATA,sha256=yp04v5SEh7um3fDD8mx5VSX7vla7I9UAEoGi3Q3Madw,2368
7
- python_custom_exceptions-0.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- python_custom_exceptions-0.0.2.dist-info/top_level.txt,sha256=_dIQhOUJyiSda1cdPIziqTOHW4_ge023lo3kpj7j3kE,25
9
- python_custom_exceptions-0.0.2.dist-info/RECORD,,