wizata-dsapi 2.1.0.dev19__tar.gz → 2.1.0.dev21__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.dev19 → wizata_dsapi-2.1.0.dev21}/PKG-INFO +1 -1
  2. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/api_config.py +10 -0
  3. wizata_dsapi-2.1.0.dev21/wizata_dsapi/version.py +1 -0
  4. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/wizata_dsapi_client.py +94 -7
  5. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi.egg-info/PKG-INFO +1 -1
  6. wizata_dsapi-2.1.0.dev19/wizata_dsapi/version.py +0 -1
  7. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/LICENSE.txt +0 -0
  8. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/README.rst +0 -0
  9. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/setup.cfg +0 -0
  10. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/setup.py +0 -0
  11. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/__init__.py +0 -0
  12. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/api_dto.py +0 -0
  13. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/api_interface.py +0 -0
  14. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/bucket.py +0 -0
  15. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/business_label.py +0 -0
  16. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/context.py +0 -0
  17. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/dashboard.py +0 -0
  18. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/dataframe_toolkit.py +0 -0
  19. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/datapoint.py +0 -0
  20. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/datastore.py +0 -0
  21. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/deployment.py +0 -0
  22. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/ds_dataframe.py +0 -0
  23. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/dsapi_json_encoder.py +0 -0
  24. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/edge_config.py +0 -0
  25. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/edge_device.py +0 -0
  26. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/edge_module.py +0 -0
  27. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/evaluation.py +0 -0
  28. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/execution.py +0 -0
  29. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/execution_log.py +0 -0
  30. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/experiment.py +0 -0
  31. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/graylog_log.py +0 -0
  32. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/group_system.py +0 -0
  33. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/ilogger.py +0 -0
  34. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/insight.py +0 -0
  35. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/mlmodel.py +0 -0
  36. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/mobile_asset.py +0 -0
  37. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/model_toolkit.py +0 -0
  38. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/models/__init__.py +0 -0
  39. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/models/common.py +0 -0
  40. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/notification.py +0 -0
  41. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/paged_query_result.py +0 -0
  42. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/pipeline.py +0 -0
  43. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/pipeline_image.py +0 -0
  44. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/plot.py +0 -0
  45. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/plots/__init__.py +0 -0
  46. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/plots/common.py +0 -0
  47. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/plots/theme.py +0 -0
  48. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/request.py +0 -0
  49. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/script.py +0 -0
  50. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/scripts/__init__.py +0 -0
  51. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/scripts/common.py +0 -0
  52. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/search.py +0 -0
  53. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/solution_component.py +0 -0
  54. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/streamlit_utils.py +0 -0
  55. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/template.py +0 -0
  56. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/template_config.py +0 -0
  57. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/trigger.py +0 -0
  58. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/twin.py +0 -0
  59. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/twinregistration.py +0 -0
  60. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/user.py +0 -0
  61. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/wizard_function.py +0 -0
  62. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/wizard_request.py +0 -0
  63. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi/words.py +0 -0
  64. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi.egg-info/SOURCES.txt +0 -0
  65. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi.egg-info/dependency_links.txt +0 -0
  66. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/wizata_dsapi.egg-info/requires.txt +0 -0
  67. {wizata_dsapi-2.1.0.dev19 → wizata_dsapi-2.1.0.dev21}/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.dev19
3
+ Version: 2.1.0.dev21
4
4
  Summary: Wizata Data Science Toolkit
5
5
  Author: Wizata S.A.
6
6
  Author-email: info@wizata.com
@@ -32,6 +32,16 @@ from .edge_device import EdgeDevice
32
32
  # by the platform internally (the 12.1 adopt-triggers migration reads them through
33
33
  # `ApiDataManager.backend_api`, which never consults this registry). What goes is
34
34
  # the ability to schedule through the public client.
35
+
36
+ #: Entities the API paginates instead of listing.
37
+ #
38
+ # ``lists()`` fetches ``GET /<route>/``, and for these there is no such route — only
39
+ # ``POST /<route>/search``. Declaring 'lists' without this set was worse than not
40
+ # declaring it: the client advertised the operation and answered 404, and the
41
+ # documentation shipped a sample nobody could run. Listing now gathers the pages
42
+ # from the search endpoint, so the caller gets what the operation promised.
43
+ _LISTS_VIA_SEARCH = {Deployment}
44
+
35
45
  _retired = {
36
46
  "triggers": (
37
47
  Trigger,
@@ -0,0 +1 @@
1
+ __version__ = "2.1.0.dev21"
@@ -361,6 +361,10 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
361
361
  :return: list of all elements with at least the id property.
362
362
  """
363
363
  dto_class = self._get_class(entity=entity, operation="lists")
364
+ from .api_config import _LISTS_VIA_SEARCH
365
+ if dto_class in _LISTS_VIA_SEARCH:
366
+ # No GET /<route>/ exists for these; the API paginates them instead.
367
+ return self._list_via_search(dto_class)
364
368
  return self._process_request(
365
369
  method="GET",
366
370
  route=dto_class.route() + "/",
@@ -368,6 +372,32 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
368
372
  result_type="list"
369
373
  )
370
374
 
375
+ def _list_via_search(self, dto_class) -> list:
376
+ """
377
+ Every record of an entity the API only paginates.
378
+
379
+ Walks the pages rather than trusting one to hold everything: a caller asking
380
+ to list is asking for all of them, and silently returning the first fifty is
381
+ the kind of wrong that looks right until an estate grows.
382
+ """
383
+ results, page = [], 1
384
+ while True:
385
+ search_query = SearchQuery()
386
+ search_query.page = page
387
+ search_query.size = 100
388
+ response = requests.post(
389
+ self.__url() + dto_class.route() + "/search",
390
+ headers=self.__header(),
391
+ data=json.dumps(search_query.to_dict())
392
+ )
393
+ if response.status_code != 200:
394
+ raise self.__raise_error(response)
395
+ paged = PagedQueryResult.from_dict(response.json(), dto_class=dto_class)
396
+ results.extend(paged.results or [])
397
+ if not paged.results or len(results) >= (paged.total or 0):
398
+ return results
399
+ page += 1
400
+
371
401
  def get(self,
372
402
  obj=None,
373
403
  id: uuid.UUID = None,
@@ -1209,6 +1239,38 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
1209
1239
  raise ValueError("a pipeline key, UUID or Pipeline is required")
1210
1240
  return urllib.parse.quote(str(reference), safe="")
1211
1241
 
1242
+ def _pipeline_uuid(self, pipeline) -> str:
1243
+ """
1244
+ Path segment for a route that addresses a pipeline by UUID only.
1245
+
1246
+ Distinct from :meth:`_pipeline_ref`, and the difference is not cosmetic: the
1247
+ live-plot route resolves a key OR a UUID (DEV-6027), while the branch, deploy
1248
+ and preview routes parse the segment with ``uuid.UUID(id)`` and answer
1249
+ ``400 badly formed hexadecimal UUID string`` for a key.
1250
+
1251
+ Callers hold keys — that is what a pipeline is called everywhere a person
1252
+ reads one — so the key is resolved here rather than refused.
1253
+
1254
+ :param pipeline: pipeline key, UUID or Pipeline.
1255
+ :return: the pipeline's UUID as a path segment.
1256
+ """
1257
+ if isinstance(pipeline, Pipeline):
1258
+ if pipeline.pipeline_id is not None:
1259
+ return str(pipeline.pipeline_id)
1260
+ pipeline = pipeline.key
1261
+ if pipeline is None:
1262
+ raise ValueError("a pipeline key, UUID or Pipeline is required")
1263
+ if isinstance(pipeline, uuid.UUID):
1264
+ return str(pipeline)
1265
+ try:
1266
+ return str(uuid.UUID(str(pipeline)))
1267
+ except (ValueError, AttributeError, TypeError):
1268
+ pass
1269
+ resolved = self.get(pipeline_key=str(pipeline))
1270
+ if resolved is None or resolved.pipeline_id is None:
1271
+ raise ValueError(f"pipeline {pipeline!r} could not be resolved to an id")
1272
+ return str(resolved.pipeline_id)
1273
+
1212
1274
  def deployed_plots(self, pipeline, twin: str = None) -> list:
1213
1275
  """
1214
1276
  list a deployed pipeline's LIVE plots - what its deployments are currently
@@ -2088,7 +2150,7 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2088
2150
  """
2089
2151
  response = self._process_request(
2090
2152
  method="GET",
2091
- route=f"{Pipeline.route()}/{self._pipeline_ref(pipeline)}/branches/"
2153
+ route=f"{Pipeline.route()}/{self._pipeline_uuid(pipeline)}/branches/"
2092
2154
  )
2093
2155
  return response.json()
2094
2156
 
@@ -2109,7 +2171,7 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2109
2171
  payload["source"] = source
2110
2172
  response = self._process_request(
2111
2173
  method="POST",
2112
- route=f"{Pipeline.route()}/{self._pipeline_ref(pipeline)}/branches/",
2174
+ route=f"{Pipeline.route()}/{self._pipeline_uuid(pipeline)}/branches/",
2113
2175
  data=json.dumps(payload)
2114
2176
  )
2115
2177
  return Pipeline.from_dict(response.json())
@@ -2127,7 +2189,7 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2127
2189
  """
2128
2190
  self._process_request(
2129
2191
  method="DELETE",
2130
- route=f"{Pipeline.route()}/{self._pipeline_ref(pipeline)}/branches/{branch}/"
2192
+ route=f"{Pipeline.route()}/{self._pipeline_uuid(pipeline)}/branches/{branch}/"
2131
2193
  )
2132
2194
 
2133
2195
  def merge_branch(self, pipeline, branch: str) -> dict:
@@ -2140,7 +2202,7 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2140
2202
  """
2141
2203
  response = self._process_request(
2142
2204
  method="POST",
2143
- route=f"{Pipeline.route()}/{self._pipeline_ref(pipeline)}/branches/{branch}/merge"
2205
+ route=f"{Pipeline.route()}/{self._pipeline_uuid(pipeline)}/branches/{branch}/merge"
2144
2206
  )
2145
2207
  return response.json()
2146
2208
 
@@ -2154,7 +2216,7 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2154
2216
  """
2155
2217
  response = self._process_request(
2156
2218
  method="GET",
2157
- route=f"{Pipeline.route()}/{self._pipeline_ref(pipeline)}/branches/{branch}/"
2219
+ route=f"{Pipeline.route()}/{self._pipeline_uuid(pipeline)}/branches/{branch}/"
2158
2220
  )
2159
2221
  return Pipeline.from_dict(response.json())
2160
2222
 
@@ -2239,7 +2301,7 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2239
2301
  payload[name] = value
2240
2302
  response = self._process_request(
2241
2303
  method="POST",
2242
- route=f"{Pipeline.route()}/{self._pipeline_ref(pipeline)}/deploy/",
2304
+ route=f"{Pipeline.route()}/{self._pipeline_uuid(pipeline)}/deploy/",
2243
2305
  data=json.dumps(payload)
2244
2306
  )
2245
2307
  return Deployment.from_dict(response.json())
@@ -2258,7 +2320,7 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2258
2320
  payload = {k: v for k, v in kwargs.items() if v is not None}
2259
2321
  response = self._process_request(
2260
2322
  method="POST",
2261
- route=f"{Pipeline.route()}/{self._pipeline_ref(pipeline)}/deploy/preview/",
2323
+ route=f"{Pipeline.route()}/{self._pipeline_uuid(pipeline)}/deploy/preview/",
2262
2324
  data=json.dumps(payload)
2263
2325
  )
2264
2326
  return response.json()
@@ -2305,6 +2367,31 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2305
2367
  """
2306
2368
  return self._deployment_action(deployment, "retry")
2307
2369
 
2370
+ def search_deployments(self, search_query=None) -> PagedQueryResult:
2371
+ """
2372
+ Search deployments using a paged query.
2373
+
2374
+ The only way to ask what is deployed: there is no GET /deployments/, because
2375
+ a deployment is not created by posting one — it is the result of deploying a
2376
+ pipeline — and the estate is paginated rather than listed.
2377
+
2378
+ :param search_query: SearchQuery instance or dict with filters, sort, page, size.
2379
+ :return: PagedQueryResult with Deployment results.
2380
+ """
2381
+ if search_query is None:
2382
+ search_query = SearchQuery()
2383
+ elif isinstance(search_query, dict):
2384
+ search_query = SearchQuery.from_dict(search_query)
2385
+ response = requests.post(
2386
+ self.__url() + "deployments/search",
2387
+ headers=self.__header(),
2388
+ data=json.dumps(search_query.to_dict())
2389
+ )
2390
+ if response.status_code == 200:
2391
+ return PagedQueryResult.from_dict(response.json(), dto_class=Deployment)
2392
+ else:
2393
+ raise self.__raise_error(response)
2394
+
2308
2395
  def await_deployment(self,
2309
2396
  deployment,
2310
2397
  timeout: int = 900,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wizata_dsapi
3
- Version: 2.1.0.dev19
3
+ Version: 2.1.0.dev21
4
4
  Summary: Wizata Data Science Toolkit
5
5
  Author: Wizata S.A.
6
6
  Author-email: info@wizata.com
@@ -1 +0,0 @@
1
- __version__ = "2.1.0.dev19"