wizata-dsapi 2.1.0.dev12__tar.gz → 2.1.0.dev14__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 (67) hide show
  1. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/PKG-INFO +1 -1
  2. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/__init__.py +6 -0
  3. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/context.py +3 -1
  4. wizata_dsapi-2.1.0.dev14/wizata_dsapi/deployment.py +237 -0
  5. wizata_dsapi-2.1.0.dev14/wizata_dsapi/version.py +1 -0
  6. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi.egg-info/PKG-INFO +1 -1
  7. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi.egg-info/SOURCES.txt +1 -0
  8. wizata_dsapi-2.1.0.dev12/wizata_dsapi/version.py +0 -1
  9. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/LICENSE.txt +0 -0
  10. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/README.rst +0 -0
  11. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/setup.cfg +0 -0
  12. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/setup.py +0 -0
  13. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/api_config.py +0 -0
  14. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/api_dto.py +0 -0
  15. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/api_interface.py +0 -0
  16. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/bucket.py +0 -0
  17. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/business_label.py +0 -0
  18. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/dashboard.py +0 -0
  19. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/dataframe_toolkit.py +0 -0
  20. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/datapoint.py +0 -0
  21. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/datastore.py +0 -0
  22. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/ds_dataframe.py +0 -0
  23. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/dsapi_json_encoder.py +0 -0
  24. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/edge_config.py +0 -0
  25. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/edge_device.py +0 -0
  26. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/edge_module.py +0 -0
  27. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/evaluation.py +0 -0
  28. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/execution.py +0 -0
  29. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/execution_log.py +0 -0
  30. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/experiment.py +0 -0
  31. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/graylog_log.py +0 -0
  32. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/group_system.py +0 -0
  33. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/ilogger.py +0 -0
  34. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/insight.py +0 -0
  35. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/mlmodel.py +0 -0
  36. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/mobile_asset.py +0 -0
  37. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/model_toolkit.py +0 -0
  38. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/models/__init__.py +0 -0
  39. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/models/common.py +0 -0
  40. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/notification.py +0 -0
  41. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/paged_query_result.py +0 -0
  42. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/pipeline.py +0 -0
  43. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/pipeline_image.py +0 -0
  44. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/plot.py +0 -0
  45. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/plots/__init__.py +0 -0
  46. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/plots/common.py +0 -0
  47. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/plots/theme.py +0 -0
  48. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/request.py +0 -0
  49. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/script.py +0 -0
  50. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/scripts/__init__.py +0 -0
  51. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/scripts/common.py +0 -0
  52. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/search.py +0 -0
  53. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/solution_component.py +0 -0
  54. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/streamlit_utils.py +0 -0
  55. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/template.py +0 -0
  56. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/template_config.py +0 -0
  57. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/trigger.py +0 -0
  58. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/twin.py +0 -0
  59. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/twinregistration.py +0 -0
  60. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/user.py +0 -0
  61. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/wizard_function.py +0 -0
  62. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/wizard_request.py +0 -0
  63. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/wizata_dsapi_client.py +0 -0
  64. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi/words.py +0 -0
  65. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi.egg-info/dependency_links.txt +0 -0
  66. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi.egg-info/requires.txt +0 -0
  67. {wizata_dsapi-2.1.0.dev12 → wizata_dsapi-2.1.0.dev14}/wizata_dsapi.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wizata_dsapi
3
- Version: 2.1.0.dev12
3
+ Version: 2.1.0.dev14
4
4
  Summary: Wizata Data Science Toolkit
5
5
  Author: Wizata S.A.
6
6
  Author-email: info@wizata.com
@@ -15,6 +15,12 @@ from .solution_component import SolutionComponent, SolutionType
15
15
  from .business_label import BusinessLabel
16
16
  from .twinregistration import TwinRegistration, TwinRegistrationProperty
17
17
  from .trigger import Trigger, validate_trigger_branch
18
+ from .deployment import (
19
+ Deployment,
20
+ DeploymentStatus,
21
+ DeploymentStep,
22
+ StepStatus,
23
+ )
18
24
  from .group_system import GroupSystem
19
25
  from .bucket import Bucket
20
26
 
@@ -43,7 +43,9 @@ class Context(ILogger):
43
43
  :ivar dict dataframes: dict of all dataframes parameters and generated by previously executed steps.
44
44
  :ivar dict datapoints: wizata_dsapi.Datapoint for each name (key) used in queries.
45
45
  :ivar uuid.UUID execution_id: Execution ID currently processed.
46
- :ivar grafana_client.GrafanaApi grafana_api: instance of grafana api.
46
+ :ivar grafana_client.GrafanaApi grafana_api: instance of grafana api - set only when the
47
+ OPTIONAL grafana-client library (>=3.5.0) is installed alongside the platform,
48
+ None otherwise (DEV-5972).
47
49
  :ivar dict models: dict of all models generated by previously executed steps.
48
50
  :ivar datetime now: Now timestamp as used by the pipeline.
49
51
  :ivar uuid.UUID pipeline_id: Pipeline ID associated with the ongoing execution.
@@ -0,0 +1,237 @@
1
+ """
2
+ Deployment — one attempt at putting a pipeline version into production (DEV-5960).
3
+
4
+ The front-end fires a single call and polls; the DS API owns the whole sequence
5
+ (merge, release cut, image build, trigger). That sequence cannot be synchronous — an
6
+ image build can outlast the gateway timeout — so it needs somewhere to record what
7
+ was asked for, how far it got, and why it stopped. This is that record.
8
+
9
+ Design notes:
10
+
11
+ * Steps are explicit rather than inferred from a status enum. A deployment that
12
+ merged and cut a release but failed to build an image is a very different thing to
13
+ recover from than one that never started, and an operator should be able to see
14
+ which without reading logs.
15
+ * The manifest is stored as executed, so the record answers "what did this deployment
16
+ actually do" later, when the plan that produced it is long gone.
17
+ * Nothing here decides policy. Validation lives in the planner; this only carries
18
+ state.
19
+ * It doubles as the pause switch for a schedule. Since the DS API owns the trigger's
20
+ lifecycle, pausing a deployment deletes its trigger and resuming recreates it from
21
+ the stored manifest — which is why the record keeps release, sha, image and
22
+ manifest even after it has completed. The trigger has no enabled flag of its own
23
+ (deferred on the backend, DEV-5962), so without this a schedule could only be
24
+ stopped by deleting it and rebuilding it from memory later.
25
+ """
26
+ import json
27
+ import uuid
28
+ from datetime import datetime
29
+ from enum import Enum
30
+
31
+ from .api_dto import ApiDto
32
+
33
+
34
+ def _epoch_ms(value):
35
+ """
36
+ Timestamps go out as epoch milliseconds, like every other DTO here.
37
+
38
+ Postgres hands back a ``datetime`` (the table stamps createdDate/updatedDate
39
+ server-side), so a record read from the database would otherwise serialize a
40
+ datetime the API cannot marshal. Ints pass through unchanged, which keeps a
41
+ JSON round-trip stable.
42
+ """
43
+ if isinstance(value, datetime):
44
+ return int(value.timestamp() * 1000)
45
+ return value
46
+
47
+
48
+ class DeploymentStatus(Enum):
49
+ """
50
+ Lifecycle of a deployment attempt.
51
+
52
+ PAUSED is what makes a schedule stoppable at all. The trigger itself has no
53
+ enabled flag — that was deferred on the backend (DEV-5962) — but the DS API
54
+ creates and deletes the trigger as part of a deployment, so pausing can be
55
+ expressed here instead: pause DELETES the trigger and keeps this record, which
56
+ still holds the release, sha, image and manifest, so resuming recreates the same
57
+ schedule rather than asking the user to rebuild it from memory. Before this, the
58
+ only way to stop a schedule was to delete it and remember what it was.
59
+ """
60
+ PENDING = "pending" # accepted, nothing done yet
61
+ DEPLOYING = "deploying" # steps in progress — the DEPLOYMENT is working, which
62
+ # says nothing about whether a pipeline is executing
63
+ DEPLOYED = "deployed" # every planned step done, schedule live
64
+ PAUSED = "paused" # deployed, trigger removed on purpose; resumable
65
+ FAILED = "failed" # a step failed; `error` says which and why
66
+
67
+
68
+ class DeploymentStep(Enum):
69
+ """The ordered steps a deployment may perform. Not all apply to every plan."""
70
+ MERGE = "merge" # feature branch -> default branch
71
+ RELEASE = "release" # cut/advance release/<name>
72
+ IMAGE = "image" # build an image pinned to the release sha
73
+ TRIGGER = "trigger" # create or update the schedule
74
+
75
+
76
+ class StepStatus(Enum):
77
+ SKIPPED = "skipped" # not part of this plan (e.g. no merge when deploying master)
78
+ PENDING = "pending"
79
+ COMPLETED = "completed"
80
+ FAILED = "failed"
81
+
82
+
83
+ class Deployment(ApiDto):
84
+ """
85
+ A deployment attempt and its progress.
86
+
87
+ :ivar uuid.UUID deployment_id: technical id, what the front-end polls on.
88
+ :ivar str pipeline_key: pipeline being deployed.
89
+ :ivar uuid.UUID pipeline_id: its technical id.
90
+ :ivar str source: ref the user deployed FROM (feature/..., master, release/...).
91
+ :ivar str release: the release ref this deployment produces or reuses.
92
+ :ivar str sha: commit the release resolves to — what actually runs.
93
+ :ivar str packaging: 'image' (frozen artifact) or 'release' (run from the branch).
94
+ :ivar str image_id: built image, when packaging='image'.
95
+ :ivar uuid.UUID trigger_id: schedule created or updated at the end.
96
+ :ivar DeploymentStatus status: overall state — pending / deploying / deployed /
97
+ paused / failed. Deliberately not "running" or "completed": a user reads those
98
+ as "is my pipeline executing", which is a different question entirely.
99
+ :ivar list steps: [{'step','status','detail'}] in execution order.
100
+ :ivar str error: failure reason when status is FAILED.
101
+ :ivar dict manifest: the deploy request as executed.
102
+ :ivar str created_by: email of the user who launched it.
103
+ :ivar int createdDate: timestamp ms.
104
+ :ivar int updatedDate: timestamp ms.
105
+ """
106
+
107
+ @classmethod
108
+ def route(cls):
109
+ return "deployments"
110
+
111
+ @classmethod
112
+ def from_dict(cls, data):
113
+ obj = Deployment()
114
+ obj.from_json(data)
115
+ return obj
116
+
117
+ def __init__(self,
118
+ deployment_id: uuid.UUID = None,
119
+ pipeline_key: str = None,
120
+ pipeline_id: uuid.UUID = None,
121
+ source: str = None,
122
+ release: str = None,
123
+ sha: str = None,
124
+ packaging: str = None,
125
+ image_id: str = None,
126
+ trigger_id: uuid.UUID = None,
127
+ status: DeploymentStatus = None,
128
+ steps: list = None,
129
+ error: str = None,
130
+ manifest: dict = None,
131
+ created_by: str = None):
132
+ if deployment_id is None:
133
+ deployment_id = uuid.uuid4()
134
+ self.deployment_id = deployment_id
135
+ self.pipeline_key = pipeline_key
136
+ self.pipeline_id = pipeline_id
137
+ self.source = source
138
+ self.release = release
139
+ self.sha = sha
140
+ self.packaging = packaging
141
+ self.image_id = image_id
142
+ self.trigger_id = trigger_id
143
+ self.status = status or DeploymentStatus.PENDING
144
+ self.steps = steps if steps is not None else []
145
+ self.error = error
146
+ self.manifest = manifest
147
+ self.created_by = created_by
148
+ self.createdDate = None
149
+ self.updatedDate = None
150
+
151
+ def api_id(self) -> str:
152
+ return str(self.deployment_id).upper()
153
+
154
+ def endpoint(self) -> str:
155
+ return "Deployments"
156
+
157
+ # ------------------------------------------------------------------ steps
158
+
159
+ def set_step(self, step: DeploymentStep, status: StepStatus, detail=None) -> None:
160
+ """
161
+ Record a step's outcome, replacing any previous entry for it so a retry
162
+ does not append duplicates.
163
+ """
164
+ entry = {"step": step.value, "status": status.value}
165
+ if detail is not None:
166
+ entry["detail"] = detail
167
+ for index, existing in enumerate(self.steps):
168
+ if existing.get("step") == step.value:
169
+ self.steps[index] = entry
170
+ return
171
+ self.steps.append(entry)
172
+
173
+ def step_status(self, step: DeploymentStep) -> StepStatus | None:
174
+ for existing in self.steps:
175
+ if existing.get("step") == step.value:
176
+ return StepStatus(existing["status"])
177
+ return None
178
+
179
+ def is_done(self, step: DeploymentStep) -> bool:
180
+ """True when a step needs no further work — completed or not planned."""
181
+ return self.step_status(step) in (StepStatus.COMPLETED, StepStatus.SKIPPED)
182
+
183
+ # ------------------------------------------------------------------ serialization
184
+
185
+ def from_json(self, obj):
186
+ if "id" in obj.keys() and obj["id"] is not None:
187
+ self.deployment_id = uuid.UUID(str(obj["id"]))
188
+ if "pipelineKey" in obj.keys():
189
+ self.pipeline_key = obj["pipelineKey"]
190
+ if "pipelineId" in obj.keys() and obj["pipelineId"] is not None:
191
+ self.pipeline_id = uuid.UUID(str(obj["pipelineId"]))
192
+ for field, attribute in (("source", "source"), ("release", "release"),
193
+ ("sha", "sha"), ("packaging", "packaging"),
194
+ ("imageId", "image_id"), ("error", "error"),
195
+ ("createdBy", "created_by")):
196
+ if field in obj.keys() and obj[field] is not None:
197
+ setattr(self, attribute, obj[field])
198
+ if "triggerId" in obj.keys() and obj["triggerId"] is not None:
199
+ self.trigger_id = uuid.UUID(str(obj["triggerId"]))
200
+ if "status" in obj.keys() and obj["status"] is not None:
201
+ self.status = DeploymentStatus(obj["status"])
202
+ if "steps" in obj.keys() and obj["steps"] is not None:
203
+ steps = obj["steps"]
204
+ self.steps = json.loads(steps) if isinstance(steps, str) else steps
205
+ if "manifest" in obj.keys() and obj["manifest"] is not None:
206
+ manifest = obj["manifest"]
207
+ self.manifest = json.loads(manifest) if isinstance(manifest, str) else manifest
208
+ if "createdDate" in obj.keys() and obj["createdDate"] is not None:
209
+ self.createdDate = obj["createdDate"]
210
+ if "updatedDate" in obj.keys() and obj["updatedDate"] is not None:
211
+ self.updatedDate = obj["updatedDate"]
212
+
213
+ def to_json(self, target: str = None):
214
+ obj = {
215
+ "id": str(self.deployment_id),
216
+ "status": self.status.value if self.status else None,
217
+ "steps": self.steps,
218
+ }
219
+ if self.pipeline_key is not None:
220
+ obj["pipelineKey"] = self.pipeline_key
221
+ if self.pipeline_id is not None:
222
+ obj["pipelineId"] = str(self.pipeline_id)
223
+ for field, value in (("source", self.source), ("release", self.release),
224
+ ("sha", self.sha), ("packaging", self.packaging),
225
+ ("imageId", self.image_id), ("error", self.error),
226
+ ("createdBy", self.created_by)):
227
+ if value is not None:
228
+ obj[field] = value
229
+ if self.trigger_id is not None:
230
+ obj["triggerId"] = str(self.trigger_id)
231
+ if self.manifest is not None:
232
+ obj["manifest"] = self.manifest
233
+ if self.createdDate is not None:
234
+ obj["createdDate"] = _epoch_ms(self.createdDate)
235
+ if self.updatedDate is not None:
236
+ obj["updatedDate"] = _epoch_ms(self.updatedDate)
237
+ return obj
@@ -0,0 +1 @@
1
+ __version__ = "2.1.0.dev14"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wizata_dsapi
3
- Version: 2.1.0.dev12
3
+ Version: 2.1.0.dev14
4
4
  Summary: Wizata Data Science Toolkit
5
5
  Author: Wizata S.A.
6
6
  Author-email: info@wizata.com
@@ -12,6 +12,7 @@ wizata_dsapi/dashboard.py
12
12
  wizata_dsapi/dataframe_toolkit.py
13
13
  wizata_dsapi/datapoint.py
14
14
  wizata_dsapi/datastore.py
15
+ wizata_dsapi/deployment.py
15
16
  wizata_dsapi/ds_dataframe.py
16
17
  wizata_dsapi/dsapi_json_encoder.py
17
18
  wizata_dsapi/edge_config.py
@@ -1 +0,0 @@
1
- __version__ = "2.1.0.dev12"