DataExcept 0.2.0__tar.gz → 0.3.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 (35) hide show
  1. {dataexcept-0.2.0 → dataexcept-0.3.0}/CHANGELOG.md +78 -1
  2. {dataexcept-0.2.0 → dataexcept-0.3.0}/CITATION.cff +1 -1
  3. {dataexcept-0.2.0 → dataexcept-0.3.0}/PKG-INFO +20 -18
  4. {dataexcept-0.2.0 → dataexcept-0.3.0}/README.md +19 -17
  5. dataexcept-0.3.0/dataexcept/__init__.py +298 -0
  6. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/__main__.py +13 -2
  7. {dataexcept-0.2.0 → dataexcept-0.3.0}/pyproject.toml +1 -1
  8. dataexcept-0.2.0/dataexcept/__init__.py +0 -94
  9. {dataexcept-0.2.0 → dataexcept-0.3.0}/LICENSE +0 -0
  10. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/_deprecation.py +0 -0
  11. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/database_exceptions.py +0 -0
  12. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/dataengineering_exceptions.py +0 -0
  13. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/datascience_exceptions/__init__.py +0 -0
  14. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/datascience_exceptions/base.py +0 -0
  15. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/datascience_exceptions/ingestion.py +0 -0
  16. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/datascience_exceptions/operations.py +0 -0
  17. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/datascience_exceptions/training.py +0 -0
  18. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/exceptions/__init__.py +0 -0
  19. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/exceptions/authentication.py +0 -0
  20. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/exceptions/base.py +0 -0
  21. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/exceptions/configuration.py +0 -0
  22. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/exceptions/external.py +0 -0
  23. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/exceptions/lifecycle.py +0 -0
  24. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/exceptions/notification.py +0 -0
  25. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/exceptions/parsing.py +0 -0
  26. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/exceptions/scheduling.py +0 -0
  27. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/exceptions/validation.py +0 -0
  28. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/io_exceptions.py +0 -0
  29. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/job_exceptions.py +0 -0
  30. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/logging_helpers.py +0 -0
  31. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/network_exceptions.py +0 -0
  32. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/pandas_exceptions.py +0 -0
  33. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/pipeline_exceptions.py +0 -0
  34. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/py.typed +0 -0
  35. {dataexcept-0.2.0 → dataexcept-0.3.0}/dataexcept/security_exceptions.py +0 -0
@@ -7,6 +7,80 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] - 2026-08-24
11
+
12
+ ### Added
13
+
14
+ - **Every exception the package defines is now importable from `dataexcept`
15
+ directly.** All 98 classes are exported at the top level, so callers no
16
+ longer need to know which domain module a class lives in. The domain modules
17
+ export the same objects, so `from dataexcept import ValidationError` and
18
+ `from dataexcept.exceptions import ValidationError` are interchangeable and
19
+ `except` behaves identically either way.
20
+
21
+ This was only safe because 0.2.0 removed the two hazards that make a flat
22
+ namespace dangerous: there are no duplicate class names left, and nothing
23
+ shadows a Python builtin. Imports are explicit rather than generated at
24
+ runtime, so type checkers and IDEs see the full surface — the package ships
25
+ `py.typed`.
26
+ - `dataexcept.exceptions` and `dataexcept.logging_helpers` are now named in
27
+ `__all__` alongside the other domain modules; the stability policy already
28
+ described them as public.
29
+ - Tests covering the public surface: every exception the package defines must
30
+ be exported and resolve, each top-level export must be the *same object* as
31
+ the submodule one, no exported name may shadow a builtin, no two exceptions
32
+ may share a name, and `from dataexcept import *` must expose the documented
33
+ surface. Verified these fail when an unexported exception is introduced.
34
+ - Tests that `poetry.lock` is committed, and that `docs/requirements.txt`
35
+ agrees with the Poetry `docs` group — the two list the same packages and
36
+ could drift apart silently.
37
+
38
+ ### Changed
39
+
40
+ - `poetry.lock` is committed, and CI installs from it. Every job previously ran
41
+ `pip install black flake8 isort mypy ruff` unpinned, so a new release of any
42
+ linter could turn the build red with no commit to point at. `poetry check
43
+ --lock` now fails the build if the lock and `pyproject.toml` disagree.
44
+ - The coverage badge is generated by `scripts/coverage_badge.py` instead of
45
+ the `coverage-badge` package. That package still imports `pkg_resources`,
46
+ removed in setuptools 81, so using it required pinning `setuptools<81` — and
47
+ dependency review flagged a moderate-severity advisory against the version
48
+ that pin selected. Its last release was August 2024. Generating the SVG
49
+ directly removes the dependency, the pin and the advisory together; the
50
+ output is byte-identical to the published badge apart from the percentage.
51
+
52
+ ## [0.2.1] - 2026-08-24
53
+
54
+ Documentation and CLI fixes. 0.2.0's README is what PyPI renders as the
55
+ project description, and its quick-start example did not run.
56
+
57
+ ### Fixed
58
+
59
+ - `python -m dataexcept --version` reported `__main__.py` as the program name
60
+ instead of `dataexcept`, because argparse defaults `prog` to `sys.argv[0]`.
61
+ - `dataexcept list` imported the deprecated `job_exceptions` shim to build its
62
+ output, so it emitted a `DeprecationWarning` at anyone who merely wanted to
63
+ see what the package offers, and it advertised `ConnectionError` and
64
+ `TimeoutError` alongside their replacements. Deprecated modules are now
65
+ skipped; the listing is 98 names, matching the classes the package defines.
66
+ - README's quick-start example began `from dataexcept import ValidationError,
67
+ ModelTrainingError`, which raises `ImportError` — `ModelTrainingError` is in
68
+ `dataexcept.datascience_exceptions` and is not re-exported at the top level.
69
+ - `docs/advanced_usage.md` taught `from dataexcept.job_exceptions import
70
+ JobError`, the deprecated path.
71
+ - README's comparison table showed exception messages without the
72
+ `[ClassName]` prefix the classes actually emit, its sample `dataexcept list`
73
+ output did not match the real alphabetical listing, its exception count and
74
+ CLI version were stale, and its end-to-end example used `np.log` without
75
+ importing numpy.
76
+
77
+ ### Added
78
+
79
+ - Tests that read the documentation: every `from dataexcept... import ...` in
80
+ README and `docs/` must resolve, no example may import a deprecated module,
81
+ and the README's exception count must match the package. Checked that these
82
+ fail when the original defects are reintroduced.
83
+
10
84
  ## [0.2.0] - 2026-08-24
11
85
 
12
86
  ### Changed
@@ -62,6 +136,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
62
136
  - `examples/example_usage.py` raised `TimeoutError` with keyword arguments the
63
137
  builtin does not accept — a live instance of the shadowing hazard.
64
138
 
139
+
65
140
  ## [0.1.0] - 2026-08-24
66
141
 
67
142
  First public release.
@@ -93,6 +168,8 @@ First public release.
93
168
  - Published to PyPI via OIDC trusted publishing; no long-lived API token is
94
169
  involved in a release.
95
170
 
96
- [Unreleased]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.2.0...HEAD
171
+ [Unreleased]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.3.0...HEAD
172
+ [0.3.0]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.2.1...v0.3.0
173
+ [0.2.1]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.2.0...v0.2.1
97
174
  [0.2.0]: https://github.com/DiogoRibeiro7/DataExcept/compare/v0.1.0...v0.2.0
98
175
  [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.0"
4
+ version: "0.3.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.0
3
+ Version: 0.3.0
4
4
  Summary: A Python package providing structured, easily-extendable custom exception types.
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -34,15 +34,16 @@ Description-Content-Type: text/markdown
34
34
 
35
35
  ❌ Without DataExcept | ✅ With DataExcept
36
36
  ------------------------------- | -------------------------------------------------------------------------------------
37
- `ValueError: Invalid value` | `DataValidationError: Invalid value for 'age': -1`
38
- `RuntimeError: Training failed` | `ConvergenceError: Model 'RandomForest' failed to converge after 100 iterations`
39
- `Exception: Prediction error` | `ModelInferenceError: Inference failed for model 'CNN': CUDA out of memory`
40
- `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'`
41
41
 
42
42
  ## 🎯 Key Features
43
43
 
44
44
  - **🏗️ Hierarchical Structure**: Catch specific errors or broad categories
45
- - **📊 Data Science Focused**: 96 exception classes covering ML pipelines, feature engineering, model training
45
+ - **📦 One Import**: Every exception is available from `dataexcept` directly, or from its domain module — same objects either way
46
+ - **📊 Data Science Focused**: 98 exception classes covering ML pipelines, feature engineering, model training
46
47
  - **🔧 Production Ready**: Comprehensive logging helpers and error context
47
48
  - **📚 Academic Quality**: Proper documentation, type hints, and citation support
48
49
  - **🐍 Python 3.10+**: Modern Python with full type safety
@@ -67,8 +68,7 @@ poetry install
67
68
  ### Basic Usage
68
69
 
69
70
  ```python
70
- from dataexcept import ValidationError, ModelTrainingError
71
- from dataexcept.datascience_exceptions import DataLoadingError
71
+ from dataexcept import DataLoadingError, ModelTrainingError, ValidationError
72
72
  import pandas as pd
73
73
 
74
74
  # Data validation with context
@@ -214,17 +214,18 @@ except Exception as exc:
214
214
  ### Command Line Interface
215
215
 
216
216
  ```bash
217
- # List all available exception classes
217
+ # List every exception class the package exports (98 of them, alphabetically)
218
218
  $ dataexcept list
219
- JobError
220
- ValidationError
221
- DataScienceError
222
- ModelTrainingError
223
- ... (40+ more)
219
+ ApiError
220
+ AuthenticationError
221
+ AuthorizationError
222
+ BatchProcessingError
223
+ BiasDetectionError
224
+ ...
224
225
 
225
226
  # Check version
226
227
  $ dataexcept --version
227
- dataexcept 0.1.0
228
+ dataexcept 0.3.0
228
229
  ```
229
230
 
230
231
  ## 🎯 Use Cases
@@ -255,6 +256,7 @@ dataexcept 0.1.0
255
256
  """
256
257
  Complete ML pipeline with DataExcept error handling
257
258
  """
259
+ import numpy as np
258
260
  import pandas as pd
259
261
  from sklearn.ensemble import RandomForestClassifier
260
262
  from dataexcept import ValidationError
@@ -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{ribeiro_dataexcept_2025,
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.0},
377
- year = {2025},
378
+ version = {0.3.0},
379
+ year = {2026},
378
380
  publisher = {GitHub}
379
381
  }
380
382
  ```
@@ -8,15 +8,16 @@
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**: 96 exception classes covering ML pipelines, feature engineering, model training
19
+ - **📦 One Import**: Every exception is available from `dataexcept` directly, or from its domain module — same objects either way
20
+ - **📊 Data Science Focused**: 98 exception classes covering ML pipelines, feature engineering, model training
20
21
  - **🔧 Production Ready**: Comprehensive logging helpers and error context
21
22
  - **📚 Academic Quality**: Proper documentation, type hints, and citation support
22
23
  - **🐍 Python 3.10+**: Modern Python with full type safety
@@ -41,8 +42,7 @@ poetry install
41
42
  ### Basic Usage
42
43
 
43
44
  ```python
44
- from dataexcept import ValidationError, ModelTrainingError
45
- from dataexcept.datascience_exceptions import DataLoadingError
45
+ from dataexcept import DataLoadingError, ModelTrainingError, ValidationError
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 all available exception classes
191
+ # List every exception class the package exports (98 of them, alphabetically)
192
192
  $ dataexcept list
193
- JobError
194
- ValidationError
195
- DataScienceError
196
- ModelTrainingError
197
- ... (40+ more)
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.0
202
+ dataexcept 0.3.0
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
@@ -343,12 +345,12 @@ through [SECURITY.md](SECURITY.md), not the public issue tracker.
343
345
  If you use DataExcept in your research, please cite it:
344
346
 
345
347
  ```bibtex
346
- @software{ribeiro_dataexcept_2025,
348
+ @software{ribeiro_dataexcept_2026,
347
349
  author = {Ribeiro, Diogo},
348
350
  title = {DataExcept: Structured Exception Handling for Data Science},
349
351
  url = {https://github.com/DiogoRibeiro7/DataExcept},
350
- version = {0.1.0},
351
- year = {2025},
352
+ version = {0.3.0},
353
+ year = {2026},
352
354
  publisher = {GitHub}
353
355
  }
354
356
  ```
@@ -0,0 +1,298 @@
1
+ """Top-level package for DataExcept.
2
+
3
+ Every exception the package defines is importable straight from here::
4
+
5
+ from dataexcept import ValidationError, ModelTrainingError
6
+
7
+ The domain modules (``datascience_exceptions``, ``pipeline_exceptions`` and so
8
+ on) remain importable and export the same objects, so both spellings work and
9
+ refer to the same classes.
10
+ """
11
+
12
+ from pathlib import Path
13
+
14
+ try: # Python >=3.11
15
+ import tomllib # type: ignore
16
+ except ModuleNotFoundError: # pragma: no cover - fallback for Python <3.11
17
+ import tomli as tomllib # type: ignore
18
+
19
+ from importlib import import_module, metadata
20
+ from typing import Any
21
+
22
+ from . import ( # noqa: F401
23
+ database_exceptions,
24
+ dataengineering_exceptions,
25
+ datascience_exceptions,
26
+ exceptions,
27
+ io_exceptions,
28
+ logging_helpers,
29
+ network_exceptions,
30
+ pandas_exceptions,
31
+ pipeline_exceptions,
32
+ security_exceptions,
33
+ )
34
+ from ._deprecation import resolve_deprecated
35
+ from .database_exceptions import (
36
+ DatabaseConnectionError,
37
+ DatabaseError,
38
+ QueryExecutionError,
39
+ TransactionError,
40
+ )
41
+ from .dataengineering_exceptions import (
42
+ BatchProcessingError,
43
+ DataEngineeringError,
44
+ DataTransformationError,
45
+ DataWarehouseConnectionError,
46
+ ETLJobError,
47
+ MissingPartitionError,
48
+ SchemaEvolutionError,
49
+ )
50
+ from .datascience_exceptions import (
51
+ BiasDetectionError,
52
+ ConvergenceError,
53
+ CrossValidationError,
54
+ DataAugmentationError,
55
+ DataDriftError,
56
+ DataExportError,
57
+ DataFormatError,
58
+ DataImbalanceError,
59
+ DataLeakageError,
60
+ DataLoadingError,
61
+ DataNormalizationError,
62
+ DataScienceError,
63
+ DataValidationError,
64
+ DeploymentError,
65
+ DimensionalityReductionError,
66
+ EarlyStoppingError,
67
+ ExperimentTrackingError,
68
+ ExplainabilityError,
69
+ FeatureEngineeringError,
70
+ FeatureScalingError,
71
+ FeatureSelectionError,
72
+ GPUOutOfMemoryError,
73
+ HyperparameterError,
74
+ HyperparameterTuningError,
75
+ MissingDataError,
76
+ ModelCompatibilityError,
77
+ ModelEvaluationError,
78
+ ModelInferenceError,
79
+ ModelSerializationError,
80
+ ModelTrainingError,
81
+ OutlierDetectionError,
82
+ OverfittingError,
83
+ PredictionError,
84
+ ResourceLimitError,
85
+ SchemaMismatchError,
86
+ TrainingTimeoutError,
87
+ UnderfittingError,
88
+ )
89
+ from .exceptions import (
90
+ AuthenticationError,
91
+ AuthorizationError,
92
+ ConfigurationError,
93
+ CronExpressionError,
94
+ DependencyError,
95
+ DeserializationError,
96
+ EmailError,
97
+ JobCancellationError,
98
+ JobError,
99
+ NotificationError,
100
+ OperationTimeoutError,
101
+ ParsingError,
102
+ ResourceNotFoundError,
103
+ ScheduleConflictError,
104
+ SerializationError,
105
+ ServiceConnectionError,
106
+ ValidationError,
107
+ WebhookError,
108
+ )
109
+ from .io_exceptions import (
110
+ CustomIOError,
111
+ FileLockError,
112
+ FileReadError,
113
+ FileWriteError,
114
+ )
115
+ from .logging_helpers import (
116
+ Context,
117
+ log_and_raise,
118
+ log_exception,
119
+ log_then_raise,
120
+ )
121
+ from .network_exceptions import (
122
+ ConnectionTimeoutError,
123
+ HostUnreachableError,
124
+ NetworkError,
125
+ ProtocolError,
126
+ )
127
+ from .pandas_exceptions import (
128
+ DtypeMismatchError,
129
+ IndexAlignmentError,
130
+ MergeKeyError,
131
+ MissingColumnError,
132
+ PandasError,
133
+ PandasIOError,
134
+ )
135
+ from .pipeline_exceptions import (
136
+ ApiError,
137
+ DataFetchError,
138
+ ExternalServiceError,
139
+ FeaturePreprocessingError,
140
+ PipelineError,
141
+ PipelineNotificationError,
142
+ PreprocessingError,
143
+ RetryLimitExceededError,
144
+ ServiceAuthenticationError,
145
+ ServiceAuthorizationError,
146
+ ServiceTimeoutError,
147
+ StorageError,
148
+ TimeDeltaTooLargeError,
149
+ TypeCheckError,
150
+ )
151
+ from .security_exceptions import (
152
+ DecryptionError,
153
+ EncryptionError,
154
+ InvalidTokenError,
155
+ SecurityError,
156
+ )
157
+
158
+ __all__ = [
159
+ # Every exception class the package defines.
160
+ "ApiError",
161
+ "AuthenticationError",
162
+ "AuthorizationError",
163
+ "BatchProcessingError",
164
+ "BiasDetectionError",
165
+ "ConfigurationError",
166
+ "ConnectionTimeoutError",
167
+ "ConvergenceError",
168
+ "CronExpressionError",
169
+ "CrossValidationError",
170
+ "CustomIOError",
171
+ "DataAugmentationError",
172
+ "DataDriftError",
173
+ "DataEngineeringError",
174
+ "DataExportError",
175
+ "DataFetchError",
176
+ "DataFormatError",
177
+ "DataImbalanceError",
178
+ "DataLeakageError",
179
+ "DataLoadingError",
180
+ "DataNormalizationError",
181
+ "DataScienceError",
182
+ "DataTransformationError",
183
+ "DataValidationError",
184
+ "DataWarehouseConnectionError",
185
+ "DatabaseConnectionError",
186
+ "DatabaseError",
187
+ "DecryptionError",
188
+ "DependencyError",
189
+ "DeploymentError",
190
+ "DeserializationError",
191
+ "DimensionalityReductionError",
192
+ "DtypeMismatchError",
193
+ "ETLJobError",
194
+ "EarlyStoppingError",
195
+ "EmailError",
196
+ "EncryptionError",
197
+ "ExperimentTrackingError",
198
+ "ExplainabilityError",
199
+ "ExternalServiceError",
200
+ "FeatureEngineeringError",
201
+ "FeaturePreprocessingError",
202
+ "FeatureScalingError",
203
+ "FeatureSelectionError",
204
+ "FileLockError",
205
+ "FileReadError",
206
+ "FileWriteError",
207
+ "GPUOutOfMemoryError",
208
+ "HostUnreachableError",
209
+ "HyperparameterError",
210
+ "HyperparameterTuningError",
211
+ "IndexAlignmentError",
212
+ "InvalidTokenError",
213
+ "JobCancellationError",
214
+ "JobError",
215
+ "MergeKeyError",
216
+ "MissingColumnError",
217
+ "MissingDataError",
218
+ "MissingPartitionError",
219
+ "ModelCompatibilityError",
220
+ "ModelEvaluationError",
221
+ "ModelInferenceError",
222
+ "ModelSerializationError",
223
+ "ModelTrainingError",
224
+ "NetworkError",
225
+ "NotificationError",
226
+ "OperationTimeoutError",
227
+ "OutlierDetectionError",
228
+ "OverfittingError",
229
+ "PandasError",
230
+ "PandasIOError",
231
+ "ParsingError",
232
+ "PipelineError",
233
+ "PipelineNotificationError",
234
+ "PredictionError",
235
+ "PreprocessingError",
236
+ "ProtocolError",
237
+ "QueryExecutionError",
238
+ "ResourceLimitError",
239
+ "ResourceNotFoundError",
240
+ "RetryLimitExceededError",
241
+ "ScheduleConflictError",
242
+ "SchemaEvolutionError",
243
+ "SchemaMismatchError",
244
+ "SecurityError",
245
+ "SerializationError",
246
+ "ServiceAuthenticationError",
247
+ "ServiceAuthorizationError",
248
+ "ServiceConnectionError",
249
+ "ServiceTimeoutError",
250
+ "StorageError",
251
+ "TimeDeltaTooLargeError",
252
+ "TrainingTimeoutError",
253
+ "TransactionError",
254
+ "TypeCheckError",
255
+ "UnderfittingError",
256
+ "ValidationError",
257
+ "WebhookError",
258
+ # Logging helpers.
259
+ "Context",
260
+ "log_and_raise",
261
+ "log_exception",
262
+ "log_then_raise",
263
+ # Domain modules, for callers who prefer a qualified import.
264
+ "database_exceptions",
265
+ "dataengineering_exceptions",
266
+ "datascience_exceptions",
267
+ "exceptions",
268
+ "io_exceptions",
269
+ "job_exceptions",
270
+ "logging_helpers",
271
+ "network_exceptions",
272
+ "pandas_exceptions",
273
+ "pipeline_exceptions",
274
+ "security_exceptions",
275
+ ]
276
+
277
+ try:
278
+ __version__ = metadata.version("DataExcept")
279
+ except metadata.PackageNotFoundError: # pragma: no cover - fallback during dev
280
+ _root = Path(__file__).resolve().parents[1]
281
+ with open(_root / "pyproject.toml", "rb") as _f:
282
+ __version__ = tomllib.load(_f)["project"]["version"]
283
+
284
+
285
+ #: Renamed in 0.2.0 because they shadowed Python builtins without inheriting
286
+ #: from them. Each alias is the same class object as its replacement.
287
+ _DEPRECATED_ALIASES = {
288
+ "ConnectionError": ServiceConnectionError,
289
+ "TimeoutError": OperationTimeoutError,
290
+ }
291
+
292
+
293
+ def __getattr__(name: str) -> Any:
294
+ if name == "job_exceptions":
295
+ module = import_module("dataexcept.job_exceptions")
296
+ globals()[name] = module
297
+ return module
298
+ 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(description="Utilities for DataExcept")
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",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "DataExcept"
3
- version = "0.2.0"
3
+ version = "0.3.0"
4
4
  description = "A Python package providing structured, easily-extendable custom exception types."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,94 +0,0 @@
1
- """Top-level package for DataExcept.
2
-
3
- Exposes the common job-related exceptions directly and also provides
4
- access to data science specific exceptions via the ``datascience_exceptions``
5
- module.
6
- """
7
-
8
- from pathlib import Path
9
-
10
- try: # Python >=3.11
11
- import tomllib # type: ignore
12
- except ModuleNotFoundError: # pragma: no cover - fallback for Python <3.11
13
- import tomli as tomllib # type: ignore
14
-
15
- from importlib import import_module, metadata
16
- from typing import Any
17
-
18
- from . import (
19
- database_exceptions,
20
- dataengineering_exceptions,
21
- datascience_exceptions,
22
- )
23
- from . import exceptions as _exceptions
24
- from . import (
25
- io_exceptions,
26
- network_exceptions,
27
- pandas_exceptions,
28
- pipeline_exceptions,
29
- security_exceptions,
30
- )
31
- from ._deprecation import resolve_deprecated
32
- from .exceptions import ( # noqa: F401
33
- AuthenticationError,
34
- AuthorizationError,
35
- ConfigurationError,
36
- CronExpressionError,
37
- DependencyError,
38
- DeserializationError,
39
- EmailError,
40
- JobCancellationError,
41
- JobError,
42
- NotificationError,
43
- OperationTimeoutError,
44
- ParsingError,
45
- ResourceNotFoundError,
46
- ScheduleConflictError,
47
- SerializationError,
48
- ServiceConnectionError,
49
- ValidationError,
50
- WebhookError,
51
- )
52
- from .logging_helpers import (
53
- log_and_raise,
54
- log_exception,
55
- log_then_raise,
56
- )
57
-
58
- try:
59
- __version__ = metadata.version("DataExcept")
60
- except metadata.PackageNotFoundError: # pragma: no cover - fallback during dev
61
- _root = Path(__file__).resolve().parents[1]
62
- with open(_root / "pyproject.toml", "rb") as _f:
63
- __version__ = tomllib.load(_f)["project"]["version"]
64
-
65
- __all__ = list(_exceptions.__all__) + [
66
- "datascience_exceptions",
67
- "job_exceptions",
68
- "pipeline_exceptions",
69
- "dataengineering_exceptions",
70
- "network_exceptions",
71
- "io_exceptions",
72
- "database_exceptions",
73
- "security_exceptions",
74
- "pandas_exceptions",
75
- "log_exception",
76
- "log_and_raise",
77
- "log_then_raise",
78
- ]
79
-
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
-
89
- def __getattr__(name: str) -> Any:
90
- if name == "job_exceptions":
91
- module = import_module("dataexcept.job_exceptions")
92
- globals()[name] = module
93
- return module
94
- return resolve_deprecated(__name__, _DEPRECATED_ALIASES, name)
File without changes