DataExcept 0.1.0__tar.gz → 0.2.1__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.
- dataexcept-0.2.1/CHANGELOG.md +132 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/CITATION.cff +2 -2
- {dataexcept-0.1.0 → dataexcept-0.2.1}/PKG-INFO +23 -21
- {dataexcept-0.1.0 → dataexcept-0.2.1}/README.md +20 -17
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/__init__.py +18 -5
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/__main__.py +13 -2
- dataexcept-0.2.1/dataexcept/_deprecation.py +38 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/datascience_exceptions/__init__.py +13 -2
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/datascience_exceptions/operations.py +2 -2
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/exceptions/__init__.py +18 -4
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/exceptions/external.py +2 -2
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/job_exceptions.py +18 -6
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/logging_helpers.py +7 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/pipeline_exceptions.py +13 -2
- {dataexcept-0.1.0 → dataexcept-0.2.1}/pyproject.toml +40 -23
- dataexcept-0.1.0/CHANGELOG.md +0 -42
- {dataexcept-0.1.0 → dataexcept-0.2.1}/LICENSE +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/database_exceptions.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/dataengineering_exceptions.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/datascience_exceptions/base.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/datascience_exceptions/ingestion.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/datascience_exceptions/training.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/exceptions/authentication.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/exceptions/base.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/exceptions/configuration.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/exceptions/lifecycle.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/exceptions/notification.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/exceptions/parsing.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/exceptions/scheduling.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/exceptions/validation.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/io_exceptions.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/network_exceptions.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/pandas_exceptions.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/py.typed +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.1}/dataexcept/security_exceptions.py +0 -0
|
@@ -0,0 +1,132 @@
|
|
|
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.2.1] - 2026-08-24
|
|
11
|
+
|
|
12
|
+
Documentation and CLI fixes. 0.2.0's README is what PyPI renders as the
|
|
13
|
+
project description, and its quick-start example did not run.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- `python -m dataexcept --version` reported `__main__.py` as the program name
|
|
18
|
+
instead of `dataexcept`, because argparse defaults `prog` to `sys.argv[0]`.
|
|
19
|
+
- `dataexcept list` imported the deprecated `job_exceptions` shim to build its
|
|
20
|
+
output, so it emitted a `DeprecationWarning` at anyone who merely wanted to
|
|
21
|
+
see what the package offers, and it advertised `ConnectionError` and
|
|
22
|
+
`TimeoutError` alongside their replacements. Deprecated modules are now
|
|
23
|
+
skipped; the listing is 98 names, matching the classes the package defines.
|
|
24
|
+
- README's quick-start example began `from dataexcept import ValidationError,
|
|
25
|
+
ModelTrainingError`, which raises `ImportError` — `ModelTrainingError` is in
|
|
26
|
+
`dataexcept.datascience_exceptions` and is not re-exported at the top level.
|
|
27
|
+
- `docs/advanced_usage.md` taught `from dataexcept.job_exceptions import
|
|
28
|
+
JobError`, the deprecated path.
|
|
29
|
+
- README's comparison table showed exception messages without the
|
|
30
|
+
`[ClassName]` prefix the classes actually emit, its sample `dataexcept list`
|
|
31
|
+
output did not match the real alphabetical listing, its exception count and
|
|
32
|
+
CLI version were stale, and its end-to-end example used `np.log` without
|
|
33
|
+
importing numpy.
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- Tests that read the documentation: every `from dataexcept... import ...` in
|
|
38
|
+
README and `docs/` must resolve, no example may import a deprecated module,
|
|
39
|
+
and the README's exception count must match the package. Checked that these
|
|
40
|
+
fail when the original defects are reintroduced.
|
|
41
|
+
|
|
42
|
+
## [0.2.0] - 2026-08-24
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- **`ConnectionError` is now `ServiceConnectionError`, and `TimeoutError` is
|
|
47
|
+
now `OperationTimeoutError`.** The old names shadowed Python builtins without
|
|
48
|
+
inheriting from them, so after `from dataexcept import ConnectionError` an
|
|
49
|
+
`except ConnectionError:` in that module silently stopped catching real
|
|
50
|
+
socket failures.
|
|
51
|
+
- **`datascience_exceptions.SerializationError` is now
|
|
52
|
+
`ModelSerializationError`**, and **`pipeline_exceptions.FeatureEngineeringError`
|
|
53
|
+
is now `FeaturePreprocessingError`.** Each of those names previously referred
|
|
54
|
+
to two different classes in different modules, so catching one silently
|
|
55
|
+
missed the other.
|
|
56
|
+
- Project metadata moved from Poetry's `[tool.poetry]` table to the standard
|
|
57
|
+
PEP 621 `[project]` table, clearing every `poetry check` deprecation. The
|
|
58
|
+
license is now an SPDX expression (PEP 639), so the built metadata carries
|
|
59
|
+
`License-Expression: MIT` and the redundant license classifier is gone.
|
|
60
|
+
Wheel and sdist contents are otherwise unchanged.
|
|
61
|
+
- `dataexcept.job_exceptions` now names its removal version, 1.0.0, in both the
|
|
62
|
+
warning and the module docstring.
|
|
63
|
+
|
|
64
|
+
### Deprecated
|
|
65
|
+
|
|
66
|
+
- `ConnectionError`, `TimeoutError`, `datascience_exceptions.SerializationError`
|
|
67
|
+
and `pipeline_exceptions.FeatureEngineeringError`. All four still resolve, to
|
|
68
|
+
the **same class object** as their replacement, so existing `except` clauses
|
|
69
|
+
keep working; touching one emits a `DeprecationWarning` naming the
|
|
70
|
+
replacement and 1.0.0 as the removal. Importing the package does not warn.
|
|
71
|
+
Find remaining uses with `python -W error::DeprecationWarning -m pytest`.
|
|
72
|
+
|
|
73
|
+
### Added
|
|
74
|
+
|
|
75
|
+
- A published [API stability policy](https://diogoribeiro7.github.io/DataExcept/stability/)
|
|
76
|
+
stating what is public, what each kind of change costs in version terms, the
|
|
77
|
+
deprecation process, and how to migrate off the 0.2.0 renames.
|
|
78
|
+
- Security scanning: CodeQL, and pip-audit against the runtime and
|
|
79
|
+
documentation dependency sets, on push, pull request and weekly — advisories
|
|
80
|
+
are published against code that has not changed. Pull requests also get a
|
|
81
|
+
dependency review failing at moderate severity.
|
|
82
|
+
- Complexity and security linting via ruff's mccabe (`C90`) and flake8-bandit
|
|
83
|
+
(`S`) rule sets, so neither needs a separate tool. Complexity is capped at 8;
|
|
84
|
+
the highest score in the package is 6.
|
|
85
|
+
- A regression guard that fails if any exported name ever shadows a builtin
|
|
86
|
+
again.
|
|
87
|
+
- `__all__` on `dataexcept.logging_helpers`, the one public module without one.
|
|
88
|
+
|
|
89
|
+
### Fixed
|
|
90
|
+
|
|
91
|
+
- `dataexcept.__version__` and `tests/test_version.py` read the version out of
|
|
92
|
+
`pyproject.toml` when the package is not installed, and were still looking in
|
|
93
|
+
`[tool.poetry]`. They now read `[project]`.
|
|
94
|
+
- `examples/example_usage.py` raised `TimeoutError` with keyword arguments the
|
|
95
|
+
builtin does not accept — a live instance of the shadowing hazard.
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
## [0.1.0] - 2026-08-24
|
|
99
|
+
|
|
100
|
+
First public release.
|
|
101
|
+
|
|
102
|
+
### Added
|
|
103
|
+
|
|
104
|
+
- Hierarchical exception classes for data science, machine learning and data
|
|
105
|
+
engineering workflows. Catch a specific failure or a broad category, and get
|
|
106
|
+
a message that names the value that caused it rather than a bare
|
|
107
|
+
`ValueError`.
|
|
108
|
+
- Domain modules for validation, configuration, authentication, parsing,
|
|
109
|
+
serialization, scheduling, notification, lifecycle and external-service
|
|
110
|
+
errors, plus dedicated pandas, database, network, I/O, pipeline and security
|
|
111
|
+
exception groups.
|
|
112
|
+
- `dataexcept.logging_helpers` with `log_exception`, `log_and_raise` and
|
|
113
|
+
`log_then_raise`, for logging exceptions with structured context and
|
|
114
|
+
re-raising without losing the traceback.
|
|
115
|
+
- A `dataexcept` command-line entry point that lists the exported exception
|
|
116
|
+
classes and reports the installed version.
|
|
117
|
+
- A `py.typed` marker, backed by a mypy-clean codebase that CI enforces, so
|
|
118
|
+
downstream type checkers get annotations that are actually correct.
|
|
119
|
+
- Documentation at
|
|
120
|
+
[diogoribeiro7.github.io/DataExcept](https://diogoribeiro7.github.io/DataExcept/),
|
|
121
|
+
including an API reference generated from the docstrings.
|
|
122
|
+
|
|
123
|
+
### Notes
|
|
124
|
+
|
|
125
|
+
- Supports Python 3.10 through 3.13.
|
|
126
|
+
- Published to PyPI via OIDC trusted publishing; no long-lived API token is
|
|
127
|
+
involved in a release.
|
|
128
|
+
|
|
129
|
+
[Unreleased]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.2.1...HEAD
|
|
130
|
+
[0.2.1]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.2.0...v0.2.1
|
|
131
|
+
[0.2.0]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.1.0...v0.2.0
|
|
132
|
+
[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.1
|
|
4
|
+
version: "0.2.1"
|
|
5
5
|
authors:
|
|
6
6
|
- family-names: "Ribeiro"
|
|
7
7
|
given-names: "Diogo"
|
|
@@ -11,4 +11,4 @@ authors:
|
|
|
11
11
|
type: software
|
|
12
12
|
url: "https://github.com/DiogoRibeiro7/DataExcept"
|
|
13
13
|
repository-code: "https://github.com/DiogoRibeiro7/DataExcept"
|
|
14
|
-
date-released: "
|
|
14
|
+
date-released: "2026-08-24"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DataExcept
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A Python package providing structured, easily-extendable custom exception types.
|
|
5
|
-
License: MIT
|
|
5
|
+
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Keywords: exceptions,errors,logging
|
|
8
8
|
Author: Diogo Ribeiro
|
|
@@ -10,13 +10,12 @@ Author-email: dfr@esmad.ipp.pt
|
|
|
10
10
|
Maintainer: Diogo Ribeiro
|
|
11
11
|
Maintainer-email: diogo.debastos.ribeiro@gmail.com
|
|
12
12
|
Requires-Python: >=3.10,<3.14
|
|
13
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
14
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
19
|
Requires-Dist: tomli ; python_version < "3.11"
|
|
21
20
|
Project-URL: Changelog, https://github.com/DiogoRibeiro7/DataExcept/releases
|
|
22
21
|
Project-URL: Documentation, https://diogoribeiro7.github.io/DataExcept/
|
|
@@ -35,15 +34,15 @@ Description-Content-Type: text/markdown
|
|
|
35
34
|
|
|
36
35
|
❌ Without DataExcept | ✅ With DataExcept
|
|
37
36
|
------------------------------- | -------------------------------------------------------------------------------------
|
|
38
|
-
`ValueError: Invalid value` | `DataValidationError: Invalid value for 'age': -1`
|
|
39
|
-
`RuntimeError: Training failed` | `ConvergenceError: Model 'RandomForest' failed to converge after 100 iterations`
|
|
40
|
-
`Exception: Prediction error` | `ModelInferenceError: Inference failed for model 'CNN': CUDA out of memory`
|
|
41
|
-
`KeyError: column not found` | `MissingColumnError: Missing required column 'customer_id' in DataFrame 'sales_data'`
|
|
37
|
+
`ValueError: Invalid value` | `DataValidationError: [DataValidationError:age] Invalid value for 'age': -1`
|
|
38
|
+
`RuntimeError: Training failed` | `ConvergenceError: [ConvergenceError] Model 'RandomForest' failed to converge after 100 iterations`
|
|
39
|
+
`Exception: Prediction error` | `ModelInferenceError: [ModelInferenceError:CNN] Inference failed for model 'CNN': CUDA out of memory`
|
|
40
|
+
`KeyError: column not found` | `MissingColumnError: [MissingColumnError] Missing required column 'customer_id' in DataFrame 'sales_data'`
|
|
42
41
|
|
|
43
42
|
## 🎯 Key Features
|
|
44
43
|
|
|
45
44
|
- **🏗️ Hierarchical Structure**: Catch specific errors or broad categories
|
|
46
|
-
- **📊 Data Science Focused**:
|
|
45
|
+
- **📊 Data Science Focused**: 98 exception classes covering ML pipelines, feature engineering, model training
|
|
47
46
|
- **🔧 Production Ready**: Comprehensive logging helpers and error context
|
|
48
47
|
- **📚 Academic Quality**: Proper documentation, type hints, and citation support
|
|
49
48
|
- **🐍 Python 3.10+**: Modern Python with full type safety
|
|
@@ -68,8 +67,8 @@ poetry install
|
|
|
68
67
|
### Basic Usage
|
|
69
68
|
|
|
70
69
|
```python
|
|
71
|
-
from dataexcept import ValidationError
|
|
72
|
-
from dataexcept.datascience_exceptions import DataLoadingError
|
|
70
|
+
from dataexcept import ValidationError
|
|
71
|
+
from dataexcept.datascience_exceptions import DataLoadingError, ModelTrainingError
|
|
73
72
|
import pandas as pd
|
|
74
73
|
|
|
75
74
|
# Data validation with context
|
|
@@ -215,17 +214,18 @@ except Exception as exc:
|
|
|
215
214
|
### Command Line Interface
|
|
216
215
|
|
|
217
216
|
```bash
|
|
218
|
-
# List
|
|
217
|
+
# List every exception class the package exports (98 of them, alphabetically)
|
|
219
218
|
$ dataexcept list
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
219
|
+
ApiError
|
|
220
|
+
AuthenticationError
|
|
221
|
+
AuthorizationError
|
|
222
|
+
BatchProcessingError
|
|
223
|
+
BiasDetectionError
|
|
224
|
+
...
|
|
225
225
|
|
|
226
226
|
# Check version
|
|
227
227
|
$ dataexcept --version
|
|
228
|
-
dataexcept 0.1
|
|
228
|
+
dataexcept 0.2.1
|
|
229
229
|
```
|
|
230
230
|
|
|
231
231
|
## 🎯 Use Cases
|
|
@@ -256,6 +256,7 @@ dataexcept 0.1.0
|
|
|
256
256
|
"""
|
|
257
257
|
Complete ML pipeline with DataExcept error handling
|
|
258
258
|
"""
|
|
259
|
+
import numpy as np
|
|
259
260
|
import pandas as pd
|
|
260
261
|
from sklearn.ensemble import RandomForestClassifier
|
|
261
262
|
from dataexcept import ValidationError
|
|
@@ -360,6 +361,7 @@ through [SECURITY.md](SECURITY.md), not the public issue tracker.
|
|
|
360
361
|
|
|
361
362
|
- **Full Documentation**: [diogoribeiro7.github.io/DataExcept](https://diogoribeiro7.github.io/DataExcept/)
|
|
362
363
|
- **API Reference**: [API Docs](https://diogoribeiro7.github.io/DataExcept/api/)
|
|
364
|
+
- **API Stability**: [What is public and what may change](https://diogoribeiro7.github.io/DataExcept/stability/)
|
|
363
365
|
- **Advanced Usage**: [Advanced Guide](https://diogoribeiro7.github.io/DataExcept/advanced_usage/)
|
|
364
366
|
- **CLI Reference**: [CLI Guide](https://diogoribeiro7.github.io/DataExcept/cli/)
|
|
365
367
|
- **Changelog**: [CHANGELOG.md](CHANGELOG.md)
|
|
@@ -369,12 +371,12 @@ through [SECURITY.md](SECURITY.md), not the public issue tracker.
|
|
|
369
371
|
If you use DataExcept in your research, please cite it:
|
|
370
372
|
|
|
371
373
|
```bibtex
|
|
372
|
-
@software{
|
|
374
|
+
@software{ribeiro_dataexcept_2026,
|
|
373
375
|
author = {Ribeiro, Diogo},
|
|
374
376
|
title = {DataExcept: Structured Exception Handling for Data Science},
|
|
375
377
|
url = {https://github.com/DiogoRibeiro7/DataExcept},
|
|
376
|
-
version = {0.1
|
|
377
|
-
year = {
|
|
378
|
+
version = {0.2.1},
|
|
379
|
+
year = {2026},
|
|
378
380
|
publisher = {GitHub}
|
|
379
381
|
}
|
|
380
382
|
```
|
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
❌ Without DataExcept | ✅ With DataExcept
|
|
10
10
|
------------------------------- | -------------------------------------------------------------------------------------
|
|
11
|
-
`ValueError: Invalid value` | `DataValidationError: Invalid value for 'age': -1`
|
|
12
|
-
`RuntimeError: Training failed` | `ConvergenceError: Model 'RandomForest' failed to converge after 100 iterations`
|
|
13
|
-
`Exception: Prediction error` | `ModelInferenceError: Inference failed for model 'CNN': CUDA out of memory`
|
|
14
|
-
`KeyError: column not found` | `MissingColumnError: Missing required column 'customer_id' in DataFrame 'sales_data'`
|
|
11
|
+
`ValueError: Invalid value` | `DataValidationError: [DataValidationError:age] Invalid value for 'age': -1`
|
|
12
|
+
`RuntimeError: Training failed` | `ConvergenceError: [ConvergenceError] Model 'RandomForest' failed to converge after 100 iterations`
|
|
13
|
+
`Exception: Prediction error` | `ModelInferenceError: [ModelInferenceError:CNN] Inference failed for model 'CNN': CUDA out of memory`
|
|
14
|
+
`KeyError: column not found` | `MissingColumnError: [MissingColumnError] Missing required column 'customer_id' in DataFrame 'sales_data'`
|
|
15
15
|
|
|
16
16
|
## 🎯 Key Features
|
|
17
17
|
|
|
18
18
|
- **🏗️ Hierarchical Structure**: Catch specific errors or broad categories
|
|
19
|
-
- **📊 Data Science Focused**:
|
|
19
|
+
- **📊 Data Science Focused**: 98 exception classes covering ML pipelines, feature engineering, model training
|
|
20
20
|
- **🔧 Production Ready**: Comprehensive logging helpers and error context
|
|
21
21
|
- **📚 Academic Quality**: Proper documentation, type hints, and citation support
|
|
22
22
|
- **🐍 Python 3.10+**: Modern Python with full type safety
|
|
@@ -41,8 +41,8 @@ poetry install
|
|
|
41
41
|
### Basic Usage
|
|
42
42
|
|
|
43
43
|
```python
|
|
44
|
-
from dataexcept import ValidationError
|
|
45
|
-
from dataexcept.datascience_exceptions import DataLoadingError
|
|
44
|
+
from dataexcept import ValidationError
|
|
45
|
+
from dataexcept.datascience_exceptions import DataLoadingError, ModelTrainingError
|
|
46
46
|
import pandas as pd
|
|
47
47
|
|
|
48
48
|
# Data validation with context
|
|
@@ -188,17 +188,18 @@ except Exception as exc:
|
|
|
188
188
|
### Command Line Interface
|
|
189
189
|
|
|
190
190
|
```bash
|
|
191
|
-
# List
|
|
191
|
+
# List every exception class the package exports (98 of them, alphabetically)
|
|
192
192
|
$ dataexcept list
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
193
|
+
ApiError
|
|
194
|
+
AuthenticationError
|
|
195
|
+
AuthorizationError
|
|
196
|
+
BatchProcessingError
|
|
197
|
+
BiasDetectionError
|
|
198
|
+
...
|
|
198
199
|
|
|
199
200
|
# Check version
|
|
200
201
|
$ dataexcept --version
|
|
201
|
-
dataexcept 0.1
|
|
202
|
+
dataexcept 0.2.1
|
|
202
203
|
```
|
|
203
204
|
|
|
204
205
|
## 🎯 Use Cases
|
|
@@ -229,6 +230,7 @@ dataexcept 0.1.0
|
|
|
229
230
|
"""
|
|
230
231
|
Complete ML pipeline with DataExcept error handling
|
|
231
232
|
"""
|
|
233
|
+
import numpy as np
|
|
232
234
|
import pandas as pd
|
|
233
235
|
from sklearn.ensemble import RandomForestClassifier
|
|
234
236
|
from dataexcept import ValidationError
|
|
@@ -333,6 +335,7 @@ through [SECURITY.md](SECURITY.md), not the public issue tracker.
|
|
|
333
335
|
|
|
334
336
|
- **Full Documentation**: [diogoribeiro7.github.io/DataExcept](https://diogoribeiro7.github.io/DataExcept/)
|
|
335
337
|
- **API Reference**: [API Docs](https://diogoribeiro7.github.io/DataExcept/api/)
|
|
338
|
+
- **API Stability**: [What is public and what may change](https://diogoribeiro7.github.io/DataExcept/stability/)
|
|
336
339
|
- **Advanced Usage**: [Advanced Guide](https://diogoribeiro7.github.io/DataExcept/advanced_usage/)
|
|
337
340
|
- **CLI Reference**: [CLI Guide](https://diogoribeiro7.github.io/DataExcept/cli/)
|
|
338
341
|
- **Changelog**: [CHANGELOG.md](CHANGELOG.md)
|
|
@@ -342,12 +345,12 @@ through [SECURITY.md](SECURITY.md), not the public issue tracker.
|
|
|
342
345
|
If you use DataExcept in your research, please cite it:
|
|
343
346
|
|
|
344
347
|
```bibtex
|
|
345
|
-
@software{
|
|
348
|
+
@software{ribeiro_dataexcept_2026,
|
|
346
349
|
author = {Ribeiro, Diogo},
|
|
347
350
|
title = {DataExcept: Structured Exception Handling for Data Science},
|
|
348
351
|
url = {https://github.com/DiogoRibeiro7/DataExcept},
|
|
349
|
-
version = {0.1
|
|
350
|
-
year = {
|
|
352
|
+
version = {0.2.1},
|
|
353
|
+
year = {2026},
|
|
351
354
|
publisher = {GitHub}
|
|
352
355
|
}
|
|
353
356
|
```
|
|
@@ -28,11 +28,11 @@ from . import (
|
|
|
28
28
|
pipeline_exceptions,
|
|
29
29
|
security_exceptions,
|
|
30
30
|
)
|
|
31
|
+
from ._deprecation import resolve_deprecated
|
|
31
32
|
from .exceptions import ( # noqa: F401
|
|
32
33
|
AuthenticationError,
|
|
33
34
|
AuthorizationError,
|
|
34
35
|
ConfigurationError,
|
|
35
|
-
ConnectionError,
|
|
36
36
|
CronExpressionError,
|
|
37
37
|
DependencyError,
|
|
38
38
|
DeserializationError,
|
|
@@ -40,22 +40,27 @@ from .exceptions import ( # noqa: F401
|
|
|
40
40
|
JobCancellationError,
|
|
41
41
|
JobError,
|
|
42
42
|
NotificationError,
|
|
43
|
+
OperationTimeoutError,
|
|
43
44
|
ParsingError,
|
|
44
45
|
ResourceNotFoundError,
|
|
45
46
|
ScheduleConflictError,
|
|
46
47
|
SerializationError,
|
|
47
|
-
|
|
48
|
+
ServiceConnectionError,
|
|
48
49
|
ValidationError,
|
|
49
50
|
WebhookError,
|
|
50
51
|
)
|
|
51
|
-
from .logging_helpers import
|
|
52
|
+
from .logging_helpers import (
|
|
53
|
+
log_and_raise,
|
|
54
|
+
log_exception,
|
|
55
|
+
log_then_raise,
|
|
56
|
+
)
|
|
52
57
|
|
|
53
58
|
try:
|
|
54
59
|
__version__ = metadata.version("DataExcept")
|
|
55
60
|
except metadata.PackageNotFoundError: # pragma: no cover - fallback during dev
|
|
56
61
|
_root = Path(__file__).resolve().parents[1]
|
|
57
62
|
with open(_root / "pyproject.toml", "rb") as _f:
|
|
58
|
-
__version__ = tomllib.load(_f)["
|
|
63
|
+
__version__ = tomllib.load(_f)["project"]["version"]
|
|
59
64
|
|
|
60
65
|
__all__ = list(_exceptions.__all__) + [
|
|
61
66
|
"datascience_exceptions",
|
|
@@ -73,9 +78,17 @@ __all__ = list(_exceptions.__all__) + [
|
|
|
73
78
|
]
|
|
74
79
|
|
|
75
80
|
|
|
81
|
+
#: Renamed in 0.2.0 because they shadowed Python builtins without inheriting
|
|
82
|
+
#: from them. Each alias is the same class object as its replacement.
|
|
83
|
+
_DEPRECATED_ALIASES = {
|
|
84
|
+
"ConnectionError": ServiceConnectionError,
|
|
85
|
+
"TimeoutError": OperationTimeoutError,
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
76
89
|
def __getattr__(name: str) -> Any:
|
|
77
90
|
if name == "job_exceptions":
|
|
78
91
|
module = import_module("dataexcept.job_exceptions")
|
|
79
92
|
globals()[name] = module
|
|
80
93
|
return module
|
|
81
|
-
|
|
94
|
+
return resolve_deprecated(__name__, _DEPRECATED_ALIASES, name)
|
|
@@ -12,9 +12,14 @@ from typing import Iterable
|
|
|
12
12
|
from . import __path__ as _PKG_PATH
|
|
13
13
|
from . import __version__
|
|
14
14
|
|
|
15
|
+
#: Deprecated compatibility shims. Listing these would advertise names that are
|
|
16
|
+
#: scheduled for removal, and importing them emits a DeprecationWarning at
|
|
17
|
+
#: anyone who merely wanted to see what the package offers.
|
|
18
|
+
_DEPRECATED_MODULES = frozenset({"dataexcept.job_exceptions"})
|
|
19
|
+
|
|
15
20
|
|
|
16
21
|
def _iter_exception_modules() -> Iterable[ModuleType]:
|
|
17
|
-
"""Yield every submodule that explicitly defines ``__all__``."""
|
|
22
|
+
"""Yield every non-deprecated submodule that explicitly defines ``__all__``."""
|
|
18
23
|
allowed_suffixes = ("exceptions", "_exceptions")
|
|
19
24
|
|
|
20
25
|
for module_info in pkgutil.walk_packages(
|
|
@@ -22,6 +27,8 @@ def _iter_exception_modules() -> Iterable[ModuleType]:
|
|
|
22
27
|
):
|
|
23
28
|
if not module_info.name.endswith(allowed_suffixes):
|
|
24
29
|
continue
|
|
30
|
+
if module_info.name in _DEPRECATED_MODULES:
|
|
31
|
+
continue
|
|
25
32
|
try:
|
|
26
33
|
module = import_module(module_info.name)
|
|
27
34
|
except ImportError as exc: # pragma: no cover - defensive guard
|
|
@@ -53,7 +60,11 @@ def _list_exceptions() -> None:
|
|
|
53
60
|
|
|
54
61
|
def main(argv: list[str] | None = None) -> None:
|
|
55
62
|
"""Entry point for the ``dataexcept`` command."""
|
|
56
|
-
parser = argparse.ArgumentParser(
|
|
63
|
+
parser = argparse.ArgumentParser(
|
|
64
|
+
# Without this, `python -m dataexcept --version` reports "__main__.py".
|
|
65
|
+
prog="dataexcept",
|
|
66
|
+
description="Utilities for DataExcept",
|
|
67
|
+
)
|
|
57
68
|
parser.add_argument(
|
|
58
69
|
"--version",
|
|
59
70
|
action="version",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Internal support for names that have been renamed.
|
|
2
|
+
|
|
3
|
+
A rename keeps the old name working as an alias bound to the *same* class
|
|
4
|
+
object, so an existing ``except OldName:`` keeps catching exactly what it
|
|
5
|
+
caught before -- the alias is not a separate class.
|
|
6
|
+
|
|
7
|
+
Access goes through a PEP 562 module ``__getattr__`` rather than a plain
|
|
8
|
+
``OldName = NewName`` assignment, because an assignment cannot warn. This is
|
|
9
|
+
private; see the stability policy for the user-facing contract.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import warnings
|
|
15
|
+
from typing import Any, Mapping
|
|
16
|
+
|
|
17
|
+
#: Version in which every currently deprecated alias is removed.
|
|
18
|
+
REMOVED_IN = "1.0.0"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def resolve_deprecated(module: str, aliases: Mapping[str, Any], name: str) -> Any:
|
|
22
|
+
"""Return the target of the deprecated *name*, warning first.
|
|
23
|
+
|
|
24
|
+
Raises ``AttributeError`` for anything not in *aliases*, so normal
|
|
25
|
+
attribute lookup on the module keeps behaving normally.
|
|
26
|
+
"""
|
|
27
|
+
try:
|
|
28
|
+
target = aliases[name]
|
|
29
|
+
except KeyError:
|
|
30
|
+
raise AttributeError(f"module {module!r} has no attribute {name!r}") from None
|
|
31
|
+
warnings.warn(
|
|
32
|
+
f"{module}.{name} is deprecated and will be removed in {REMOVED_IN}; "
|
|
33
|
+
f"use {target.__name__} instead",
|
|
34
|
+
DeprecationWarning,
|
|
35
|
+
# resolve_deprecated -> __getattr__ -> the caller we want to blame.
|
|
36
|
+
stacklevel=3,
|
|
37
|
+
)
|
|
38
|
+
return target
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"""Custom exceptions for data science workflows."""
|
|
2
2
|
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from .._deprecation import resolve_deprecated
|
|
3
6
|
from .base import DataScienceError
|
|
4
7
|
from .ingestion import (
|
|
5
8
|
DataAugmentationError,
|
|
@@ -18,8 +21,8 @@ from .operations import (
|
|
|
18
21
|
DataDriftError,
|
|
19
22
|
DataExportError,
|
|
20
23
|
DeploymentError,
|
|
24
|
+
ModelSerializationError,
|
|
21
25
|
ResourceLimitError,
|
|
22
|
-
SerializationError,
|
|
23
26
|
)
|
|
24
27
|
from .training import (
|
|
25
28
|
BiasDetectionError,
|
|
@@ -59,7 +62,7 @@ __all__ = [
|
|
|
59
62
|
"HyperparameterError",
|
|
60
63
|
"ModelEvaluationError",
|
|
61
64
|
"PredictionError",
|
|
62
|
-
"
|
|
65
|
+
"ModelSerializationError",
|
|
63
66
|
"DeploymentError",
|
|
64
67
|
"DataDriftError",
|
|
65
68
|
"ResourceLimitError",
|
|
@@ -83,3 +86,11 @@ __all__ = [
|
|
|
83
86
|
"FeatureScalingError",
|
|
84
87
|
"ModelCompatibilityError",
|
|
85
88
|
]
|
|
89
|
+
|
|
90
|
+
#: Renamed in 0.2.0: this named the same thing as
|
|
91
|
+
#: ``dataexcept.exceptions.SerializationError`` while being a different class.
|
|
92
|
+
_DEPRECATED_ALIASES = {"SerializationError": ModelSerializationError}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def __getattr__(name: str) -> Any:
|
|
96
|
+
return resolve_deprecated(__name__, _DEPRECATED_ALIASES, name)
|
|
@@ -7,7 +7,7 @@ from typing import Any, Optional
|
|
|
7
7
|
from .base import DataScienceError
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class
|
|
10
|
+
class ModelSerializationError(DataScienceError):
|
|
11
11
|
"""
|
|
12
12
|
Raised when saving or loading a model fails.
|
|
13
13
|
|
|
@@ -30,7 +30,7 @@ class SerializationError(DataScienceError):
|
|
|
30
30
|
super().__init__(message)
|
|
31
31
|
|
|
32
32
|
def __str__(self) -> str:
|
|
33
|
-
return f"[
|
|
33
|
+
return f"[ModelSerializationError] {self.path}"
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class DeploymentError(DataScienceError):
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# __init__.py
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from .._deprecation import resolve_deprecated
|
|
2
5
|
from .authentication import AuthenticationError, AuthorizationError
|
|
3
6
|
from .base import JobError
|
|
4
7
|
from .configuration import ConfigurationError
|
|
5
8
|
from .external import (
|
|
6
|
-
ConnectionError,
|
|
7
9
|
DependencyError,
|
|
10
|
+
OperationTimeoutError,
|
|
8
11
|
ResourceNotFoundError,
|
|
9
|
-
|
|
12
|
+
ServiceConnectionError,
|
|
10
13
|
)
|
|
11
14
|
from .lifecycle import JobCancellationError
|
|
12
15
|
from .notification import EmailError, NotificationError, WebhookError
|
|
@@ -18,8 +21,8 @@ __all__ = [
|
|
|
18
21
|
"JobError",
|
|
19
22
|
"ValidationError",
|
|
20
23
|
"ConfigurationError",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
24
|
+
"ServiceConnectionError",
|
|
25
|
+
"OperationTimeoutError",
|
|
23
26
|
"ResourceNotFoundError",
|
|
24
27
|
"DependencyError",
|
|
25
28
|
"AuthenticationError",
|
|
@@ -34,3 +37,14 @@ __all__ = [
|
|
|
34
37
|
"WebhookError",
|
|
35
38
|
"JobCancellationError",
|
|
36
39
|
]
|
|
40
|
+
|
|
41
|
+
#: Renamed in 0.2.0 because they shadowed Python builtins without inheriting
|
|
42
|
+
#: from them. The alias is the same class object, so ``except`` keeps working.
|
|
43
|
+
_DEPRECATED_ALIASES = {
|
|
44
|
+
"ConnectionError": ServiceConnectionError,
|
|
45
|
+
"TimeoutError": OperationTimeoutError,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def __getattr__(name: str) -> Any:
|
|
50
|
+
return resolve_deprecated(__name__, _DEPRECATED_ALIASES, name)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from .base import JobError
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class ServiceConnectionError(JobError):
|
|
5
5
|
"""Raised when a connection to an external service fails."""
|
|
6
6
|
|
|
7
7
|
def __init__(self, service_name: str, original_exception: Exception | None = None):
|
|
@@ -13,7 +13,7 @@ class ConnectionError(JobError):
|
|
|
13
13
|
super().__init__(msg)
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
class
|
|
16
|
+
class OperationTimeoutError(JobError):
|
|
17
17
|
"""Raised when an operation exceeds its time limit."""
|
|
18
18
|
|
|
19
19
|
def __init__(self, operation: str, timeout: float):
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"""Backward compatible job-related exceptions.
|
|
2
2
|
|
|
3
|
+
.. deprecated:: 0.1.0
|
|
4
|
+
Use :mod:`dataexcept.exceptions` instead. This module is scheduled for
|
|
5
|
+
removal in 1.0.0; see the stability policy in the documentation.
|
|
6
|
+
|
|
3
7
|
This module re-exports the core job exceptions defined in
|
|
4
|
-
:mod:`dataexcept.exceptions`.
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
:mod:`dataexcept.exceptions`. Importing it emits a :class:`DeprecationWarning`.
|
|
9
|
+
Every name it exports is available from :mod:`dataexcept.exceptions` and from
|
|
10
|
+
the top-level :mod:`dataexcept` package, so the migration is a change of import
|
|
11
|
+
line only -- the classes are identical objects, not replacements, so existing
|
|
12
|
+
``except`` clauses keep working during the transition.
|
|
7
13
|
"""
|
|
8
14
|
|
|
9
15
|
from __future__ import annotations
|
|
@@ -14,7 +20,6 @@ from .exceptions import (
|
|
|
14
20
|
AuthenticationError,
|
|
15
21
|
AuthorizationError,
|
|
16
22
|
ConfigurationError,
|
|
17
|
-
ConnectionError,
|
|
18
23
|
CronExpressionError,
|
|
19
24
|
DependencyError,
|
|
20
25
|
DeserializationError,
|
|
@@ -22,15 +27,21 @@ from .exceptions import (
|
|
|
22
27
|
JobCancellationError,
|
|
23
28
|
JobError,
|
|
24
29
|
NotificationError,
|
|
30
|
+
OperationTimeoutError,
|
|
25
31
|
ParsingError,
|
|
26
32
|
ResourceNotFoundError,
|
|
27
33
|
ScheduleConflictError,
|
|
28
34
|
SerializationError,
|
|
29
|
-
|
|
35
|
+
ServiceConnectionError,
|
|
30
36
|
ValidationError,
|
|
31
37
|
WebhookError,
|
|
32
38
|
)
|
|
33
39
|
|
|
40
|
+
# This module is itself deprecated, so it binds the pre-0.2.0 names directly
|
|
41
|
+
# rather than going through the alias machinery and warning a second time.
|
|
42
|
+
ConnectionError = ServiceConnectionError
|
|
43
|
+
TimeoutError = OperationTimeoutError
|
|
44
|
+
|
|
34
45
|
__all__ = [
|
|
35
46
|
"JobError",
|
|
36
47
|
"ValidationError",
|
|
@@ -53,7 +64,8 @@ __all__ = [
|
|
|
53
64
|
]
|
|
54
65
|
|
|
55
66
|
warnings.warn(
|
|
56
|
-
"dataexcept.job_exceptions is deprecated
|
|
67
|
+
"dataexcept.job_exceptions is deprecated and will be removed in 1.0.0; "
|
|
68
|
+
"use dataexcept.exceptions instead",
|
|
57
69
|
DeprecationWarning,
|
|
58
70
|
stacklevel=2,
|
|
59
71
|
)
|
|
@@ -4,6 +4,8 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Any, Optional
|
|
6
6
|
|
|
7
|
+
from ._deprecation import resolve_deprecated
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
class PipelineError(Exception):
|
|
9
11
|
"""Base exception for pipeline errors."""
|
|
@@ -22,7 +24,7 @@ class PreprocessingError(PipelineError):
|
|
|
22
24
|
super().__init__(message)
|
|
23
25
|
|
|
24
26
|
|
|
25
|
-
class
|
|
27
|
+
class FeaturePreprocessingError(PreprocessingError):
|
|
26
28
|
"""Raised when feature engineering fails."""
|
|
27
29
|
|
|
28
30
|
def __init__(self, feature: str, reason: Optional[str] = None) -> None:
|
|
@@ -190,7 +192,7 @@ class DataFetchError(PipelineError):
|
|
|
190
192
|
__all__ = [
|
|
191
193
|
"PipelineError",
|
|
192
194
|
"PreprocessingError",
|
|
193
|
-
"
|
|
195
|
+
"FeaturePreprocessingError",
|
|
194
196
|
"StorageError",
|
|
195
197
|
"PipelineNotificationError",
|
|
196
198
|
"RetryLimitExceededError",
|
|
@@ -203,3 +205,12 @@ __all__ = [
|
|
|
203
205
|
"TypeCheckError",
|
|
204
206
|
"DataFetchError",
|
|
205
207
|
]
|
|
208
|
+
|
|
209
|
+
#: Renamed in 0.2.0: this named the same thing as
|
|
210
|
+
#: ``dataexcept.datascience_exceptions.FeatureEngineeringError`` while being a
|
|
211
|
+
#: different class, so catching one silently missed the other.
|
|
212
|
+
_DEPRECATED_ALIASES = {"FeatureEngineeringError": FeaturePreprocessingError}
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def __getattr__(name: str) -> Any:
|
|
216
|
+
return resolve_deprecated(__name__, _DEPRECATED_ALIASES, name)
|
|
@@ -1,24 +1,15 @@
|
|
|
1
|
-
[
|
|
1
|
+
[project]
|
|
2
2
|
name = "DataExcept"
|
|
3
|
-
version = "0.1
|
|
3
|
+
version = "0.2.1"
|
|
4
4
|
description = "A Python package providing structured, easily-extendable custom exception types."
|
|
5
|
-
authors = ["Diogo Ribeiro <dfr@esmad.ipp.pt>"]
|
|
6
|
-
maintainers = ["Diogo Ribeiro <diogo.debastos.ribeiro@gmail.com>"]
|
|
7
|
-
license = "MIT"
|
|
8
5
|
readme = "README.md"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.10,<3.14"
|
|
9
|
+
authors = [{ name = "Diogo Ribeiro", email = "dfr@esmad.ipp.pt" }]
|
|
10
|
+
maintainers = [{ name = "Diogo Ribeiro", email = "diogo.debastos.ribeiro@gmail.com" }]
|
|
13
11
|
keywords = ["exceptions", "errors", "logging"]
|
|
14
|
-
include = [
|
|
15
|
-
"CITATION.cff",
|
|
16
|
-
"LICENSE",
|
|
17
|
-
"CHANGELOG.md",
|
|
18
|
-
]
|
|
19
|
-
|
|
20
12
|
classifiers = [
|
|
21
|
-
"License :: OSI Approved :: MIT License",
|
|
22
13
|
"Programming Language :: Python :: 3",
|
|
23
14
|
"Programming Language :: Python :: 3 :: Only",
|
|
24
15
|
"Programming Language :: Python :: 3.10",
|
|
@@ -26,17 +17,26 @@ classifiers = [
|
|
|
26
17
|
"Programming Language :: Python :: 3.12",
|
|
27
18
|
"Programming Language :: Python :: 3.13",
|
|
28
19
|
]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"tomli ; python_version < '3.11'",
|
|
22
|
+
]
|
|
29
23
|
|
|
30
|
-
[
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://github.com/DiogoRibeiro7/DataExcept"
|
|
26
|
+
Repository = "https://github.com/DiogoRibeiro7/DataExcept"
|
|
27
|
+
Documentation = "https://diogoribeiro7.github.io/DataExcept/"
|
|
31
28
|
Changelog = "https://github.com/DiogoRibeiro7/DataExcept/releases"
|
|
32
29
|
Issues = "https://github.com/DiogoRibeiro7/DataExcept/issues"
|
|
33
30
|
|
|
34
|
-
[
|
|
31
|
+
[project.scripts]
|
|
35
32
|
dataexcept = "dataexcept.__main__:main"
|
|
36
33
|
|
|
37
|
-
[tool.poetry
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
[tool.poetry]
|
|
35
|
+
packages = [{ include = "dataexcept" }]
|
|
36
|
+
include = [
|
|
37
|
+
"CITATION.cff",
|
|
38
|
+
"CHANGELOG.md",
|
|
39
|
+
]
|
|
40
40
|
|
|
41
41
|
[tool.poetry.group.dev.dependencies]
|
|
42
42
|
black = "*"
|
|
@@ -54,7 +54,7 @@ mkdocs-material = ">=9.5,<10"
|
|
|
54
54
|
mkdocstrings = { extras = ["python"], version = ">=0.26" }
|
|
55
55
|
|
|
56
56
|
[build-system]
|
|
57
|
-
requires = ["poetry-core>=
|
|
57
|
+
requires = ["poetry-core>=2.0.0"]
|
|
58
58
|
build-backend = "poetry.core.masonry.api"
|
|
59
59
|
|
|
60
60
|
[tool.flake8]
|
|
@@ -72,9 +72,26 @@ line-length = 88
|
|
|
72
72
|
target-version = "py310"
|
|
73
73
|
|
|
74
74
|
[tool.ruff.lint]
|
|
75
|
-
|
|
75
|
+
# S = flake8-bandit (security), C90 = mccabe (complexity). Both ship with ruff,
|
|
76
|
+
# so neither needs a separate tool in CI.
|
|
77
|
+
select = ["E", "F", "S", "C90"]
|
|
76
78
|
ignore = []
|
|
77
79
|
|
|
80
|
+
[tool.ruff.lint.mccabe]
|
|
81
|
+
# The most complex function in the package currently scores 6. Eight leaves
|
|
82
|
+
# room to breathe while still catching a function that grows out of hand.
|
|
83
|
+
max-complexity = 8
|
|
84
|
+
|
|
85
|
+
[tool.ruff.lint.per-file-ignores]
|
|
86
|
+
# assert is how a test asserts, and "/tmp/data" there is a string literal used
|
|
87
|
+
# as fixture data rather than a path that is ever opened.
|
|
88
|
+
"tests/**" = ["S101", "S108", "S603"]
|
|
89
|
+
# The lambda example asserts to narrow Optionals for the type checker.
|
|
90
|
+
"examples/**" = ["S101"]
|
|
91
|
+
# bump_version.py deliberately shells out to poetry, by name, on a maintainer's
|
|
92
|
+
# own machine.
|
|
93
|
+
"scripts/**" = ["S603", "S607"]
|
|
94
|
+
|
|
78
95
|
[tool.mypy]
|
|
79
96
|
python_version = "3.10"
|
|
80
97
|
files = ["dataexcept"]
|
dataexcept-0.1.0/CHANGELOG.md
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
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.1.0] - 2026-08-24
|
|
11
|
-
|
|
12
|
-
First public release.
|
|
13
|
-
|
|
14
|
-
### Added
|
|
15
|
-
|
|
16
|
-
- Hierarchical exception classes for data science, machine learning and data
|
|
17
|
-
engineering workflows. Catch a specific failure or a broad category, and get
|
|
18
|
-
a message that names the value that caused it rather than a bare
|
|
19
|
-
`ValueError`.
|
|
20
|
-
- Domain modules for validation, configuration, authentication, parsing,
|
|
21
|
-
serialization, scheduling, notification, lifecycle and external-service
|
|
22
|
-
errors, plus dedicated pandas, database, network, I/O, pipeline and security
|
|
23
|
-
exception groups.
|
|
24
|
-
- `dataexcept.logging_helpers` with `log_exception`, `log_and_raise` and
|
|
25
|
-
`log_then_raise`, for logging exceptions with structured context and
|
|
26
|
-
re-raising without losing the traceback.
|
|
27
|
-
- A `dataexcept` command-line entry point that lists the exported exception
|
|
28
|
-
classes and reports the installed version.
|
|
29
|
-
- A `py.typed` marker, backed by a mypy-clean codebase that CI enforces, so
|
|
30
|
-
downstream type checkers get annotations that are actually correct.
|
|
31
|
-
- Documentation at
|
|
32
|
-
[diogoribeiro7.github.io/DataExcept](https://diogoribeiro7.github.io/DataExcept/),
|
|
33
|
-
including an API reference generated from the docstrings.
|
|
34
|
-
|
|
35
|
-
### Notes
|
|
36
|
-
|
|
37
|
-
- Supports Python 3.10 through 3.13.
|
|
38
|
-
- Published to PyPI via OIDC trusted publishing; no long-lived API token is
|
|
39
|
-
involved in a release.
|
|
40
|
-
|
|
41
|
-
[Unreleased]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.1.0...HEAD
|
|
42
|
-
[0.1.0]: https://github.com/DiogoRibeiro7/DataExcept/releases/tag/v0.1.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|