weaverstack 0.1.1__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.
- weaver/__init__.py +59 -0
- weaver/build_bundle/__init__.py +109 -0
- weaver/build_bundle/aliases.py +325 -0
- weaver/build_bundle/bundle.py +359 -0
- weaver/build_bundle/catalogue_actions.py +275 -0
- weaver/build_bundle/changes.py +186 -0
- weaver/build_bundle/endpoints.py +83 -0
- weaver/build_bundle/executors/__init__.py +69 -0
- weaver/build_bundle/executors/alias.py +202 -0
- weaver/build_bundle/executors/base.py +132 -0
- weaver/build_bundle/executors/folder.py +71 -0
- weaver/build_bundle/executors/load_file.py +205 -0
- weaver/build_bundle/executors/spark_case.py +26 -0
- weaver/build_bundle/executors/spark_schema.py +60 -0
- weaver/build_bundle/executors/spark_sql.py +59 -0
- weaver/build_bundle/executors/spark_sql_batch.py +57 -0
- weaver/build_bundle/executors/spark_table.py +213 -0
- weaver/build_bundle/executors/sql_endpoint_refresh.py +34 -0
- weaver/build_bundle/executors/tsql.py +81 -0
- weaver/build_bundle/incremental.py +288 -0
- weaver/build_bundle/installer.py +384 -0
- weaver/build_bundle/models.py +288 -0
- weaver/build_bundle/payloads.py +34 -0
- weaver/build_bundle/physical.py +625 -0
- weaver/build_bundle/planner.py +389 -0
- weaver/build_bundle/prune.py +620 -0
- weaver/build_bundle/report.py +108 -0
- weaver/build_bundle/stages.py +196 -0
- weaver/build_bundle/targets.py +272 -0
- weaver/build_bundle/workflow.py +585 -0
- weaver/catalogue/__init__.py +73 -0
- weaver/catalogue/builtin.py +238 -0
- weaver/catalogue/claims.py +121 -0
- weaver/catalogue/projection.py +437 -0
- weaver/catalogue/reader.py +152 -0
- weaver/catalogue/reconcile.py +231 -0
- weaver/catalogue/render.py +410 -0
- weaver/catalogue/state.py +660 -0
- weaver/catalogue/tables.py +648 -0
- weaver/config.py +178 -0
- weaver/declaration/__init__.py +171 -0
- weaver/declaration/columns.py +223 -0
- weaver/declaration/ddl.py +266 -0
- weaver/declaration/dependencies.py +544 -0
- weaver/declaration/graph.py +240 -0
- weaver/declaration/item_dependencies.py +292 -0
- weaver/declaration/load.py +191 -0
- weaver/declaration/metadata.py +1405 -0
- weaver/declaration/model.py +448 -0
- weaver/declaration/references.py +294 -0
- weaver/declaration/repository.py +959 -0
- weaver/declaration/schemas.py +135 -0
- weaver/declaration/source.py +674 -0
- weaver/declaration/spark_load.py +759 -0
- weaver/declaration/sql_shaping.py +591 -0
- weaver/declaration/templates/ddl/declared_create_table.sql +64 -0
- weaver/declaration/templates/ddl/infer_create_table.sql +97 -0
- weaver/declaration/templates/ddl/metadata_column_validation.sql +30 -0
- weaver/declaration/templates/load/column_metadata.sql +40 -0
- weaver/declaration/templates/load/full_replace_body.sql +21 -0
- weaver/declaration/templates/load/install_load_procedure.sql +27 -0
- weaver/declaration/templates/load/load_procedure.sql +48 -0
- weaver/declaration/templates/load/primary_key_body.sql +113 -0
- weaver/declaration/tsql_ddl.py +468 -0
- weaver/declaration/tsql_load.py +417 -0
- weaver/declaration/warehouse_type_mapping.yml +93 -0
- weaver/diagnostics.py +247 -0
- weaver/errors.py +61 -0
- weaver/etl.py +469 -0
- weaver/fabric/__init__.py +107 -0
- weaver/fabric/auth.py +137 -0
- weaver/fabric/capacity.py +143 -0
- weaver/fabric/client.py +147 -0
- weaver/fabric/environment.py +460 -0
- weaver/fabric/livy.py +478 -0
- weaver/fabric/notebooks.py +201 -0
- weaver/fabric/onelake.py +263 -0
- weaver/fabric/resolution.py +344 -0
- weaver/fabric/resources.py +245 -0
- weaver/fabric/session.py +148 -0
- weaver/fabric/shortcuts.py +120 -0
- weaver/fabric/sql.py +118 -0
- weaver/fabric/store.py +198 -0
- weaver/initialise.py +209 -0
- weaver/lakehouse.py +386 -0
- weaver/load.py +474 -0
- weaver/load_execution.py +483 -0
- weaver/load_plan.py +912 -0
- weaver/load_report.py +330 -0
- weaver/load_resolution.py +386 -0
- weaver/locations.py +164 -0
- weaver/objects.py +392 -0
- weaver/operations.py +757 -0
- weaver/physical_wipe.py +369 -0
- weaver/push.py +76 -0
- weaver/resolution.py +292 -0
- weaver/runtime/__init__.py +30 -0
- weaver/runtime/folder_load.py +402 -0
- weaver/runtime/load_contract.py +245 -0
- weaver/runtime/load_result.py +104 -0
- weaver/runtime/spark_load.py +152 -0
- weaver/runtime/table_load.py +497 -0
- weaver/spark/__init__.py +49 -0
- weaver/spark/catalogue.py +245 -0
- weaver/spark/destination.py +195 -0
- weaver/spark/session.py +84 -0
- weaver/spark/tokens.py +138 -0
- weaver/sql/__init__.py +40 -0
- weaver/sql/authentication.py +38 -0
- weaver/sql/connection.py +90 -0
- weaver/sql/errors.py +25 -0
- weaver/sql/execution.py +123 -0
- weaver/sql/pool.py +174 -0
- weaver/sql/wipe.py +156 -0
- weaver/store.py +209 -0
- weaver/targets.py +257 -0
- weaver/task_logging.py +215 -0
- weaver/unbind.py +74 -0
- weaver/workspaces.py +175 -0
- weaver_cli/__init__.py +12 -0
- weaver_cli/__main__.py +7 -0
- weaver_cli/main.py +626 -0
- weaverstack-0.1.1.dist-info/METADATA +113 -0
- weaverstack-0.1.1.dist-info/RECORD +127 -0
- weaverstack-0.1.1.dist-info/WHEEL +4 -0
- weaverstack-0.1.1.dist-info/entry_points.txt +2 -0
- weaverstack-0.1.1.dist-info/licenses/LICENSE +201 -0
weaver/load_report.py
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"""What a load run reports: statuses, messages and the shape returned to a caller.
|
|
2
|
+
|
|
3
|
+
The vocabulary layer of load orchestration, and it is deliberately the only one
|
|
4
|
+
that has no behaviour. Planning, resolution, execution and logging all produce
|
|
5
|
+
these values; nothing here produces anything.
|
|
6
|
+
|
|
7
|
+
**A message stream, not an error string.** A node can fail for several reasons at
|
|
8
|
+
once — its target is missing *and* the module it would import cannot be located —
|
|
9
|
+
and an orchestrator that flattened those into one string would be choosing which
|
|
10
|
+
half of the answer to keep. So every finding, whether the primitive returned it
|
|
11
|
+
or the orchestrator caught it, enters one stream of :class:`LoadMessage`, and a
|
|
12
|
+
node carries as many as it has.
|
|
13
|
+
|
|
14
|
+
**Dry-run statuses are not execution statuses.** A validated node has not run,
|
|
15
|
+
and calling it ``succeeded`` would put a claim in a report that nothing performed.
|
|
16
|
+
The two sets are kept apart here so the distinction cannot be lost downstream —
|
|
17
|
+
see :data:`VALIDATION_STATUSES` and :data:`EXECUTION_STATUSES`.
|
|
18
|
+
|
|
19
|
+
:class:`weaver.runtime.load_result.LoadResult` is re-exported rather than
|
|
20
|
+
redefined. A primitive already returns that shape on all four engines, and a
|
|
21
|
+
second dataclass meaning the same thing is exactly the drift the runtime module
|
|
22
|
+
exists to prevent.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from dataclasses import dataclass, field
|
|
28
|
+
from typing import Any, Mapping
|
|
29
|
+
|
|
30
|
+
from .runtime.load_result import LoadResult
|
|
31
|
+
|
|
32
|
+
# --- statuses ----------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
#: Planned but not started.
|
|
35
|
+
PENDING = "pending"
|
|
36
|
+
#: Dispatch began.
|
|
37
|
+
RUNNING = "running"
|
|
38
|
+
#: Completed successfully.
|
|
39
|
+
SUCCEEDED = "succeeded"
|
|
40
|
+
#: Valid work completed, but the primitive reported rejected rows.
|
|
41
|
+
SUCCEEDED_WITH_REJECTS = "succeeded_with_rejects"
|
|
42
|
+
#: The primitive or the dispatch around it failed.
|
|
43
|
+
FAILED = "failed"
|
|
44
|
+
#: An upstream dependency failed or could not be validated.
|
|
45
|
+
BLOCKED = "blocked"
|
|
46
|
+
#: Deliberately omitted by a planner or execution policy. Never used for failure
|
|
47
|
+
#: propagation — a node whose dependency failed is ``blocked``, and conflating
|
|
48
|
+
#: the two would make "nothing was wrong" and "something upstream broke" read the
|
|
49
|
+
#: same in a log.
|
|
50
|
+
SKIPPED = "skipped"
|
|
51
|
+
|
|
52
|
+
EXECUTION_STATUSES = (
|
|
53
|
+
PENDING,
|
|
54
|
+
RUNNING,
|
|
55
|
+
SUCCEEDED,
|
|
56
|
+
SUCCEEDED_WITH_REJECTS,
|
|
57
|
+
FAILED,
|
|
58
|
+
BLOCKED,
|
|
59
|
+
SKIPPED,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
#: A dry-run node's dispatch target and prerequisites were all resolved.
|
|
63
|
+
VALIDATED = "validated"
|
|
64
|
+
#: A dry-run node's own primitive or target could not be resolved.
|
|
65
|
+
INVALID = "invalid"
|
|
66
|
+
|
|
67
|
+
VALIDATION_STATUSES = (VALIDATED, INVALID, BLOCKED)
|
|
68
|
+
|
|
69
|
+
# --- final task statuses ------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
#: Every executable step succeeded without rejects.
|
|
72
|
+
TASK_SUCCEEDED = "succeeded"
|
|
73
|
+
#: Every executable branch completed, but a primitive reported rejects.
|
|
74
|
+
TASK_SUCCEEDED_WITH_REJECTS = "succeeded_with_rejects"
|
|
75
|
+
#: At least one branch succeeded and at least one failed or was blocked.
|
|
76
|
+
TASK_PARTIALLY_SUCCEEDED = "partially_succeeded"
|
|
77
|
+
#: No requested branch completed, or fail-fast stopped the task.
|
|
78
|
+
TASK_FAILED = "failed"
|
|
79
|
+
#: A dry run could not resolve a valid executable plan.
|
|
80
|
+
TASK_INVALID = "invalid"
|
|
81
|
+
|
|
82
|
+
# --- message codes ------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
SEVERITY_ERROR = "error"
|
|
85
|
+
SEVERITY_WARNING = "warning"
|
|
86
|
+
SEVERITY_INFO = "info"
|
|
87
|
+
|
|
88
|
+
#: The primitive ran and refused rows.
|
|
89
|
+
PRIMITIVE_REJECTS = "primitive_rejects"
|
|
90
|
+
#: The primitive ran and reported failure in its own result.
|
|
91
|
+
PRIMITIVE_FAILURE = "primitive_failure"
|
|
92
|
+
#: Dispatch raised something the primitive did not normalise.
|
|
93
|
+
DISPATCH_EXCEPTION = "dispatch_exception"
|
|
94
|
+
#: The installed primitive could not be located.
|
|
95
|
+
DISPATCH_LOCATION_MISSING = "dispatch_location_missing"
|
|
96
|
+
#: The physical target the node loads into is not there.
|
|
97
|
+
TARGET_MISSING = "target_missing"
|
|
98
|
+
#: A deployed Python module could not be imported, or carries no expected class.
|
|
99
|
+
MODULE_IMPORT_FAILURE = "module_import_failure"
|
|
100
|
+
#: A primitive returned something that is not a load result.
|
|
101
|
+
RESULT_CONTRACT_INVALID = "result_contract_invalid"
|
|
102
|
+
#: The endpoint refresh could not be performed.
|
|
103
|
+
ENDPOINT_REFRESH_FAILURE = "endpoint_refresh_failure"
|
|
104
|
+
#: An upstream node failed or was invalid, so this one may not run.
|
|
105
|
+
DEPENDENCY_BLOCKED = "dependency_blocked"
|
|
106
|
+
#: The catalogue's physical binding is missing, ambiguous or malformed.
|
|
107
|
+
CATALOGUE_BINDING_INVALID = "catalogue_binding_invalid"
|
|
108
|
+
#: The planned graph contains a cycle.
|
|
109
|
+
DAG_CYCLE = "dag_cycle"
|
|
110
|
+
#: A dependency named in the catalogue could not be resolved to anything.
|
|
111
|
+
DEPENDENCY_UNRESOLVED = "dependency_unresolved"
|
|
112
|
+
#: A reference Weaver deliberately does not follow — a fully qualified physical
|
|
113
|
+
#: read that names something outside the estate's own logical graph.
|
|
114
|
+
DEPENDENCY_EXTERNAL = "dependency_external"
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@dataclass(frozen=True)
|
|
118
|
+
class LoadMessage:
|
|
119
|
+
"""One finding about one node, or about the run as a whole.
|
|
120
|
+
|
|
121
|
+
``source`` says who noticed: the primitive that ran, or the orchestrator
|
|
122
|
+
around it. Both enter the same stream deliberately — a caller reading a
|
|
123
|
+
node's messages should not have to know which layer wrote each one to see
|
|
124
|
+
everything that was wrong with it.
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
severity: str
|
|
128
|
+
code: str
|
|
129
|
+
message: str
|
|
130
|
+
detail: str | None = None
|
|
131
|
+
source: str | None = None
|
|
132
|
+
|
|
133
|
+
def to_mapping(self) -> dict[str, Any]:
|
|
134
|
+
return {
|
|
135
|
+
"severity": self.severity,
|
|
136
|
+
"code": self.code,
|
|
137
|
+
"message": self.message,
|
|
138
|
+
"detail": self.detail,
|
|
139
|
+
"source": self.source,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def error(code: str, message: str, **extra: str | None) -> LoadMessage:
|
|
144
|
+
return LoadMessage(SEVERITY_ERROR, code, message, **extra)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def warning(code: str, message: str, **extra: str | None) -> LoadMessage:
|
|
148
|
+
return LoadMessage(SEVERITY_WARNING, code, message, **extra)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def info(code: str, message: str, **extra: str | None) -> LoadMessage:
|
|
152
|
+
return LoadMessage(SEVERITY_INFO, code, message, **extra)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@dataclass(frozen=True)
|
|
156
|
+
class LoadNodeReport:
|
|
157
|
+
"""What became of one planned node.
|
|
158
|
+
|
|
159
|
+
``executed`` is separate from ``status`` and has to be: a dry run reports
|
|
160
|
+
``validated`` having executed nothing, and a real run reports ``blocked``
|
|
161
|
+
having executed nothing either. A reader asking "did this touch the target?"
|
|
162
|
+
is asking about ``executed``, and no status answers it on its own.
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
node_id: str
|
|
166
|
+
logical_id: str | None
|
|
167
|
+
physical_target: str
|
|
168
|
+
primitive_kind: str
|
|
169
|
+
dispatch_location: str | None
|
|
170
|
+
status: str
|
|
171
|
+
executed: bool = False
|
|
172
|
+
messages: tuple[LoadMessage, ...] = ()
|
|
173
|
+
result: LoadResult | None = None
|
|
174
|
+
started_at: str | None = None
|
|
175
|
+
finished_at: str | None = None
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def succeeded(self) -> bool:
|
|
179
|
+
return self.status in (SUCCEEDED, VALIDATED)
|
|
180
|
+
|
|
181
|
+
def to_mapping(self) -> dict[str, Any]:
|
|
182
|
+
return {
|
|
183
|
+
"node_id": self.node_id,
|
|
184
|
+
"logical_id": self.logical_id,
|
|
185
|
+
"physical_target": self.physical_target,
|
|
186
|
+
"primitive_kind": self.primitive_kind,
|
|
187
|
+
"dispatch_location": self.dispatch_location,
|
|
188
|
+
"status": self.status,
|
|
189
|
+
"executed": self.executed,
|
|
190
|
+
"started_at": self.started_at,
|
|
191
|
+
"finished_at": self.finished_at,
|
|
192
|
+
"rows": None if self.result is None else _counts(self.result),
|
|
193
|
+
"messages": [message.to_mapping() for message in self.messages],
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _counts(result: LoadResult) -> dict[str, int]:
|
|
198
|
+
return {
|
|
199
|
+
"rows_read": result.rows_read,
|
|
200
|
+
"rows_inserted": result.rows_inserted,
|
|
201
|
+
"rows_updated": result.rows_updated,
|
|
202
|
+
"rows_deleted": result.rows_deleted,
|
|
203
|
+
"rows_rejected": result.rows_rejected,
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
@dataclass(frozen=True)
|
|
208
|
+
class LoadRunReport:
|
|
209
|
+
"""One ``weaver.load(...)`` invocation, whole.
|
|
210
|
+
|
|
211
|
+
The same shape whether or not anything ran, which is what lets a dry run be
|
|
212
|
+
inspected exactly as a real run is. ``task_id`` and ``task_log`` are absent
|
|
213
|
+
for a dry run, and their absence is the report saying so — dry runs write no
|
|
214
|
+
evidence, so there is none to point at.
|
|
215
|
+
"""
|
|
216
|
+
|
|
217
|
+
requested: tuple[str, ...]
|
|
218
|
+
status: str
|
|
219
|
+
dry_run: bool
|
|
220
|
+
fault_tolerant: bool
|
|
221
|
+
nodes: tuple[LoadNodeReport, ...] = ()
|
|
222
|
+
edges: tuple[tuple[str, str], ...] = ()
|
|
223
|
+
order: tuple[str, ...] = ()
|
|
224
|
+
messages: tuple[LoadMessage, ...] = ()
|
|
225
|
+
task_id: str | None = None
|
|
226
|
+
task_log: str | None = None
|
|
227
|
+
started_at: str | None = None
|
|
228
|
+
finished_at: str | None = None
|
|
229
|
+
workspace: str | None = None
|
|
230
|
+
|
|
231
|
+
@property
|
|
232
|
+
def succeeded(self) -> bool:
|
|
233
|
+
return self.status in (TASK_SUCCEEDED, TASK_SUCCEEDED_WITH_REJECTS)
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def by_node(self) -> Mapping[str, LoadNodeReport]:
|
|
237
|
+
return {node.node_id: node for node in self.nodes}
|
|
238
|
+
|
|
239
|
+
def to_mapping(self) -> dict[str, Any]:
|
|
240
|
+
return {
|
|
241
|
+
"requested": list(self.requested),
|
|
242
|
+
"status": self.status,
|
|
243
|
+
"dry_run": self.dry_run,
|
|
244
|
+
"fault_tolerant": self.fault_tolerant,
|
|
245
|
+
"workspace": self.workspace,
|
|
246
|
+
"task_id": self.task_id,
|
|
247
|
+
"task_log": self.task_log,
|
|
248
|
+
"started_at": self.started_at,
|
|
249
|
+
"finished_at": self.finished_at,
|
|
250
|
+
"order": list(self.order),
|
|
251
|
+
"edges": [list(edge) for edge in self.edges],
|
|
252
|
+
"nodes": [node.to_mapping() for node in self.nodes],
|
|
253
|
+
"messages": [message.to_mapping() for message in self.messages],
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def final_status(nodes: tuple[LoadNodeReport, ...], *, dry_run: bool) -> str:
|
|
258
|
+
"""The task status these node reports add up to.
|
|
259
|
+
|
|
260
|
+
Derived rather than accumulated, so the summary cannot disagree with the
|
|
261
|
+
nodes it summarises — the failure mode of a status advanced by hand as the
|
|
262
|
+
run proceeds.
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
if not nodes:
|
|
266
|
+
return TASK_INVALID if dry_run else TASK_SUCCEEDED
|
|
267
|
+
statuses = [node.status for node in nodes]
|
|
268
|
+
if dry_run:
|
|
269
|
+
return TASK_INVALID if any(
|
|
270
|
+
status in (INVALID, BLOCKED) for status in statuses
|
|
271
|
+
) else TASK_SUCCEEDED
|
|
272
|
+
bad = [status for status in statuses if status in (FAILED, BLOCKED)]
|
|
273
|
+
good = [
|
|
274
|
+
status
|
|
275
|
+
for status in statuses
|
|
276
|
+
if status in (SUCCEEDED, SUCCEEDED_WITH_REJECTS, SKIPPED)
|
|
277
|
+
]
|
|
278
|
+
if not bad:
|
|
279
|
+
return (
|
|
280
|
+
TASK_SUCCEEDED_WITH_REJECTS
|
|
281
|
+
if SUCCEEDED_WITH_REJECTS in statuses
|
|
282
|
+
else TASK_SUCCEEDED
|
|
283
|
+
)
|
|
284
|
+
if good:
|
|
285
|
+
return TASK_PARTIALLY_SUCCEEDED
|
|
286
|
+
return TASK_FAILED
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
__all__ = [
|
|
290
|
+
"BLOCKED",
|
|
291
|
+
"DAG_CYCLE",
|
|
292
|
+
"DEPENDENCY_BLOCKED",
|
|
293
|
+
"DEPENDENCY_EXTERNAL",
|
|
294
|
+
"DEPENDENCY_UNRESOLVED",
|
|
295
|
+
"DISPATCH_EXCEPTION",
|
|
296
|
+
"DISPATCH_LOCATION_MISSING",
|
|
297
|
+
"ENDPOINT_REFRESH_FAILURE",
|
|
298
|
+
"EXECUTION_STATUSES",
|
|
299
|
+
"FAILED",
|
|
300
|
+
"INVALID",
|
|
301
|
+
"CATALOGUE_BINDING_INVALID",
|
|
302
|
+
"LoadMessage",
|
|
303
|
+
"LoadNodeReport",
|
|
304
|
+
"LoadResult",
|
|
305
|
+
"LoadRunReport",
|
|
306
|
+
"MODULE_IMPORT_FAILURE",
|
|
307
|
+
"PENDING",
|
|
308
|
+
"PRIMITIVE_FAILURE",
|
|
309
|
+
"PRIMITIVE_REJECTS",
|
|
310
|
+
"RESULT_CONTRACT_INVALID",
|
|
311
|
+
"RUNNING",
|
|
312
|
+
"SEVERITY_ERROR",
|
|
313
|
+
"SEVERITY_INFO",
|
|
314
|
+
"SEVERITY_WARNING",
|
|
315
|
+
"SKIPPED",
|
|
316
|
+
"SUCCEEDED",
|
|
317
|
+
"SUCCEEDED_WITH_REJECTS",
|
|
318
|
+
"TARGET_MISSING",
|
|
319
|
+
"TASK_FAILED",
|
|
320
|
+
"TASK_INVALID",
|
|
321
|
+
"TASK_PARTIALLY_SUCCEEDED",
|
|
322
|
+
"TASK_SUCCEEDED",
|
|
323
|
+
"TASK_SUCCEEDED_WITH_REJECTS",
|
|
324
|
+
"VALIDATED",
|
|
325
|
+
"VALIDATION_STATUSES",
|
|
326
|
+
"error",
|
|
327
|
+
"final_status",
|
|
328
|
+
"info",
|
|
329
|
+
"warning",
|
|
330
|
+
]
|