DataExcept 0.2.1__tar.gz → 0.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.
Files changed (40) hide show
  1. dataexcept-0.4.0/CHANGELOG.md +276 -0
  2. {dataexcept-0.2.1 → dataexcept-0.4.0}/CITATION.cff +1 -1
  3. {dataexcept-0.2.1 → dataexcept-0.4.0}/PKG-INFO +13 -14
  4. {dataexcept-0.2.1 → dataexcept-0.4.0}/README.md +12 -13
  5. dataexcept-0.4.0/dataexcept/__init__.py +309 -0
  6. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/__main__.py +7 -1
  7. dataexcept-0.4.0/dataexcept/_validation.py +22 -0
  8. dataexcept-0.4.0/dataexcept/base.py +67 -0
  9. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/database_exceptions.py +7 -3
  10. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/dataengineering_exceptions.py +3 -1
  11. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/datascience_exceptions/base.py +3 -1
  12. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/datascience_exceptions/ingestion.py +5 -4
  13. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/datascience_exceptions/operations.py +4 -3
  14. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/datascience_exceptions/training.py +9 -8
  15. dataexcept-0.4.0/dataexcept/exceptions/base.py +7 -0
  16. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/exceptions/notification.py +6 -4
  17. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/io_exceptions.py +3 -1
  18. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/network_exceptions.py +3 -1
  19. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/pandas_exceptions.py +3 -1
  20. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/pipeline_exceptions.py +6 -3
  21. dataexcept-0.4.0/dataexcept/redaction.py +114 -0
  22. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/security_exceptions.py +8 -3
  23. {dataexcept-0.2.1 → dataexcept-0.4.0}/pyproject.toml +21 -2
  24. dataexcept-0.2.1/CHANGELOG.md +0 -132
  25. dataexcept-0.2.1/dataexcept/__init__.py +0 -94
  26. dataexcept-0.2.1/dataexcept/exceptions/base.py +0 -4
  27. {dataexcept-0.2.1 → dataexcept-0.4.0}/LICENSE +0 -0
  28. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/_deprecation.py +0 -0
  29. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/datascience_exceptions/__init__.py +0 -0
  30. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/exceptions/__init__.py +0 -0
  31. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/exceptions/authentication.py +0 -0
  32. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/exceptions/configuration.py +0 -0
  33. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/exceptions/external.py +0 -0
  34. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/exceptions/lifecycle.py +0 -0
  35. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/exceptions/parsing.py +0 -0
  36. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/exceptions/scheduling.py +0 -0
  37. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/exceptions/validation.py +0 -0
  38. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/job_exceptions.py +0 -0
  39. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/logging_helpers.py +0 -0
  40. {dataexcept-0.2.1 → dataexcept-0.4.0}/dataexcept/py.typed +0 -0
@@ -0,0 +1,276 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.4.0] - 2026-08-24
11
+
12
+ ### Added
13
+
14
+ - **`DataExceptError`, the root of the hierarchy.** Every exception the package
15
+ raises now derives from it, so one clause catches the whole library:
16
+ ```python
17
+ except DataExceptError:
18
+ ...
19
+ ```
20
+ The nine domain roots (`JobError`, `DataScienceError`, `PipelineError` and
21
+ the rest) sit beneath it and still catch only their own domain, so granular
22
+ handling is unchanged.
23
+
24
+ ### Changed
25
+
26
+ - `SECURITY.md` claimed 0.1.x was the supported version, and `CHECKLIST.md`
27
+ still described an uncommitted lockfile, 30 of 96 top-level exports, 109 tests
28
+ and 85% coverage. Both now match the project.
29
+ - **Coverage is now measured honestly, and gated.** `coverage run -m pytest`
30
+ had no `source` setting, so it counted the tests and examples in the
31
+ denominator — and test files are by definition fully executed. The reported
32
+ figure was inflated: 86% when the package alone was at 79%.
33
+ `[tool.coverage.run]` now restricts measurement to `dataexcept` and enables
34
+ branch coverage, and `fail_under = 91` stops it regressing. The honest number
35
+ is **92%**; the README, checklist and roadmap now quote that rather than the
36
+ inflated one.
37
+ - The CLI is exercised in-process as well as through a subprocess. The
38
+ subprocess tests verify real invocation but coverage cannot see inside them,
39
+ which left `__main__.py` reporting 23% despite being tested. It now reports
40
+ 93%.
41
+
42
+ ### Fixed
43
+
44
+ - **NumPy scalars are accepted where a number is expected.** Eleven validations
45
+ used `isinstance(value, (int, float))`, which rejects `numpy.float32` and
46
+ `numpy.int64` — a poor answer from a library aimed at data science. They now
47
+ use `numbers.Real`, which NumPy registers its scalar types with, so this needs
48
+ no dependency on NumPy. Arrays and non-numbers are still rejected.
49
+ - **A wrapped exception is now chained.** Constructors that take an underlying
50
+ exception recorded it on an attribute but never set `__cause__`, so a
51
+ traceback did not show what actually failed. `DataExceptError` now mirrors it,
52
+ and Python prints "The above exception was the direct cause of the following
53
+ exception" as if `raise ... from` had been used.
54
+ - `from dataexcept import *` failed under `-W error::DeprecationWarning`,
55
+ because `__all__` listed the deprecated `job_exceptions` module. It is no
56
+ longer advertised there; it remains importable until 1.0.0.
57
+ - A redundant `global` declaration in `examples/lambda_main.py` raised three
58
+ `F824` warnings. CI linted only `dataexcept` and `tests` with flake8 while the
59
+ formatters covered `examples` and `scripts`; flake8 now covers all four.
60
+ - **Four exceptions discarded the reason for the failure.**
61
+ `DataLoadingError`, `MissingDataError`, `ModelSerializationError` and
62
+ `DeploymentError` rendered only their identifying attribute —
63
+ `[DataLoadingError] orders.csv` — while "invalid utf-8", "disk full" or
64
+ "permission denied" sat unseen in `args[0]`. Since logging uses `str(exc)`,
65
+ the part a reader needs never reached the log. All four now render the full
66
+ message, and a test asserts no class drops it.
67
+ - **Exceptions can now cross a process boundary.** They could not be pickled:
68
+ most constructors take several arguments while `Exception.args` holds only
69
+ the rendered message, and the default protocol replays `args` through
70
+ `__init__`. Of 98 classes, 39 raised `TypeError` on unpickling and a further
71
+ 47 came back with different state — only 10 round-tripped exactly. Raising
72
+ one inside a `ProcessPoolExecutor` killed the pool with `BrokenProcessPool`.
73
+ `DataExceptError.__reduce__` restores `args` and `__dict__` directly instead
74
+ of replaying `__init__`. All 97 constructible classes now round-trip with
75
+ identical type, message and attributes, covered by a test per class plus a
76
+ real process-pool test.
77
+ - The stability policy and README both claimed `except JobError:` catches
78
+ "anything else this library raises". It did not — there were nine
79
+ disconnected trees under `Exception`, so `JobError` caught neither
80
+ `ModelTrainingError` nor `PipelineError` nor `DatabaseError`. The claim is
81
+ now true of `DataExceptError`, and the docs say which base covers what.
82
+
83
+ ### Security
84
+
85
+ - **A release now has to prove where it came from.** The release workflow
86
+ checked only that the tag text matched `pyproject.toml`, so a tag pushed to
87
+ an unreviewed branch could reach the PyPI publishing job. It now refuses to
88
+ build unless the tagged commit is reachable from `main` and the same checks
89
+ branch protection requires are green on that exact commit.
90
+ - The built wheel is tested before it is published. A new `verify-wheel` job
91
+ installs the artifact, deletes the source package so nothing can import it by
92
+ accident, and runs the whole suite against what will actually be uploaded.
93
+ `scripts/check_wheel.py` then asserts the distribution ships `py.typed` and a
94
+ complete `__all__` — a file can be present in the repository and missing from
95
+ the artifact.
96
+ - **Credentials are no longer written into exception messages.** `log_exception`
97
+ logs `str(exc)`, so a failed connection put the database password in the log.
98
+ `InvalidTokenError` embedded the whole token; `DatabaseConnectionError` the
99
+ whole connection URL including username and password; `WebhookError` and
100
+ `ApiError` the URL including any signing or key parameter.
101
+ These are now redacted before being stored or rendered, so the raw value is
102
+ absent from the message, the attributes and a pickle of the exception. A
103
+ secret renders as `***(1a2b3c4d)` — a truncated SHA-256, so the same bad
104
+ credential failing repeatedly stays correlatable in a log without appearing
105
+ in it. Host, port and path survive, because those are what make the error
106
+ actionable.
107
+ `QueryExecutionError` still embeds the SQL it is given; SECURITY.md now says
108
+ so explicitly rather than leaving it to be discovered.
109
+
110
+ ## [0.3.0] - 2026-08-24
111
+
112
+ ### Added
113
+
114
+ - **Every exception the package defines is now importable from `dataexcept`
115
+ directly.** All 98 classes are exported at the top level, so callers no
116
+ longer need to know which domain module a class lives in. The domain modules
117
+ export the same objects, so `from dataexcept import ValidationError` and
118
+ `from dataexcept.exceptions import ValidationError` are interchangeable and
119
+ `except` behaves identically either way.
120
+
121
+ This was only safe because 0.2.0 removed the two hazards that make a flat
122
+ namespace dangerous: there are no duplicate class names left, and nothing
123
+ shadows a Python builtin. Imports are explicit rather than generated at
124
+ runtime, so type checkers and IDEs see the full surface — the package ships
125
+ `py.typed`.
126
+ - `dataexcept.exceptions` and `dataexcept.logging_helpers` are now named in
127
+ `__all__` alongside the other domain modules; the stability policy already
128
+ described them as public.
129
+ - Tests covering the public surface: every exception the package defines must
130
+ be exported and resolve, each top-level export must be the *same object* as
131
+ the submodule one, no exported name may shadow a builtin, no two exceptions
132
+ may share a name, and `from dataexcept import *` must expose the documented
133
+ surface. Verified these fail when an unexported exception is introduced.
134
+ - Tests that `poetry.lock` is committed, and that `docs/requirements.txt`
135
+ agrees with the Poetry `docs` group — the two list the same packages and
136
+ could drift apart silently.
137
+
138
+ ### Changed
139
+
140
+ - `poetry.lock` is committed, and CI installs from it. Every job previously ran
141
+ `pip install black flake8 isort mypy ruff` unpinned, so a new release of any
142
+ linter could turn the build red with no commit to point at. `poetry check
143
+ --lock` now fails the build if the lock and `pyproject.toml` disagree.
144
+ - The coverage badge is generated by `scripts/coverage_badge.py` instead of
145
+ the `coverage-badge` package. That package still imports `pkg_resources`,
146
+ removed in setuptools 81, so using it required pinning `setuptools<81` — and
147
+ dependency review flagged a moderate-severity advisory against the version
148
+ that pin selected. Its last release was August 2024. Generating the SVG
149
+ directly removes the dependency, the pin and the advisory together; the
150
+ output is byte-identical to the published badge apart from the percentage.
151
+
152
+ ## [0.2.1] - 2026-08-24
153
+
154
+ Documentation and CLI fixes. 0.2.0's README is what PyPI renders as the
155
+ project description, and its quick-start example did not run.
156
+
157
+ ### Fixed
158
+
159
+ - `python -m dataexcept --version` reported `__main__.py` as the program name
160
+ instead of `dataexcept`, because argparse defaults `prog` to `sys.argv[0]`.
161
+ - `dataexcept list` imported the deprecated `job_exceptions` shim to build its
162
+ output, so it emitted a `DeprecationWarning` at anyone who merely wanted to
163
+ see what the package offers, and it advertised `ConnectionError` and
164
+ `TimeoutError` alongside their replacements. Deprecated modules are now
165
+ skipped; the listing is 98 names, matching the classes the package defines.
166
+ - README's quick-start example began `from dataexcept import ValidationError,
167
+ ModelTrainingError`, which raises `ImportError` — `ModelTrainingError` is in
168
+ `dataexcept.datascience_exceptions` and is not re-exported at the top level.
169
+ - `docs/advanced_usage.md` taught `from dataexcept.job_exceptions import
170
+ JobError`, the deprecated path.
171
+ - README's comparison table showed exception messages without the
172
+ `[ClassName]` prefix the classes actually emit, its sample `dataexcept list`
173
+ output did not match the real alphabetical listing, its exception count and
174
+ CLI version were stale, and its end-to-end example used `np.log` without
175
+ importing numpy.
176
+
177
+ ### Added
178
+
179
+ - Tests that read the documentation: every `from dataexcept... import ...` in
180
+ README and `docs/` must resolve, no example may import a deprecated module,
181
+ and the README's exception count must match the package. Checked that these
182
+ fail when the original defects are reintroduced.
183
+
184
+ ## [0.2.0] - 2026-08-24
185
+
186
+ ### Changed
187
+
188
+ - **`ConnectionError` is now `ServiceConnectionError`, and `TimeoutError` is
189
+ now `OperationTimeoutError`.** The old names shadowed Python builtins without
190
+ inheriting from them, so after `from dataexcept import ConnectionError` an
191
+ `except ConnectionError:` in that module silently stopped catching real
192
+ socket failures.
193
+ - **`datascience_exceptions.SerializationError` is now
194
+ `ModelSerializationError`**, and **`pipeline_exceptions.FeatureEngineeringError`
195
+ is now `FeaturePreprocessingError`.** Each of those names previously referred
196
+ to two different classes in different modules, so catching one silently
197
+ missed the other.
198
+ - Project metadata moved from Poetry's `[tool.poetry]` table to the standard
199
+ PEP 621 `[project]` table, clearing every `poetry check` deprecation. The
200
+ license is now an SPDX expression (PEP 639), so the built metadata carries
201
+ `License-Expression: MIT` and the redundant license classifier is gone.
202
+ Wheel and sdist contents are otherwise unchanged.
203
+ - `dataexcept.job_exceptions` now names its removal version, 1.0.0, in both the
204
+ warning and the module docstring.
205
+
206
+ ### Deprecated
207
+
208
+ - `ConnectionError`, `TimeoutError`, `datascience_exceptions.SerializationError`
209
+ and `pipeline_exceptions.FeatureEngineeringError`. All four still resolve, to
210
+ the **same class object** as their replacement, so existing `except` clauses
211
+ keep working; touching one emits a `DeprecationWarning` naming the
212
+ replacement and 1.0.0 as the removal. Importing the package does not warn.
213
+ Find remaining uses with `python -W error::DeprecationWarning -m pytest`.
214
+
215
+ ### Added
216
+
217
+ - A published [API stability policy](https://diogoribeiro7.github.io/DataExcept/stability/)
218
+ stating what is public, what each kind of change costs in version terms, the
219
+ deprecation process, and how to migrate off the 0.2.0 renames.
220
+ - Security scanning: CodeQL, and pip-audit against the runtime and
221
+ documentation dependency sets, on push, pull request and weekly — advisories
222
+ are published against code that has not changed. Pull requests also get a
223
+ dependency review failing at moderate severity.
224
+ - Complexity and security linting via ruff's mccabe (`C90`) and flake8-bandit
225
+ (`S`) rule sets, so neither needs a separate tool. Complexity is capped at 8;
226
+ the highest score in the package is 6.
227
+ - A regression guard that fails if any exported name ever shadows a builtin
228
+ again.
229
+ - `__all__` on `dataexcept.logging_helpers`, the one public module without one.
230
+
231
+ ### Fixed
232
+
233
+ - `dataexcept.__version__` and `tests/test_version.py` read the version out of
234
+ `pyproject.toml` when the package is not installed, and were still looking in
235
+ `[tool.poetry]`. They now read `[project]`.
236
+ - `examples/example_usage.py` raised `TimeoutError` with keyword arguments the
237
+ builtin does not accept — a live instance of the shadowing hazard.
238
+
239
+
240
+ ## [0.1.0] - 2026-08-24
241
+
242
+ First public release.
243
+
244
+ ### Added
245
+
246
+ - Hierarchical exception classes for data science, machine learning and data
247
+ engineering workflows. Catch a specific failure or a broad category, and get
248
+ a message that names the value that caused it rather than a bare
249
+ `ValueError`.
250
+ - Domain modules for validation, configuration, authentication, parsing,
251
+ serialization, scheduling, notification, lifecycle and external-service
252
+ errors, plus dedicated pandas, database, network, I/O, pipeline and security
253
+ exception groups.
254
+ - `dataexcept.logging_helpers` with `log_exception`, `log_and_raise` and
255
+ `log_then_raise`, for logging exceptions with structured context and
256
+ re-raising without losing the traceback.
257
+ - A `dataexcept` command-line entry point that lists the exported exception
258
+ classes and reports the installed version.
259
+ - A `py.typed` marker, backed by a mypy-clean codebase that CI enforces, so
260
+ downstream type checkers get annotations that are actually correct.
261
+ - Documentation at
262
+ [diogoribeiro7.github.io/DataExcept](https://diogoribeiro7.github.io/DataExcept/),
263
+ including an API reference generated from the docstrings.
264
+
265
+ ### Notes
266
+
267
+ - Supports Python 3.10 through 3.13.
268
+ - Published to PyPI via OIDC trusted publishing; no long-lived API token is
269
+ involved in a release.
270
+
271
+ [Unreleased]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.4.0...HEAD
272
+ [0.4.0]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.3.0...v0.4.0
273
+ [0.3.0]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.2.1...v0.3.0
274
+ [0.2.1]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.2.0...v0.2.1
275
+ [0.2.0]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.1.0...v0.2.0
276
+ [0.1.0]: https://github.com/DiogoRibeiro7/DataExcept/releases/tag/v0.1.0
@@ -1,7 +1,7 @@
1
1
  cff-version: 1.2.0
2
2
  message: "If you use this software, please cite it using the following metadata."
3
3
  title: "DataExcept"
4
- version: "0.2.1"
4
+ version: "0.4.0"
5
5
  authors:
6
6
  - family-names: "Ribeiro"
7
7
  given-names: "Diogo"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DataExcept
3
- Version: 0.2.1
3
+ Version: 0.4.0
4
4
  Summary: A Python package providing structured, easily-extendable custom exception types.
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -41,12 +41,13 @@ Description-Content-Type: text/markdown
41
41
 
42
42
  ## 🎯 Key Features
43
43
 
44
- - **🏗️ Hierarchical Structure**: Catch specific errors or broad categories
45
- - **📊 Data Science Focused**: 98 exception classes covering ML pipelines, feature engineering, model training
46
- - **🔧 Production Ready**: Comprehensive logging helpers and error context
44
+ - **🏗️ Hierarchical Structure**: Catch one specific error, a whole domain, or everything via `DataExceptError`
45
+ - **📦 One Import**: Every exception is available from `dataexcept` directly, or from its domain module — same objects either way
46
+ - **📊 Data Science Focused**: 99 exception classes covering ML pipelines, feature engineering, model training
47
+ - **🔧 Production Ready**: Logging helpers, error context, and exceptions that survive a process boundary intact
47
48
  - **📚 Academic Quality**: Proper documentation, type hints, and citation support
48
49
  - **🐍 Python 3.10+**: Modern Python with full type safety
49
- - **🧪 Well Tested**: Broad test suite with comprehensive edge case handling (see the coverage badge above)
50
+ - **🧪 Well Tested**: 690+ tests at 92% branch coverage of the package, gated in CI
50
51
 
51
52
  ## 📦 Quick Installation
52
53
 
@@ -67,8 +68,7 @@ poetry install
67
68
  ### Basic Usage
68
69
 
69
70
  ```python
70
- from dataexcept import ValidationError
71
- from dataexcept.datascience_exceptions import DataLoadingError, ModelTrainingError
71
+ from dataexcept import DataLoadingError, ModelTrainingError, ValidationError
72
72
  import pandas as pd
73
73
 
74
74
  # Data validation with context
@@ -105,8 +105,7 @@ def load_dataset(file_path: str) -> pd.DataFrame:
105
105
  ### Exception Hierarchies
106
106
 
107
107
  ```python
108
- from dataexcept import JobError
109
- from dataexcept.datascience_exceptions import ModelTrainingError, ConvergenceError
108
+ from dataexcept import ConvergenceError, DataExceptError, ModelTrainingError
110
109
 
111
110
  try:
112
111
  # Your ML pipeline
@@ -119,8 +118,8 @@ except ModelTrainingError:
119
118
  # Handle any training-related error
120
119
  logger.error("Training failed, falling back to simpler model")
121
120
  train_simple_model()
122
- except JobError:
123
- # Handle any job-related error
121
+ except DataExceptError:
122
+ # Handle anything else DataExcept raised
124
123
  logger.error("Job failed, notifying administrators")
125
124
  send_alert()
126
125
  ```
@@ -214,7 +213,7 @@ except Exception as exc:
214
213
  ### Command Line Interface
215
214
 
216
215
  ```bash
217
- # List every exception class the package exports (98 of them, alphabetically)
216
+ # List every exception class the package exports (99 of them, alphabetically)
218
217
  $ dataexcept list
219
218
  ApiError
220
219
  AuthenticationError
@@ -225,7 +224,7 @@ BiasDetectionError
225
224
 
226
225
  # Check version
227
226
  $ dataexcept --version
228
- dataexcept 0.2.1
227
+ dataexcept 0.4.0
229
228
  ```
230
229
 
231
230
  ## 🎯 Use Cases
@@ -375,7 +374,7 @@ If you use DataExcept in your research, please cite it:
375
374
  author = {Ribeiro, Diogo},
376
375
  title = {DataExcept: Structured Exception Handling for Data Science},
377
376
  url = {https://github.com/DiogoRibeiro7/DataExcept},
378
- version = {0.2.1},
377
+ version = {0.4.0},
379
378
  year = {2026},
380
379
  publisher = {GitHub}
381
380
  }
@@ -15,12 +15,13 @@
15
15
 
16
16
  ## 🎯 Key Features
17
17
 
18
- - **🏗️ Hierarchical Structure**: Catch specific errors or broad categories
19
- - **📊 Data Science Focused**: 98 exception classes covering ML pipelines, feature engineering, model training
20
- - **🔧 Production Ready**: Comprehensive logging helpers and error context
18
+ - **🏗️ Hierarchical Structure**: Catch one specific error, a whole domain, or everything via `DataExceptError`
19
+ - **📦 One Import**: Every exception is available from `dataexcept` directly, or from its domain module — same objects either way
20
+ - **📊 Data Science Focused**: 99 exception classes covering ML pipelines, feature engineering, model training
21
+ - **🔧 Production Ready**: Logging helpers, error context, and exceptions that survive a process boundary intact
21
22
  - **📚 Academic Quality**: Proper documentation, type hints, and citation support
22
23
  - **🐍 Python 3.10+**: Modern Python with full type safety
23
- - **🧪 Well Tested**: Broad test suite with comprehensive edge case handling (see the coverage badge above)
24
+ - **🧪 Well Tested**: 690+ tests at 92% branch coverage of the package, gated in CI
24
25
 
25
26
  ## 📦 Quick Installation
26
27
 
@@ -41,8 +42,7 @@ poetry install
41
42
  ### Basic Usage
42
43
 
43
44
  ```python
44
- from dataexcept import ValidationError
45
- from dataexcept.datascience_exceptions import DataLoadingError, ModelTrainingError
45
+ from dataexcept import DataLoadingError, ModelTrainingError, ValidationError
46
46
  import pandas as pd
47
47
 
48
48
  # Data validation with context
@@ -79,8 +79,7 @@ def load_dataset(file_path: str) -> pd.DataFrame:
79
79
  ### Exception Hierarchies
80
80
 
81
81
  ```python
82
- from dataexcept import JobError
83
- from dataexcept.datascience_exceptions import ModelTrainingError, ConvergenceError
82
+ from dataexcept import ConvergenceError, DataExceptError, ModelTrainingError
84
83
 
85
84
  try:
86
85
  # Your ML pipeline
@@ -93,8 +92,8 @@ except ModelTrainingError:
93
92
  # Handle any training-related error
94
93
  logger.error("Training failed, falling back to simpler model")
95
94
  train_simple_model()
96
- except JobError:
97
- # Handle any job-related error
95
+ except DataExceptError:
96
+ # Handle anything else DataExcept raised
98
97
  logger.error("Job failed, notifying administrators")
99
98
  send_alert()
100
99
  ```
@@ -188,7 +187,7 @@ except Exception as exc:
188
187
  ### Command Line Interface
189
188
 
190
189
  ```bash
191
- # List every exception class the package exports (98 of them, alphabetically)
190
+ # List every exception class the package exports (99 of them, alphabetically)
192
191
  $ dataexcept list
193
192
  ApiError
194
193
  AuthenticationError
@@ -199,7 +198,7 @@ BiasDetectionError
199
198
 
200
199
  # Check version
201
200
  $ dataexcept --version
202
- dataexcept 0.2.1
201
+ dataexcept 0.4.0
203
202
  ```
204
203
 
205
204
  ## 🎯 Use Cases
@@ -349,7 +348,7 @@ If you use DataExcept in your research, please cite it:
349
348
  author = {Ribeiro, Diogo},
350
349
  title = {DataExcept: Structured Exception Handling for Data Science},
351
350
  url = {https://github.com/DiogoRibeiro7/DataExcept},
352
- version = {0.2.1},
351
+ version = {0.4.0},
353
352
  year = {2026},
354
353
  publisher = {GitHub}
355
354
  }