DataExcept 0.1.0__tar.gz → 0.2.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.
- dataexcept-0.2.0/CHANGELOG.md +98 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/CITATION.cff +2 -2
- {dataexcept-0.1.0 → dataexcept-0.2.0}/PKG-INFO +5 -5
- {dataexcept-0.1.0 → dataexcept-0.2.0}/README.md +2 -1
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/__init__.py +18 -5
- dataexcept-0.2.0/dataexcept/_deprecation.py +38 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/datascience_exceptions/__init__.py +13 -2
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/datascience_exceptions/operations.py +2 -2
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/exceptions/__init__.py +18 -4
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/exceptions/external.py +2 -2
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/job_exceptions.py +18 -6
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/logging_helpers.py +7 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/pipeline_exceptions.py +13 -2
- {dataexcept-0.1.0 → dataexcept-0.2.0}/pyproject.toml +40 -23
- dataexcept-0.1.0/CHANGELOG.md +0 -42
- {dataexcept-0.1.0 → dataexcept-0.2.0}/LICENSE +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/__main__.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/database_exceptions.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/dataengineering_exceptions.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/datascience_exceptions/base.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/datascience_exceptions/ingestion.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/datascience_exceptions/training.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/exceptions/authentication.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/exceptions/base.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/exceptions/configuration.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/exceptions/lifecycle.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/exceptions/notification.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/exceptions/parsing.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/exceptions/scheduling.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/exceptions/validation.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/io_exceptions.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/network_exceptions.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/pandas_exceptions.py +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/py.typed +0 -0
- {dataexcept-0.1.0 → dataexcept-0.2.0}/dataexcept/security_exceptions.py +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
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.0] - 2026-08-24
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **`ConnectionError` is now `ServiceConnectionError`, and `TimeoutError` is
|
|
15
|
+
now `OperationTimeoutError`.** The old names shadowed Python builtins without
|
|
16
|
+
inheriting from them, so after `from dataexcept import ConnectionError` an
|
|
17
|
+
`except ConnectionError:` in that module silently stopped catching real
|
|
18
|
+
socket failures.
|
|
19
|
+
- **`datascience_exceptions.SerializationError` is now
|
|
20
|
+
`ModelSerializationError`**, and **`pipeline_exceptions.FeatureEngineeringError`
|
|
21
|
+
is now `FeaturePreprocessingError`.** Each of those names previously referred
|
|
22
|
+
to two different classes in different modules, so catching one silently
|
|
23
|
+
missed the other.
|
|
24
|
+
- Project metadata moved from Poetry's `[tool.poetry]` table to the standard
|
|
25
|
+
PEP 621 `[project]` table, clearing every `poetry check` deprecation. The
|
|
26
|
+
license is now an SPDX expression (PEP 639), so the built metadata carries
|
|
27
|
+
`License-Expression: MIT` and the redundant license classifier is gone.
|
|
28
|
+
Wheel and sdist contents are otherwise unchanged.
|
|
29
|
+
- `dataexcept.job_exceptions` now names its removal version, 1.0.0, in both the
|
|
30
|
+
warning and the module docstring.
|
|
31
|
+
|
|
32
|
+
### Deprecated
|
|
33
|
+
|
|
34
|
+
- `ConnectionError`, `TimeoutError`, `datascience_exceptions.SerializationError`
|
|
35
|
+
and `pipeline_exceptions.FeatureEngineeringError`. All four still resolve, to
|
|
36
|
+
the **same class object** as their replacement, so existing `except` clauses
|
|
37
|
+
keep working; touching one emits a `DeprecationWarning` naming the
|
|
38
|
+
replacement and 1.0.0 as the removal. Importing the package does not warn.
|
|
39
|
+
Find remaining uses with `python -W error::DeprecationWarning -m pytest`.
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- A published [API stability policy](https://diogoribeiro7.github.io/DataExcept/stability/)
|
|
44
|
+
stating what is public, what each kind of change costs in version terms, the
|
|
45
|
+
deprecation process, and how to migrate off the 0.2.0 renames.
|
|
46
|
+
- Security scanning: CodeQL, and pip-audit against the runtime and
|
|
47
|
+
documentation dependency sets, on push, pull request and weekly — advisories
|
|
48
|
+
are published against code that has not changed. Pull requests also get a
|
|
49
|
+
dependency review failing at moderate severity.
|
|
50
|
+
- Complexity and security linting via ruff's mccabe (`C90`) and flake8-bandit
|
|
51
|
+
(`S`) rule sets, so neither needs a separate tool. Complexity is capped at 8;
|
|
52
|
+
the highest score in the package is 6.
|
|
53
|
+
- A regression guard that fails if any exported name ever shadows a builtin
|
|
54
|
+
again.
|
|
55
|
+
- `__all__` on `dataexcept.logging_helpers`, the one public module without one.
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- `dataexcept.__version__` and `tests/test_version.py` read the version out of
|
|
60
|
+
`pyproject.toml` when the package is not installed, and were still looking in
|
|
61
|
+
`[tool.poetry]`. They now read `[project]`.
|
|
62
|
+
- `examples/example_usage.py` raised `TimeoutError` with keyword arguments the
|
|
63
|
+
builtin does not accept — a live instance of the shadowing hazard.
|
|
64
|
+
|
|
65
|
+
## [0.1.0] - 2026-08-24
|
|
66
|
+
|
|
67
|
+
First public release.
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- Hierarchical exception classes for data science, machine learning and data
|
|
72
|
+
engineering workflows. Catch a specific failure or a broad category, and get
|
|
73
|
+
a message that names the value that caused it rather than a bare
|
|
74
|
+
`ValueError`.
|
|
75
|
+
- Domain modules for validation, configuration, authentication, parsing,
|
|
76
|
+
serialization, scheduling, notification, lifecycle and external-service
|
|
77
|
+
errors, plus dedicated pandas, database, network, I/O, pipeline and security
|
|
78
|
+
exception groups.
|
|
79
|
+
- `dataexcept.logging_helpers` with `log_exception`, `log_and_raise` and
|
|
80
|
+
`log_then_raise`, for logging exceptions with structured context and
|
|
81
|
+
re-raising without losing the traceback.
|
|
82
|
+
- A `dataexcept` command-line entry point that lists the exported exception
|
|
83
|
+
classes and reports the installed version.
|
|
84
|
+
- A `py.typed` marker, backed by a mypy-clean codebase that CI enforces, so
|
|
85
|
+
downstream type checkers get annotations that are actually correct.
|
|
86
|
+
- Documentation at
|
|
87
|
+
[diogoribeiro7.github.io/DataExcept](https://diogoribeiro7.github.io/DataExcept/),
|
|
88
|
+
including an API reference generated from the docstrings.
|
|
89
|
+
|
|
90
|
+
### Notes
|
|
91
|
+
|
|
92
|
+
- Supports Python 3.10 through 3.13.
|
|
93
|
+
- Published to PyPI via OIDC trusted publishing; no long-lived API token is
|
|
94
|
+
involved in a release.
|
|
95
|
+
|
|
96
|
+
[Unreleased]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.2.0...HEAD
|
|
97
|
+
[0.2.0]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.1.0...v0.2.0
|
|
98
|
+
[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.
|
|
4
|
+
version: "0.2.0"
|
|
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.
|
|
3
|
+
Version: 0.2.0
|
|
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/
|
|
@@ -43,7 +42,7 @@ Description-Content-Type: text/markdown
|
|
|
43
42
|
## 🎯 Key Features
|
|
44
43
|
|
|
45
44
|
- **🏗️ Hierarchical Structure**: Catch specific errors or broad categories
|
|
46
|
-
- **📊 Data Science Focused**:
|
|
45
|
+
- **📊 Data Science Focused**: 96 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
|
|
@@ -360,6 +359,7 @@ through [SECURITY.md](SECURITY.md), not the public issue tracker.
|
|
|
360
359
|
|
|
361
360
|
- **Full Documentation**: [diogoribeiro7.github.io/DataExcept](https://diogoribeiro7.github.io/DataExcept/)
|
|
362
361
|
- **API Reference**: [API Docs](https://diogoribeiro7.github.io/DataExcept/api/)
|
|
362
|
+
- **API Stability**: [What is public and what may change](https://diogoribeiro7.github.io/DataExcept/stability/)
|
|
363
363
|
- **Advanced Usage**: [Advanced Guide](https://diogoribeiro7.github.io/DataExcept/advanced_usage/)
|
|
364
364
|
- **CLI Reference**: [CLI Guide](https://diogoribeiro7.github.io/DataExcept/cli/)
|
|
365
365
|
- **Changelog**: [CHANGELOG.md](CHANGELOG.md)
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
## 🎯 Key Features
|
|
17
17
|
|
|
18
18
|
- **🏗️ Hierarchical Structure**: Catch specific errors or broad categories
|
|
19
|
-
- **📊 Data Science Focused**:
|
|
19
|
+
- **📊 Data Science Focused**: 96 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
|
|
@@ -333,6 +333,7 @@ through [SECURITY.md](SECURITY.md), not the public issue tracker.
|
|
|
333
333
|
|
|
334
334
|
- **Full Documentation**: [diogoribeiro7.github.io/DataExcept](https://diogoribeiro7.github.io/DataExcept/)
|
|
335
335
|
- **API Reference**: [API Docs](https://diogoribeiro7.github.io/DataExcept/api/)
|
|
336
|
+
- **API Stability**: [What is public and what may change](https://diogoribeiro7.github.io/DataExcept/stability/)
|
|
336
337
|
- **Advanced Usage**: [Advanced Guide](https://diogoribeiro7.github.io/DataExcept/advanced_usage/)
|
|
337
338
|
- **CLI Reference**: [CLI Guide](https://diogoribeiro7.github.io/DataExcept/cli/)
|
|
338
339
|
- **Changelog**: [CHANGELOG.md](CHANGELOG.md)
|
|
@@ -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)
|
|
@@ -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.
|
|
3
|
+
version = "0.2.0"
|
|
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
|
|
File without changes
|