recotem 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- recotem/__init__.py +5 -0
- recotem/__main__.py +14 -0
- recotem/_exit_codes.py +157 -0
- recotem/_http_fetch.py +609 -0
- recotem/_idmap.py +124 -0
- recotem/_ipython_stub.py +29 -0
- recotem/_log_safe.py +52 -0
- recotem/_metrics_bigquery.py +72 -0
- recotem/_metrics_watcher.py +74 -0
- recotem/_size_cap.py +164 -0
- recotem/artifact/__init__.py +11 -0
- recotem/artifact/format.py +233 -0
- recotem/artifact/io.py +406 -0
- recotem/artifact/signing.py +497 -0
- recotem/cli.py +807 -0
- recotem/config.py +575 -0
- recotem/datasource/__init__.py +10 -0
- recotem/datasource/base.py +164 -0
- recotem/datasource/bigquery.py +360 -0
- recotem/datasource/csv.py +585 -0
- recotem/datasource/registry.py +221 -0
- recotem/datasource/sql.py +546 -0
- recotem/log_redaction.py +282 -0
- recotem/logging.py +92 -0
- recotem/metadata/__init__.py +3 -0
- recotem/metadata/loader.py +470 -0
- recotem/recipe/__init__.py +26 -0
- recotem/recipe/envvars.py +150 -0
- recotem/recipe/errors.py +59 -0
- recotem/recipe/loader.py +803 -0
- recotem/recipe/models.py +338 -0
- recotem/serving/__init__.py +4 -0
- recotem/serving/_header_utils.py +36 -0
- recotem/serving/_naming.py +26 -0
- recotem/serving/app.py +912 -0
- recotem/serving/auth.py +298 -0
- recotem/serving/metrics.py +465 -0
- recotem/serving/registry.py +360 -0
- recotem/serving/routes.py +962 -0
- recotem/serving/schemas.py +279 -0
- recotem/serving/watcher.py +1480 -0
- recotem/training/__init__.py +8 -0
- recotem/training/_compat.py +30 -0
- recotem/training/algorithms.py +113 -0
- recotem/training/errors.py +79 -0
- recotem/training/evaluate.py +73 -0
- recotem/training/lock.py +363 -0
- recotem/training/pipeline.py +825 -0
- recotem/training/progress.py +244 -0
- recotem/training/search.py +704 -0
- recotem/training/split.py +145 -0
- recotem/version.py +1 -0
- recotem-2.0.0.dist-info/METADATA +430 -0
- recotem-2.0.0.dist-info/RECORD +57 -0
- recotem-2.0.0.dist-info/WHEEL +4 -0
- recotem-2.0.0.dist-info/entry_points.txt +8 -0
- recotem-2.0.0.dist-info/licenses/LICENSE +201 -0
recotem/__init__.py
ADDED
recotem/__main__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Enable ``python -m recotem`` invocation.
|
|
2
|
+
|
|
3
|
+
The console-script entry point ``recotem`` is the recommended way to run the
|
|
4
|
+
CLI, but it is unavailable when the package is installed into a venv that is
|
|
5
|
+
not on ``PATH``. Falling back to ``python -m recotem`` keeps the troubleshooting
|
|
6
|
+
advice in ``docs/getting-started.md`` honest.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from recotem.cli import app
|
|
12
|
+
|
|
13
|
+
if __name__ == "__main__":
|
|
14
|
+
app()
|
recotem/_exit_codes.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Canonical exit-code constants and exception-to-exit-code mapping.
|
|
2
|
+
|
|
3
|
+
Single source of truth for both ``recotem.cli`` and
|
|
4
|
+
``recotem.training.pipeline`` so the two paths cannot diverge silently.
|
|
5
|
+
|
|
6
|
+
Exit code table
|
|
7
|
+
---------------
|
|
8
|
+
| Code | Constant | Meaning |
|
|
9
|
+
|------|---------------------|--------------------------------------------|
|
|
10
|
+
| 0 | _EXIT_SUCCESS | success |
|
|
11
|
+
| 1 | _EXIT_UNKNOWN | unhandled / unmapped exception |
|
|
12
|
+
| 2 | _EXIT_RECIPE | RecipeError |
|
|
13
|
+
| 3 | _EXIT_DATASOURCE | DataSourceError |
|
|
14
|
+
| 4 | _EXIT_TRAINING | TrainingError |
|
|
15
|
+
| 5 | _EXIT_ARTIFACT | ArtifactError |
|
|
16
|
+
| 6 | _EXIT_LOCK_CONTESTED| LockContestedError |
|
|
17
|
+
| 7 | _EXIT_HTTP_FETCH | HttpFetchError |
|
|
18
|
+
| 8 | _EXIT_CONFIG | ConfigError / missing signing keys |
|
|
19
|
+
|
|
20
|
+
Design note on imports
|
|
21
|
+
----------------------
|
|
22
|
+
All exception-class imports inside ``_map_exception_to_exit`` are deferred to
|
|
23
|
+
function-call time to prevent circular imports. The ``recotem.training``
|
|
24
|
+
package ``__init__.py`` imports ``pipeline``, which imports this module, so
|
|
25
|
+
any top-level import of ``recotem.training.*`` here would cause a circular
|
|
26
|
+
import. Deferring the imports to inside the function is safe because the
|
|
27
|
+
function is only called after all modules are fully initialised.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
# Exit-code constants (no imports needed — just ints)
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
_EXIT_SUCCESS = 0
|
|
37
|
+
_EXIT_UNKNOWN = 1
|
|
38
|
+
_EXIT_RECIPE = 2
|
|
39
|
+
_EXIT_DATASOURCE = 3
|
|
40
|
+
_EXIT_TRAINING = 4
|
|
41
|
+
_EXIT_ARTIFACT = 5
|
|
42
|
+
_EXIT_LOCK_CONTESTED = 6
|
|
43
|
+
_EXIT_HTTP_FETCH = 7
|
|
44
|
+
_EXIT_CONFIG = 8
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _map_exception_to_exit(exc: BaseException) -> int: # noqa: C901
|
|
48
|
+
"""Map a known exception type to its canonical exit code.
|
|
49
|
+
|
|
50
|
+
Checked in priority order so that the most-specific mapping wins when
|
|
51
|
+
exception hierarchies overlap (e.g. a subclass of TrainingError that
|
|
52
|
+
signals a configuration problem maps to _EXIT_CONFIG, not _EXIT_TRAINING).
|
|
53
|
+
|
|
54
|
+
All exception-class imports are deferred (inside this function) to avoid
|
|
55
|
+
circular imports at module level — see module docstring for details.
|
|
56
|
+
|
|
57
|
+
The ``__cause__`` chain is walked for HttpFetchError so that a
|
|
58
|
+
DataSourceError wrapping an HttpFetchError maps to exit 7 (transient
|
|
59
|
+
network) rather than exit 3 (structural datasource failure). CronJob
|
|
60
|
+
retry logic distinguishes the two.
|
|
61
|
+
"""
|
|
62
|
+
# --- configuration errors (signing_key_missing TrainingError subclass) ---
|
|
63
|
+
try:
|
|
64
|
+
from recotem.training.errors import (
|
|
65
|
+
TrainingError as _TrainingError, # noqa: PLC0415
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if isinstance(exc, _TrainingError) and getattr(exc, "code", "") in (
|
|
69
|
+
"signing_key_missing",
|
|
70
|
+
):
|
|
71
|
+
return _EXIT_CONFIG
|
|
72
|
+
except (ImportError, AttributeError):
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
# --- recipe errors ---
|
|
76
|
+
try:
|
|
77
|
+
from recotem.recipe.errors import RecipeError as _RecipeError # noqa: PLC0415
|
|
78
|
+
|
|
79
|
+
if isinstance(exc, _RecipeError):
|
|
80
|
+
return _EXIT_RECIPE
|
|
81
|
+
except ImportError:
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
# --- HTTP fetch errors (checked BEFORE DataSourceError so that a
|
|
85
|
+
# DataSourceError wrapping an HttpFetchError still maps to exit 7).
|
|
86
|
+
# CronJob retry semantics distinguish transient HTTP/SSRF failures (7)
|
|
87
|
+
# from structural data-source failures (3).
|
|
88
|
+
try:
|
|
89
|
+
from recotem._http_fetch import (
|
|
90
|
+
HttpFetchError as _HttpFetchError, # noqa: PLC0415
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Walk the __cause__ chain — datasource layers wrap HttpFetchError
|
|
94
|
+
# into DataSourceError via ``raise DataSourceError(...) from exc``.
|
|
95
|
+
cur: BaseException | None = exc
|
|
96
|
+
while cur is not None:
|
|
97
|
+
if isinstance(cur, _HttpFetchError):
|
|
98
|
+
return _EXIT_HTTP_FETCH
|
|
99
|
+
cur = cur.__cause__
|
|
100
|
+
except (ImportError, AttributeError):
|
|
101
|
+
pass
|
|
102
|
+
|
|
103
|
+
# --- datasource errors ---
|
|
104
|
+
try:
|
|
105
|
+
from recotem.datasource.base import (
|
|
106
|
+
DataSourceError as _DataSourceError, # noqa: PLC0415
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if isinstance(exc, _DataSourceError):
|
|
110
|
+
return _EXIT_DATASOURCE
|
|
111
|
+
except ImportError:
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
# --- config errors (must come before ArtifactError so that a signing-key
|
|
115
|
+
# misconfiguration on the serve path exits 8, not 5) ---
|
|
116
|
+
try:
|
|
117
|
+
from recotem.config import ConfigError as _ConfigError # noqa: PLC0415
|
|
118
|
+
|
|
119
|
+
if isinstance(exc, _ConfigError):
|
|
120
|
+
return _EXIT_CONFIG
|
|
121
|
+
except ImportError:
|
|
122
|
+
pass
|
|
123
|
+
|
|
124
|
+
# --- artifact errors ---
|
|
125
|
+
try:
|
|
126
|
+
from recotem.artifact.format import (
|
|
127
|
+
ArtifactError as _ArtifactError, # noqa: PLC0415
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
if isinstance(exc, _ArtifactError):
|
|
131
|
+
return _EXIT_ARTIFACT
|
|
132
|
+
except ImportError:
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
# --- lock contested ---
|
|
136
|
+
try:
|
|
137
|
+
from recotem.training.lock import (
|
|
138
|
+
LockContestedError as _LockContestedError, # noqa: PLC0415
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if isinstance(exc, _LockContestedError):
|
|
142
|
+
return _EXIT_LOCK_CONTESTED
|
|
143
|
+
except (ImportError, AttributeError):
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
# --- general training errors ---
|
|
147
|
+
try:
|
|
148
|
+
from recotem.training.errors import (
|
|
149
|
+
TrainingError as _TrainingError2, # noqa: PLC0415
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
if isinstance(exc, _TrainingError2):
|
|
153
|
+
return _EXIT_TRAINING
|
|
154
|
+
except (ImportError, AttributeError):
|
|
155
|
+
pass
|
|
156
|
+
|
|
157
|
+
return _EXIT_UNKNOWN
|