wizata-dsapi 2.1.0.dev16__tar.gz → 2.1.0.dev18__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 (68) hide show
  1. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/PKG-INFO +1 -1
  2. wizata_dsapi-2.1.0.dev18/wizata_dsapi/plot.py +104 -0
  3. wizata_dsapi-2.1.0.dev18/wizata_dsapi/version.py +1 -0
  4. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/wizata_dsapi_client.py +90 -1
  5. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi.egg-info/PKG-INFO +1 -1
  6. wizata_dsapi-2.1.0.dev16/wizata_dsapi/plot.py +0 -70
  7. wizata_dsapi-2.1.0.dev16/wizata_dsapi/version.py +0 -1
  8. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/LICENSE.txt +0 -0
  9. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/README.rst +0 -0
  10. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/setup.cfg +0 -0
  11. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/setup.py +0 -0
  12. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/__init__.py +0 -0
  13. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/api_config.py +0 -0
  14. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/api_dto.py +0 -0
  15. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/api_interface.py +0 -0
  16. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/bucket.py +0 -0
  17. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/business_label.py +0 -0
  18. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/context.py +0 -0
  19. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/dashboard.py +0 -0
  20. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/dataframe_toolkit.py +0 -0
  21. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/datapoint.py +0 -0
  22. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/datastore.py +0 -0
  23. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/deployment.py +0 -0
  24. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/ds_dataframe.py +0 -0
  25. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/dsapi_json_encoder.py +0 -0
  26. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/edge_config.py +0 -0
  27. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/edge_device.py +0 -0
  28. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/edge_module.py +0 -0
  29. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/evaluation.py +0 -0
  30. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/execution.py +0 -0
  31. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/execution_log.py +0 -0
  32. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/experiment.py +0 -0
  33. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/graylog_log.py +0 -0
  34. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/group_system.py +0 -0
  35. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/ilogger.py +0 -0
  36. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/insight.py +0 -0
  37. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/mlmodel.py +0 -0
  38. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/mobile_asset.py +0 -0
  39. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/model_toolkit.py +0 -0
  40. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/models/__init__.py +0 -0
  41. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/models/common.py +0 -0
  42. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/notification.py +0 -0
  43. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/paged_query_result.py +0 -0
  44. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/pipeline.py +0 -0
  45. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/pipeline_image.py +0 -0
  46. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/plots/__init__.py +0 -0
  47. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/plots/common.py +0 -0
  48. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/plots/theme.py +0 -0
  49. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/request.py +0 -0
  50. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/script.py +0 -0
  51. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/scripts/__init__.py +0 -0
  52. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/scripts/common.py +0 -0
  53. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/search.py +0 -0
  54. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/solution_component.py +0 -0
  55. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/streamlit_utils.py +0 -0
  56. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/template.py +0 -0
  57. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/template_config.py +0 -0
  58. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/trigger.py +0 -0
  59. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/twin.py +0 -0
  60. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/twinregistration.py +0 -0
  61. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/user.py +0 -0
  62. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/wizard_function.py +0 -0
  63. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/wizard_request.py +0 -0
  64. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi/words.py +0 -0
  65. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi.egg-info/SOURCES.txt +0 -0
  66. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi.egg-info/dependency_links.txt +0 -0
  67. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/wizata_dsapi.egg-info/requires.txt +0 -0
  68. {wizata_dsapi-2.1.0.dev16 → wizata_dsapi-2.1.0.dev18}/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.dev16
3
+ Version: 2.1.0.dev18
4
4
  Summary: Wizata Data Science Toolkit
5
5
  Author: Wizata S.A.
6
6
  Author-email: info@wizata.com
@@ -0,0 +1,104 @@
1
+ import uuid
2
+ from .api_dto import ApiDto
3
+
4
+
5
+ class Plot(ApiDto):
6
+ """
7
+ A plot is a definition of a Plotly figure that can be stored and shared on Wizata.
8
+ :ivar plot_id: The UUID of the plot. None for a deployed plot, which is addressed
9
+ by ``key`` instead — see below.
10
+ :ivar name: A simple name helping the user identifying the plot.
11
+ :ivar figure: Plotly figure defining the plot itself.
12
+ :ivar key: DEV-6026 — the deterministic identity of a DEPLOYED plot,
13
+ ``<pipeline key>/<twin key>/<plot script>.<input dataframe>``. An experiment
14
+ plot is one blob per execution addressed by ``plot_id`` and fetched with
15
+ ``GET /plots/<id>/``; a deployed plot is one blob per (pipeline, twin, plot
16
+ step) that is overwritten, so it has no uuid at all. `plot_id` is deliberately
17
+ left None in that case rather than minted and dropped: a uuid that looks
18
+ addressable via ``GET /plots/<id>`` but is not would be its own trap. Note the
19
+ identity is the plot STEP — its script and input dataframe, both from the
20
+ pipeline definition — and not ``name``, which stays the display label, so
21
+ relabelling a chart cannot orphan its blob.
22
+ """
23
+
24
+ @classmethod
25
+ def route(cls):
26
+ return "plots"
27
+
28
+ @classmethod
29
+ def from_dict(cls, data):
30
+ obj = Plot()
31
+ obj.from_json(data)
32
+ return obj
33
+
34
+ def __init__(self, plot_id=None, name=None, figure=None, key=None):
35
+ # A keyed (deployed) plot gets NO uuid — see the `key` note on the class.
36
+ # Every other plot keeps minting one, so nothing that existed changes.
37
+ if plot_id is not None:
38
+ self.plot_id = plot_id
39
+ elif key is not None:
40
+ self.plot_id = None
41
+ else:
42
+ self.plot_id = uuid.uuid4()
43
+ self.name = name
44
+ self.figure = figure
45
+ self.key = key
46
+
47
+ def api_id(self) -> str:
48
+ """
49
+ Id of the plot (plot_id)
50
+ :return: string formatted UUID of the plot, None for a deployed plot — it is
51
+ not a backend entity, so there is no id to send.
52
+ """
53
+ if self.plot_id is None:
54
+ return None
55
+ return str(self.plot_id).upper()
56
+
57
+ def endpoint(self) -> str:
58
+ """
59
+ Name of the endpoints used to manipulate plots.
60
+ :return: Endpoint name.
61
+ """
62
+ return "Plots"
63
+
64
+ def from_json(self, obj):
65
+ """
66
+ Load the Plot entity from a dictionary representation of the Plot.
67
+ :param obj: Dict version of the Plot.
68
+ """
69
+ if "id" in obj.keys():
70
+ self.plot_id = uuid.UUID(obj["id"])
71
+ if "key" in obj.keys():
72
+ # A deployed plot: keyed, never uuid-addressed. Clearing plot_id undoes
73
+ # the uuid __init__ minted before from_json ran, so a round-tripped
74
+ # execution log does not grow a uuid that addresses nothing.
75
+ self.key = obj["key"]
76
+ self.plot_id = None
77
+ if "name" in obj.keys():
78
+ self.name = obj["name"]
79
+ if "figure" in obj.keys():
80
+ self.figure = obj["figure"]
81
+
82
+ def to_json(self, target: str = None):
83
+ """
84
+ Convert the plot to a dictionary compatible to JSON format.
85
+ :return: dictionary representation of the Plot object.
86
+ """
87
+ # A deployed plot carries its deterministic key and NO id. The execution log
88
+ # is what makes it traceable which run last wrote a plot, and `key` is what
89
+ # the deployed-plot endpoint reads — an "id" beside it would only invite a
90
+ # GET /plots/<id> that cannot answer.
91
+ if self.key is not None:
92
+ obj = {
93
+ "key": self.key
94
+ }
95
+ else:
96
+ obj = {
97
+ "id": str(self.plot_id)
98
+ }
99
+ if self.name is not None:
100
+ obj["name"] = self.name
101
+ if target is None or target != 'logs':
102
+ if self.figure is not None:
103
+ obj["figure"] = self.figure
104
+ return obj
@@ -0,0 +1 @@
1
+ __version__ = "2.1.0.dev18"
@@ -1124,7 +1124,12 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
1124
1124
  else:
1125
1125
  raise ValueError('No plot has been fetch.')
1126
1126
  elif figure is not None:
1127
- return plotly.io.from_json(plot.figure)
1127
+ # Read `figure`, not `plot.figure` — with only a figure passed there is no
1128
+ # plot to read it from. A live plot's envelope carries the figure as the
1129
+ # JSON string it was stored as, an experiment plot as a dict once decoded,
1130
+ # and both must render.
1131
+ return plotly.io.from_json(figure if isinstance(figure, str)
1132
+ else json.dumps(figure))
1128
1133
  elif plot_id is not None:
1129
1134
  plot = self.get(Plot(plot_id=plot_id))
1130
1135
  if plot.figure is not None:
@@ -1156,6 +1161,90 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
1156
1161
  else:
1157
1162
  raise TypeError("execution must be an ExecutionLog")
1158
1163
 
1164
+ @staticmethod
1165
+ def _pipeline_ref(pipeline) -> str:
1166
+ """
1167
+ Path segment addressing a pipeline, from a key, a UUID or a Pipeline.
1168
+
1169
+ The live-plot route accepts both the key and the UUID, so a caller passes
1170
+ whichever it already has. A Pipeline is asked for its key first: a deployed
1171
+ plot is addressed by pipeline KEY everywhere else it appears (the blob path,
1172
+ ExecutionLog.plots), so the key is the reference that matches what comes back.
1173
+ """
1174
+ if isinstance(pipeline, Pipeline):
1175
+ reference = pipeline.key if pipeline.key is not None else pipeline.pipeline_id
1176
+ else:
1177
+ reference = pipeline
1178
+ if reference is None:
1179
+ raise ValueError("a pipeline key, UUID or Pipeline is required")
1180
+ return urllib.parse.quote(str(reference), safe="")
1181
+
1182
+ def deployed_plots(self, pipeline, twin: str = None) -> list:
1183
+ """
1184
+ list a deployed pipeline's LIVE plots - what its deployments are currently
1185
+ drawing, one per (twin, plot step).
1186
+
1187
+ A live plot is overwritten on every triggered run, so there is exactly one
1188
+ current figure per plot and no history to page through. Fetch one with
1189
+ :meth:`deployed_plot`. Experiment plots are elsewhere and unchanged - one blob
1190
+ per execution, see :meth:`plots`.
1191
+
1192
+ :param pipeline: pipeline key, UUID or Pipeline - both references are accepted.
1193
+ :param twin: hardware id, to list only that twin's plots.
1194
+ :return: list of dict {pipelineKey, twin, script, dataframe, key, deploymentId,
1195
+ produced, lastModified, size}. 'produced' is False when the definition has
1196
+ this plot step but no run has written it yet.
1197
+ """
1198
+ response = self._process_request(
1199
+ method="GET",
1200
+ route=f"{Pipeline.route()}/{self._pipeline_ref(pipeline)}/plots/",
1201
+ params={"twin": twin} if twin is not None else None
1202
+ )
1203
+ return response.json().get("results", [])
1204
+
1205
+ def deployed_plot(self,
1206
+ pipeline,
1207
+ script: str,
1208
+ dataframe: str,
1209
+ twin: str = None,
1210
+ shape: str = "figure") -> dict:
1211
+ """
1212
+ fetch one of a deployed pipeline's LIVE plots.
1213
+
1214
+ The plot step is identified by BOTH its script and its input dataframe - that
1215
+ pair is the plot's identity, as :meth:`deployed_plots` lists it.
1216
+
1217
+ Returns the envelope, not the bare figure, because the provenance is the point:
1218
+ a live plot is overwritten on every run and 'generatedAt' / 'executionId' say
1219
+ which one wrote it. Render it with ``client.plot(figure=envelope["figure"])``.
1220
+
1221
+ :param pipeline: pipeline key, UUID or Pipeline - both references are accepted.
1222
+ :param script: the plot step's script.
1223
+ :param dataframe: the plot step's input dataframe.
1224
+ :param twin: hardware id - required on a templated pipeline.
1225
+ :param shape: 'figure' (default) for the stored Plotly figure, or 'data' for its
1226
+ traces projected to 'series'.
1227
+ :return: dict with {pipelineKey, twin, script, dataframe, name, executionId,
1228
+ release, sha, imageId, generatedAt} plus 'figure', or 'series' and
1229
+ 'notProjected' when shape is 'data'.
1230
+ """
1231
+ if script is None or dataframe is None:
1232
+ raise ValueError(
1233
+ "script and dataframe are both parts of a plot's identity - pass both"
1234
+ )
1235
+ if shape not in ("figure", "data"):
1236
+ raise ValueError(f"shape must be 'figure' or 'data', got {shape!r}")
1237
+
1238
+ params = {"script": script, "dataframe": dataframe, "format": shape}
1239
+ if twin is not None:
1240
+ params["twin"] = twin
1241
+ response = self._process_request(
1242
+ method="GET",
1243
+ route=f"{Pipeline.route()}/{self._pipeline_ref(pipeline)}/plots/",
1244
+ params=params
1245
+ )
1246
+ return response.json()
1247
+
1159
1248
  def upload_model(self,
1160
1249
  model_info: ModelInfo,
1161
1250
  bytes_content = None):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wizata_dsapi
3
- Version: 2.1.0.dev16
3
+ Version: 2.1.0.dev18
4
4
  Summary: Wizata Data Science Toolkit
5
5
  Author: Wizata S.A.
6
6
  Author-email: info@wizata.com
@@ -1,70 +0,0 @@
1
- import uuid
2
- from .api_dto import ApiDto
3
-
4
-
5
- class Plot(ApiDto):
6
- """
7
- A plot is a definition of a Plotly figure that can be stored and shared on Wizata.
8
- :ivar plot_id: The UUID of the plot.
9
- :ivar name: A simple name helping the user identifying the plot.
10
- :ivar figure: Plotly figure defining the plot itself.
11
- """
12
-
13
- @classmethod
14
- def route(cls):
15
- return "plots"
16
-
17
- @classmethod
18
- def from_dict(cls, data):
19
- obj = Plot()
20
- obj.from_json(data)
21
- return obj
22
-
23
- def __init__(self, plot_id=None, name=None, figure=None):
24
- if plot_id is None:
25
- self.plot_id = uuid.uuid4()
26
- else:
27
- self.plot_id = plot_id
28
- self.name = name
29
- self.figure = figure
30
-
31
- def api_id(self) -> str:
32
- """
33
- Id of the plot (plot_id)
34
- :return: string formatted UUID of the plot.
35
- """
36
- return str(self.plot_id).upper()
37
-
38
- def endpoint(self) -> str:
39
- """
40
- Name of the endpoints used to manipulate plots.
41
- :return: Endpoint name.
42
- """
43
- return "Plots"
44
-
45
- def from_json(self, obj):
46
- """
47
- Load the Plot entity from a dictionary representation of the Plot.
48
- :param obj: Dict version of the Plot.
49
- """
50
- if "id" in obj.keys():
51
- self.plot_id = uuid.UUID(obj["id"])
52
- if "name" in obj.keys():
53
- self.name = obj["name"]
54
- if "figure" in obj.keys():
55
- self.figure = obj["figure"]
56
-
57
- def to_json(self, target: str = None):
58
- """
59
- Convert the plot to a dictionary compatible to JSON format.
60
- :return: dictionary representation of the Plot object.
61
- """
62
- obj = {
63
- "id": str(self.plot_id)
64
- }
65
- if self.name is not None:
66
- obj["name"] = self.name
67
- if target is None or target != 'logs':
68
- if self.figure is not None:
69
- obj["figure"] = self.figure
70
- return obj
@@ -1 +0,0 @@
1
- __version__ = "2.1.0.dev16"