wizata-dsapi 2.2.0.dev8__tar.gz → 2.2.0.dev10__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 (71) hide show
  1. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/PKG-INFO +1 -1
  2. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/__init__.py +1 -1
  3. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/inventory.py +62 -4
  4. wizata_dsapi-2.2.0.dev10/wizata_dsapi/version.py +1 -0
  5. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/wizata_dsapi_client.py +52 -13
  6. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi.egg-info/PKG-INFO +1 -1
  7. wizata_dsapi-2.2.0.dev8/wizata_dsapi/version.py +0 -1
  8. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/LICENSE.txt +0 -0
  9. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/README.rst +0 -0
  10. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/setup.cfg +0 -0
  11. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/setup.py +0 -0
  12. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/api_config.py +0 -0
  13. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/api_dto.py +0 -0
  14. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/api_interface.py +0 -0
  15. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/bucket.py +0 -0
  16. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/business_label.py +0 -0
  17. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/connection.py +0 -0
  18. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/connection_types.py +0 -0
  19. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/context.py +0 -0
  20. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/dashboard.py +0 -0
  21. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/dataframe_toolkit.py +0 -0
  22. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/datapoint.py +0 -0
  23. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/datastore.py +0 -0
  24. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/deployment.py +0 -0
  25. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/ds_dataframe.py +0 -0
  26. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/dsapi_json_encoder.py +0 -0
  27. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/edge_config.py +0 -0
  28. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/edge_device.py +0 -0
  29. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/edge_module.py +0 -0
  30. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/evaluation.py +0 -0
  31. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/execution.py +0 -0
  32. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/execution_log.py +0 -0
  33. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/experiment.py +0 -0
  34. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/graylog_log.py +0 -0
  35. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/group_system.py +0 -0
  36. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/ilogger.py +0 -0
  37. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/insight.py +0 -0
  38. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/mlmodel.py +0 -0
  39. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/mobile_asset.py +0 -0
  40. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/model_toolkit.py +0 -0
  41. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/models/__init__.py +0 -0
  42. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/models/common.py +0 -0
  43. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/notification.py +0 -0
  44. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/paged_query_result.py +0 -0
  45. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/pipeline.py +0 -0
  46. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/pipeline_image.py +0 -0
  47. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/plot.py +0 -0
  48. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/plots/__init__.py +0 -0
  49. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/plots/common.py +0 -0
  50. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/plots/theme.py +0 -0
  51. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/product.py +0 -0
  52. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/request.py +0 -0
  53. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/script.py +0 -0
  54. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/scripts/__init__.py +0 -0
  55. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/scripts/common.py +0 -0
  56. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/search.py +0 -0
  57. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/solution_component.py +0 -0
  58. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/streamlit_utils.py +0 -0
  59. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/template.py +0 -0
  60. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/template_config.py +0 -0
  61. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/trigger.py +0 -0
  62. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/twin.py +0 -0
  63. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/twinregistration.py +0 -0
  64. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/user.py +0 -0
  65. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/wizard_function.py +0 -0
  66. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/wizard_request.py +0 -0
  67. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi/words.py +0 -0
  68. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi.egg-info/SOURCES.txt +0 -0
  69. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi.egg-info/dependency_links.txt +0 -0
  70. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/wizata_dsapi.egg-info/requires.txt +0 -0
  71. {wizata_dsapi-2.2.0.dev8 → wizata_dsapi-2.2.0.dev10}/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.2.0.dev8
3
+ Version: 2.2.0.dev10
4
4
  Summary: Wizata Data Science Toolkit
5
5
  Author: Wizata S.A.
6
6
  Author-email: info@wizata.com
@@ -66,7 +66,7 @@ from .connection import Connection, ConnectionMapping, ConnectionDirection, Tran
66
66
  from .connection_types import ConnectionType, CONNECTION_TYPES, TRANSFORM_SCHEMAS, get_connection_type, \
67
67
  list_connection_types
68
68
  from .product import ProductKind, Product, ProductComponent, BUILTIN_PRODUCT_KINDS, is_valid_product_key
69
- from .inventory import (InventoryBalance, inventory_mode, INVENTORY_OPTION, INVENTORY_MODES,
69
+ from .inventory import (InventoryBalance, InventoryStorage, InventoryStorageDatapoint, inventory_mode, INVENTORY_OPTION, INVENTORY_MODES,
70
70
  INVENTORY_MOVEMENTS, INVENTORY_BALANCES, INVENTORY_STOCK,
71
71
  PRODUCT_TAG, PRODUCT_MESSAGE_KEY)
72
72
  from .dashboard import Dashboard, DashboardType
@@ -83,8 +83,9 @@ class InventoryBalance:
83
83
  DataPoint ``datapoint`` (a hardware id), true at ``timestamp`` (when it was
84
84
  counted, not when it was recorded: that is ``created_at``).
85
85
 
86
- PostgreSQL ``"InventoryBalance"``, PK (``datapoint``, ``product``, ``timestamp``).
87
- Writing the same key again replaces the quantity.
86
+ PostgreSQL ``"InventoryBalance"``, PK ``id`` (DEV-6085); (``datapoint``, ``product``,
87
+ ``timestamp``) is unique, and writing the same key again replaces the quantity.
88
+ ``count`` is the key shared by every balance written in one call (one count).
88
89
 
89
90
  On write only:
90
91
 
@@ -99,7 +100,9 @@ class InventoryBalance:
99
100
  return "planner/inventory/balances"
100
101
 
101
102
  def __init__(self, datapoint: str = None, product: str = None, timestamp=None,
102
- quantity: float = None, unit=None, twin: str = None):
103
+ quantity: float = None, unit=None, twin: str = None, balance_id=None, count=None):
104
+ self.id: Optional[str] = _uuid_str(balance_id)
105
+ self.count: Optional[str] = _uuid_str(count)
103
106
  self.datapoint: Optional[str] = datapoint
104
107
  self.product: Optional[str] = product
105
108
  self.timestamp: Optional[datetime] = _ts_in(timestamp)
@@ -113,7 +116,8 @@ class InventoryBalance:
113
116
 
114
117
  def to_dict(self) -> dict:
115
118
  obj = {}
116
- for name, value in (("datapoint", self.datapoint), ("product", self.product),
119
+ for name, value in (("id", self.id), ("count", self.count),
120
+ ("datapoint", self.datapoint), ("product", self.product),
117
121
  ("quantity", self.quantity), ("unit", self.unit),
118
122
  ("twin", self.twin), ("createdBy", self.created_by),
119
123
  ("updatedBy", self.updated_by)):
@@ -128,6 +132,8 @@ class InventoryBalance:
128
132
  @classmethod
129
133
  def from_dict(cls, data: dict) -> "InventoryBalance":
130
134
  obj = cls()
135
+ obj.id = _uuid_str(data.get("id"))
136
+ obj.count = _uuid_str(data.get("count"))
131
137
  obj.datapoint = data.get("datapoint")
132
138
  obj.product = data.get("product")
133
139
  obj.timestamp = _ts_in(data.get("timestamp"))
@@ -140,9 +146,61 @@ class InventoryBalance:
140
146
  obj.updated_by = data.get("updatedBy") or data.get("updated_by")
141
147
  return obj
142
148
 
149
+ def api_id(self) -> str:
150
+ return self.id
151
+
143
152
  def key(self) -> tuple:
144
153
  return self.datapoint, self.product, self.timestamp
145
154
 
146
155
  def __repr__(self) -> str:
147
156
  return (f"InventoryBalance(datapoint={self.datapoint!r}, product={self.product!r}, "
148
157
  f"timestamp={self.timestamp!r}, quantity={self.quantity!r})")
158
+
159
+
160
+ class InventoryStorageDatapoint:
161
+ """One inventoryMovement DataPoint of a storage: its category and unit (DEV-6086)."""
162
+
163
+ def __init__(self, hardware_id: str = None, name: str = None, category=None, unit=None,
164
+ unit_symbol: str = None):
165
+ self.hardware_id: Optional[str] = hardware_id
166
+ self.name: Optional[str] = name
167
+ self.category: Optional[str] = _uuid_str(category)
168
+ self.unit: Optional[str] = _uuid_str(unit)
169
+ self.unit_symbol: Optional[str] = unit_symbol
170
+
171
+ def to_dict(self) -> dict:
172
+ return {"hardwareId": self.hardware_id, "name": self.name, "category": self.category,
173
+ "unit": self.unit, "unitSymbol": self.unit_symbol}
174
+
175
+ @classmethod
176
+ def from_dict(cls, data: dict) -> "InventoryStorageDatapoint":
177
+ return cls(hardware_id=data.get("hardwareId") or data.get("hardware_id"), name=data.get("name"),
178
+ category=data.get("category"), unit=data.get("unit"),
179
+ unit_symbol=data.get("unitSymbol") or data.get("unit_symbol"))
180
+
181
+
182
+ class InventoryStorage:
183
+ """
184
+ A storage place: a Twin holding at least one inventoryMovement DataPoint (DEV-6086).
185
+ Read only, from ``POST /dsapi/planner/inventory/storages/search``.
186
+ """
187
+
188
+ def __init__(self, twin_id=None, twin_hardware_id: str = None, twin_name: str = None,
189
+ datapoints: list = None):
190
+ self.twin_id: Optional[str] = _uuid_str(twin_id)
191
+ self.twin_hardware_id: Optional[str] = twin_hardware_id
192
+ self.twin_name: Optional[str] = twin_name
193
+ self.datapoints: list = list(datapoints or [])
194
+
195
+ def to_dict(self) -> dict:
196
+ return {"twin": {"id": self.twin_id, "hardwareId": self.twin_hardware_id, "name": self.twin_name},
197
+ "datapoints": [d.to_dict() for d in self.datapoints]}
198
+
199
+ @classmethod
200
+ def from_dict(cls, data: dict) -> "InventoryStorage":
201
+ twin = data.get("twin") or {}
202
+ return cls(twin_id=twin.get("id"), twin_hardware_id=twin.get("hardwareId"), twin_name=twin.get("name"),
203
+ datapoints=[InventoryStorageDatapoint.from_dict(d) for d in data.get("datapoints") or []])
204
+
205
+ def __repr__(self) -> str:
206
+ return f"InventoryStorage({self.twin_hardware_id!r}, {[d.hardware_id for d in self.datapoints]})"
@@ -0,0 +1 @@
1
+ __version__ = "2.2.0.dev10"
@@ -55,7 +55,7 @@ from .version import __version__
55
55
  import ast
56
56
  from .deployment import Deployment, DeploymentStatus
57
57
  from .product import ProductKind, Product, ProductComponent
58
- from .inventory import InventoryBalance
58
+ from .inventory import InventoryBalance, InventoryStorage
59
59
  from .api_config import _registry
60
60
 
61
61
  from .streamlit_utils import get_streamlit_token, get_streamlit_domain
@@ -2886,7 +2886,8 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2886
2886
  inventoryMovement DataPoint by ``datapoint``, or by ``twin`` (the DataPoint
2887
2887
  of the product's category on that Twin). ``unit`` converts the quantity to
2888
2888
  the DataPoint's unit.
2889
- :return: the stored balances, quantities in the DataPoint's unit.
2889
+ :return: the stored balances, quantities in the DataPoint's unit, each with its
2890
+ ``id`` and the ``count`` key the call created.
2890
2891
  """
2891
2892
  body = [b.to_dict() if isinstance(b, InventoryBalance) else b for b in balances]
2892
2893
  response = self._planner_request("POST", "planner/inventory/balances/", body=body)
@@ -2896,8 +2897,8 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2896
2897
  """
2897
2898
  List recorded balances, newest first by default.
2898
2899
 
2899
- :param search_query: SearchQuery or dict; filters on ``datapoint`` and
2900
- ``product`` (eq / in) and ``timestamp`` (gte / gt / lt / lte).
2900
+ :param search_query: SearchQuery or dict; filters on ``datapoint``, ``product``,
2901
+ ``twin``, ``count``, ``id`` (eq / in) and ``timestamp`` (eq / gte / gt / lt / lte).
2901
2902
  :return: PagedQueryResult with InventoryBalance results.
2902
2903
  """
2903
2904
  if search_query is None:
@@ -2908,19 +2909,57 @@ class WizataDSAPIClient(ApiInterface, ApiDtoInterface):
2908
2909
  body=search_query.to_dict())
2909
2910
  return PagedQueryResult.from_dict(response.json(), dto_class=InventoryBalance)
2910
2911
 
2911
- def delete_inventory_balance(self, datapoint: str, product: str, timestamp):
2912
+ def search_inventory_storages(self, search_query=None) -> PagedQueryResult:
2913
+ """
2914
+ The storage places: Twins holding an inventoryMovement DataPoint, each with those
2915
+ datapoints' category, unit and unit symbol (DEV-6086).
2916
+
2917
+ :param search_query: SearchQuery or dict; filters ``twin`` (hardware id or id) and
2918
+ ``category`` (eq / in), ``_search`` (``{"query": text}`` on names and hardware ids).
2919
+ :return: PagedQueryResult with InventoryStorage results, sorted by twin name.
2920
+ """
2921
+ if search_query is None:
2922
+ search_query = SearchQuery()
2923
+ elif isinstance(search_query, dict):
2924
+ search_query = SearchQuery.from_dict(search_query)
2925
+ response = self._planner_request("POST", "planner/inventory/storages/search",
2926
+ body=search_query.to_dict())
2927
+ return PagedQueryResult.from_dict(response.json(), dto_class=InventoryStorage)
2928
+
2929
+ @staticmethod
2930
+ def _balance_id(value) -> str:
2931
+ balance_id = value.id if isinstance(value, InventoryBalance) else value
2932
+ if not balance_id:
2933
+ raise ValueError("please provide a balance or its id")
2934
+ return urllib.parse.quote(str(balance_id), safe="")
2935
+
2936
+ def get_inventory_balance(self, balance_id):
2937
+ """
2938
+ :param balance_id: the balance's id.
2939
+ :return: InventoryBalance, or None when it does not exist.
2940
+ """
2941
+ response = self._planner_request("GET", f"planner/inventory/balances/{self._balance_id(balance_id)}/",
2942
+ expected=(200, 404))
2943
+ return InventoryBalance.from_dict(response.json()) if response.status_code == 200 else None
2944
+
2945
+ def update_inventory_balance(self, balance: InventoryBalance) -> InventoryBalance:
2946
+ """
2947
+ Change one balance's quantity and/or time (its datapoint and product never change).
2948
+ ``unit`` converts the quantity to the datapoint's unit. 409 when another balance
2949
+ already holds the new time.
2950
+ """
2951
+ body = {k: v for k, v in balance.to_dict().items() if k in ("quantity", "timestamp", "unit")}
2952
+ response = self._planner_request("PUT", f"planner/inventory/balances/{self._balance_id(balance)}/",
2953
+ body=body)
2954
+ return InventoryBalance.from_dict(response.json())
2955
+
2956
+ def delete_inventory_balance(self, balance):
2912
2957
  """
2913
2958
  Delete one recorded balance (a count entered by mistake).
2914
2959
 
2915
- :param timestamp: datetime or ISO string, exactly as stored.
2960
+ :param balance: InventoryBalance or its id.
2916
2961
  """
2917
- if isinstance(timestamp, datetime.datetime):
2918
- if timestamp.tzinfo is None:
2919
- timestamp = timestamp.replace(tzinfo=datetime.timezone.utc)
2920
- timestamp = timestamp.isoformat()
2921
- self._planner_request("DELETE", "planner/inventory/balances/",
2922
- params={"datapoint": datapoint, "product": product,
2923
- "timestamp": timestamp},
2962
+ self._planner_request("DELETE", f"planner/inventory/balances/{self._balance_id(balance)}/",
2924
2963
  expected=(204,))
2925
2964
 
2926
2965
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wizata_dsapi
3
- Version: 2.2.0.dev8
3
+ Version: 2.2.0.dev10
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.2.0.dev8"