ni.datastore 0.1.0.dev5__tar.gz → 0.1.0.dev6__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.
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/PKG-INFO +3 -3
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/pyproject.toml +6 -6
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_data_store_client.py +65 -52
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/__init__.py +3 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_metadata_store_client.py +64 -23
- ni_datastore-0.1.0.dev6/src/ni/datastore/metadata/_types/_metadata_items.py +155 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/LICENSE +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/README.md +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/__init__.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/__init__.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_grpc_conversion.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/__init__.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/_error_information.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/_moniker.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/_outcome.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/_published_condition.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/_published_measurement.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/_step.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/_test_result.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/py.typed +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/py.typed +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_grpc_conversion.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/__init__.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_alias.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_alias_target_type.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_extension_schema.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_hardware_item.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_operator.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_software_item.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_test.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_test_adapter.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_test_description.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_test_station.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_uut.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_uut_instance.py +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/py.typed +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/py.typed +0 -0
- {ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: ni.datastore
|
|
3
|
-
Version: 0.1.0.
|
|
3
|
+
Version: 0.1.0.dev6
|
|
4
4
|
Summary: APIs for publishing and retrieving data from NI Measurement Data Services
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: datastore
|
|
@@ -25,8 +25,8 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
25
25
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
26
26
|
Requires-Dist: hightime (>=0.3.0.dev0)
|
|
27
27
|
Requires-Dist: ni-datamonikers-v1-client (>=0.1.0.dev1)
|
|
28
|
-
Requires-Dist: ni-measurements-data-v1-client (>=0.2.0.
|
|
29
|
-
Requires-Dist: ni-measurements-metadata-v1-client (>=0.2.0.
|
|
28
|
+
Requires-Dist: ni-measurements-data-v1-client (>=0.2.0.dev4)
|
|
29
|
+
Requires-Dist: ni-measurements-metadata-v1-client (>=0.2.0.dev2)
|
|
30
30
|
Requires-Dist: ni-protobuf-types (>=1.0.1.dev0)
|
|
31
31
|
Requires-Dist: protobuf (>=4.21)
|
|
32
32
|
Description-Content-Type: text/markdown
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ni.datastore"
|
|
3
|
-
version = "0.1.0.
|
|
3
|
+
version = "0.1.0.dev6"
|
|
4
4
|
license = "MIT"
|
|
5
5
|
description = "APIs for publishing and retrieving data from NI Measurement Data Services"
|
|
6
6
|
authors = [{name = "NI", email = "opensource@ni.com"}]
|
|
@@ -38,8 +38,8 @@ requires-poetry = '>=2.1,<3.0'
|
|
|
38
38
|
python = "^3.10"
|
|
39
39
|
protobuf = {version=">=4.21"}
|
|
40
40
|
ni-datamonikers-v1-client = { version = ">=0.1.0.dev1", allow-prereleases = true }
|
|
41
|
-
ni-measurements-data-v1-client = { version = ">=0.2.0.
|
|
42
|
-
ni-measurements-metadata-v1-client = { version = ">=0.2.0.
|
|
41
|
+
ni-measurements-data-v1-client = { version = ">=0.2.0.dev4", allow-prereleases = true }
|
|
42
|
+
ni-measurements-metadata-v1-client = { version = ">=0.2.0.dev2", allow-prereleases = true }
|
|
43
43
|
ni-protobuf-types = { version = ">=1.0.1.dev0", allow-prereleases = true }
|
|
44
44
|
hightime = { version = ">=0.3.0.dev0", allow-prereleases = true }
|
|
45
45
|
|
|
@@ -50,7 +50,7 @@ ipykernel = ">=6.0"
|
|
|
50
50
|
plotly = ">=5.0"
|
|
51
51
|
nbformat = ">=4.2.0"
|
|
52
52
|
ipython = ">=7.0"
|
|
53
|
-
jupyter = ">=1.0"
|
|
53
|
+
jupyter = ">=1.0"
|
|
54
54
|
|
|
55
55
|
[tool.poetry.group.lint.dependencies]
|
|
56
56
|
bandit = { version = ">=1.7", extras = ["toml"] }
|
|
@@ -92,7 +92,7 @@ skips = [
|
|
|
92
92
|
extend_exclude = "docs,examples"
|
|
93
93
|
|
|
94
94
|
[tool.black]
|
|
95
|
-
extend-exclude = 'docs/|_pb2(_grpc)?\.(py|pyi)$'
|
|
95
|
+
extend-exclude = 'docs/|examples/|_pb2(_grpc)?\.(py|pyi)$'
|
|
96
96
|
line-length = 100
|
|
97
97
|
|
|
98
98
|
[tool.mypy]
|
|
@@ -101,7 +101,7 @@ files = "."
|
|
|
101
101
|
namespace_packages = true
|
|
102
102
|
strict = true
|
|
103
103
|
explicit_package_bases = true
|
|
104
|
-
exclude = ["docs"]
|
|
104
|
+
exclude = ["docs", "examples"]
|
|
105
105
|
|
|
106
106
|
[tool.pyright]
|
|
107
107
|
include = ["src/", "tests/"]
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_data_store_client.py
RENAMED
|
@@ -33,6 +33,8 @@ from ni.measurements.data.v1.client import DataStoreClient as DataStoreServiceCl
|
|
|
33
33
|
from ni.measurements.data.v1.data_store_service_pb2 import (
|
|
34
34
|
CreateStepRequest,
|
|
35
35
|
CreateTestResultRequest,
|
|
36
|
+
GetConditionRequest,
|
|
37
|
+
GetMeasurementRequest,
|
|
36
38
|
GetStepRequest,
|
|
37
39
|
GetTestResultRequest,
|
|
38
40
|
PublishConditionBatchRequest,
|
|
@@ -74,7 +76,10 @@ class DataStoreClient:
|
|
|
74
76
|
"_moniker_clients_lock",
|
|
75
77
|
)
|
|
76
78
|
|
|
77
|
-
_DATA_STORE_CLIENT_CLOSED_ERROR =
|
|
79
|
+
_DATA_STORE_CLIENT_CLOSED_ERROR = (
|
|
80
|
+
"This DataStoreClient has been closed. Create a new DataStoreClient for further "
|
|
81
|
+
"interaction with the data store."
|
|
82
|
+
)
|
|
78
83
|
|
|
79
84
|
_closed: bool
|
|
80
85
|
_discovery_client: DiscoveryClient | None
|
|
@@ -144,18 +149,18 @@ class DataStoreClient:
|
|
|
144
149
|
|
|
145
150
|
def publish_condition(
|
|
146
151
|
self,
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
name: str,
|
|
153
|
+
condition_type: str,
|
|
149
154
|
value: object,
|
|
150
155
|
step_id: str,
|
|
151
|
-
) ->
|
|
156
|
+
) -> str:
|
|
152
157
|
"""Publish a condition value to the data store.
|
|
153
158
|
|
|
154
159
|
Args:
|
|
155
|
-
|
|
160
|
+
name: An identifier describing the condition value.
|
|
156
161
|
For example, "Voltage" or "Temperature".
|
|
157
162
|
|
|
158
|
-
|
|
163
|
+
condition_type: The type of this condition. For example, "Upper Limit",
|
|
159
164
|
"Environment", or "Setup".
|
|
160
165
|
|
|
161
166
|
value: The single value for this condition to publish on the test
|
|
@@ -166,32 +171,28 @@ class DataStoreClient:
|
|
|
166
171
|
value is expected to be a parsable GUID.
|
|
167
172
|
|
|
168
173
|
Returns:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
Vector)
|
|
172
|
-
- The unique ID of the condition for referencing in queries
|
|
173
|
-
- Metadata including condition name, type, step ID and test
|
|
174
|
-
result ID
|
|
174
|
+
str: The condition id - the unique ID of the condition for
|
|
175
|
+
referencing in queries
|
|
175
176
|
"""
|
|
176
177
|
publish_request = PublishConditionRequest(
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
name=name,
|
|
179
|
+
condition_type=condition_type,
|
|
179
180
|
step_id=step_id,
|
|
180
181
|
)
|
|
181
182
|
populate_publish_condition_request_value(publish_request, value)
|
|
182
183
|
publish_response = self._get_data_store_client().publish_condition(publish_request)
|
|
183
|
-
return
|
|
184
|
+
return publish_response.condition_id
|
|
184
185
|
|
|
185
186
|
def publish_condition_batch(
|
|
186
|
-
self,
|
|
187
|
-
) ->
|
|
187
|
+
self, name: str, condition_type: str, values: object, step_id: str
|
|
188
|
+
) -> str:
|
|
188
189
|
"""Publish a batch of N values for a condition to the data store.
|
|
189
190
|
|
|
190
191
|
Args:
|
|
191
|
-
|
|
192
|
+
name: An identifier describing the condition values.
|
|
192
193
|
For example, "Voltage" or "Temperature".
|
|
193
194
|
|
|
194
|
-
|
|
195
|
+
condition_type: The type of this condition. For example, "Upper Limit",
|
|
195
196
|
"Environment", or "Setup".
|
|
196
197
|
|
|
197
198
|
values: The values for this condition across all publishes on the
|
|
@@ -201,27 +202,21 @@ class DataStoreClient:
|
|
|
201
202
|
values. This value is expected to be a parsable GUID.
|
|
202
203
|
|
|
203
204
|
Returns:
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
- A moniker for retrieving the condition data (returns a
|
|
208
|
-
Vector)
|
|
209
|
-
- The unique ID of the condition for referencing in queries
|
|
210
|
-
- Metadata including condition name, type, step ID and test
|
|
211
|
-
result ID
|
|
205
|
+
str: The condition id - the unique ID of the condition for
|
|
206
|
+
referencing in queries
|
|
212
207
|
"""
|
|
213
208
|
publish_request = PublishConditionBatchRequest(
|
|
214
|
-
|
|
215
|
-
|
|
209
|
+
name=name,
|
|
210
|
+
condition_type=condition_type,
|
|
216
211
|
step_id=step_id,
|
|
217
212
|
)
|
|
218
213
|
populate_publish_condition_batch_request_values(publish_request, values)
|
|
219
214
|
publish_response = self._get_data_store_client().publish_condition_batch(publish_request)
|
|
220
|
-
return
|
|
215
|
+
return publish_response.condition_id
|
|
221
216
|
|
|
222
217
|
def publish_measurement(
|
|
223
218
|
self,
|
|
224
|
-
|
|
219
|
+
name: str,
|
|
225
220
|
value: object, # More strongly typed Union[bool, AnalogWaveform] can be used if needed
|
|
226
221
|
step_id: str,
|
|
227
222
|
timestamp: ht.datetime | None = None,
|
|
@@ -231,11 +226,11 @@ class DataStoreClient:
|
|
|
231
226
|
test_adapter_ids: Iterable[str] = tuple(),
|
|
232
227
|
software_item_ids: Iterable[str] = tuple(),
|
|
233
228
|
notes: str = "",
|
|
234
|
-
) ->
|
|
229
|
+
) -> str:
|
|
235
230
|
"""Publish a single measurement value associated with a test step.
|
|
236
231
|
|
|
237
232
|
Args:
|
|
238
|
-
|
|
233
|
+
name: The name used for associating/grouping
|
|
239
234
|
conceptually alike measurements across multiple publish
|
|
240
235
|
iterations. For example, "Temperature" can be used for
|
|
241
236
|
associating temperature readings across multiple iterations.
|
|
@@ -279,15 +274,10 @@ class DataStoreClient:
|
|
|
279
274
|
notes: Any notes to be associated with the captured measurement.
|
|
280
275
|
|
|
281
276
|
Returns:
|
|
282
|
-
|
|
283
|
-
its metadata, including:
|
|
284
|
-
- A moniker for retrieving the measurement data
|
|
285
|
-
- Associated conditions from the test step
|
|
286
|
-
- Measurement metadata (name, type, timestamps, outcome)
|
|
287
|
-
- Associated hardware, software, and test adapter IDs
|
|
277
|
+
str: The published measurement id.
|
|
288
278
|
"""
|
|
289
279
|
publish_request = PublishMeasurementRequest(
|
|
290
|
-
|
|
280
|
+
name=name,
|
|
291
281
|
step_id=step_id,
|
|
292
282
|
outcome=outcome.to_protobuf(),
|
|
293
283
|
error_information=(
|
|
@@ -303,11 +293,11 @@ class DataStoreClient:
|
|
|
303
293
|
get_publish_measurement_timestamp(publish_request, timestamp)
|
|
304
294
|
)
|
|
305
295
|
publish_response = self._get_data_store_client().publish_measurement(publish_request)
|
|
306
|
-
return
|
|
296
|
+
return publish_response.measurement_id
|
|
307
297
|
|
|
308
298
|
def publish_measurement_batch(
|
|
309
299
|
self,
|
|
310
|
-
|
|
300
|
+
name: str,
|
|
311
301
|
values: object,
|
|
312
302
|
step_id: str,
|
|
313
303
|
timestamps: Iterable[ht.datetime] = tuple(),
|
|
@@ -317,11 +307,11 @@ class DataStoreClient:
|
|
|
317
307
|
test_adapter_ids: Iterable[str] = tuple(),
|
|
318
308
|
software_item_ids: Iterable[str] = tuple(),
|
|
319
309
|
notes: str = "",
|
|
320
|
-
) -> Sequence[
|
|
310
|
+
) -> Sequence[str]:
|
|
321
311
|
"""Publish multiple scalar measurements at once for parametric sweeps.
|
|
322
312
|
|
|
323
313
|
Args:
|
|
324
|
-
|
|
314
|
+
name: The name used for associating/grouping
|
|
325
315
|
conceptually alike measurements across multiple publish
|
|
326
316
|
iterations. For example, "Temperature" can be used for
|
|
327
317
|
associating temperature readings across multiple iterations.
|
|
@@ -362,14 +352,13 @@ class DataStoreClient:
|
|
|
362
352
|
notes: Any notes to be associated with the published measurements.
|
|
363
353
|
|
|
364
354
|
Returns:
|
|
365
|
-
Sequence[
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
will currently always have a single PublishedMeasurement
|
|
355
|
+
Sequence[str]: The ids of the published measurement ids.
|
|
356
|
+
NOTE: Using a Sequence is for future flexibility.
|
|
357
|
+
This sequence will currently always have a single measurement id
|
|
369
358
|
returned.
|
|
370
359
|
"""
|
|
371
360
|
publish_request = PublishMeasurementBatchRequest(
|
|
372
|
-
|
|
361
|
+
name=name,
|
|
373
362
|
step_id=step_id,
|
|
374
363
|
timestamps=[hightime_datetime_to_protobuf(ts) for ts in timestamps],
|
|
375
364
|
outcomes=[outcome.to_protobuf() for outcome in outcomes],
|
|
@@ -383,9 +372,7 @@ class DataStoreClient:
|
|
|
383
372
|
)
|
|
384
373
|
populate_publish_measurement_batch_request_values(publish_request, values)
|
|
385
374
|
publish_response = self._get_data_store_client().publish_measurement_batch(publish_request)
|
|
386
|
-
return
|
|
387
|
-
PublishedMeasurement.from_protobuf(pm) for pm in publish_response.published_measurements
|
|
388
|
-
]
|
|
375
|
+
return publish_response.measurement_ids
|
|
389
376
|
|
|
390
377
|
@overload
|
|
391
378
|
def read_data(
|
|
@@ -484,6 +471,32 @@ class DataStoreClient:
|
|
|
484
471
|
get_response = self._get_data_store_client().get_step(get_request)
|
|
485
472
|
return Step.from_protobuf(get_response.step)
|
|
486
473
|
|
|
474
|
+
def get_measurement(self, measurement_id: str) -> PublishedMeasurement:
|
|
475
|
+
"""Get the measurement associated with the given identifier.
|
|
476
|
+
|
|
477
|
+
Args:
|
|
478
|
+
measurement_id: The identifier of the desired measurement.
|
|
479
|
+
|
|
480
|
+
Returns:
|
|
481
|
+
PublishedMeasurement: The metadata of the requested measurement.
|
|
482
|
+
"""
|
|
483
|
+
get_request = GetMeasurementRequest(measurement_id=measurement_id)
|
|
484
|
+
get_response = self._get_data_store_client().get_measurement(get_request)
|
|
485
|
+
return PublishedMeasurement.from_protobuf(get_response.published_measurement)
|
|
486
|
+
|
|
487
|
+
def get_condition(self, condition_id: str) -> PublishedCondition:
|
|
488
|
+
"""Get the condition associated with the given identifier.
|
|
489
|
+
|
|
490
|
+
Args:
|
|
491
|
+
condition_id: The identifier of the desired condition.
|
|
492
|
+
|
|
493
|
+
Returns:
|
|
494
|
+
PublishedCondition: The metadata of the requested condition.
|
|
495
|
+
"""
|
|
496
|
+
get_request = GetConditionRequest(condition_id=condition_id)
|
|
497
|
+
get_response = self._get_data_store_client().get_condition(get_request)
|
|
498
|
+
return PublishedCondition.from_protobuf(get_response.published_condition)
|
|
499
|
+
|
|
487
500
|
def create_test_result(self, test_result: TestResult) -> str:
|
|
488
501
|
"""Create a test result object for publishing measurements.
|
|
489
502
|
|
|
@@ -5,6 +5,7 @@ from ni.datastore.metadata._types._alias import Alias
|
|
|
5
5
|
from ni.datastore.metadata._types._alias_target_type import AliasTargetType
|
|
6
6
|
from ni.datastore.metadata._types._extension_schema import ExtensionSchema
|
|
7
7
|
from ni.datastore.metadata._types._hardware_item import HardwareItem
|
|
8
|
+
from ni.datastore.metadata._types._metadata_items import MetadataItems
|
|
8
9
|
from ni.datastore.metadata._types._operator import Operator
|
|
9
10
|
from ni.datastore.metadata._types._software_item import SoftwareItem
|
|
10
11
|
from ni.datastore.metadata._types._test import Test
|
|
@@ -19,6 +20,7 @@ __all__ = [
|
|
|
19
20
|
"AliasTargetType",
|
|
20
21
|
"ExtensionSchema",
|
|
21
22
|
"HardwareItem",
|
|
23
|
+
"MetadataItems",
|
|
22
24
|
"MetadataStoreClient",
|
|
23
25
|
"Operator",
|
|
24
26
|
"SoftwareItem",
|
|
@@ -35,6 +37,7 @@ Alias.__module__ = __name__
|
|
|
35
37
|
AliasTargetType.__module__ = __name__
|
|
36
38
|
ExtensionSchema.__module__ = __name__
|
|
37
39
|
HardwareItem.__module__ = __name__
|
|
40
|
+
MetadataItems.__module__ = __name__
|
|
38
41
|
MetadataStoreClient.__module__ = __name__
|
|
39
42
|
Operator.__module__ = __name__
|
|
40
43
|
SoftwareItem.__module__ = __name__
|
|
@@ -14,6 +14,7 @@ from grpc import Channel
|
|
|
14
14
|
from ni.datastore.metadata._types._alias import Alias
|
|
15
15
|
from ni.datastore.metadata._types._extension_schema import ExtensionSchema
|
|
16
16
|
from ni.datastore.metadata._types._hardware_item import HardwareItem
|
|
17
|
+
from ni.datastore.metadata._types._metadata_items import MetadataItems
|
|
17
18
|
from ni.datastore.metadata._types._operator import Operator
|
|
18
19
|
from ni.datastore.metadata._types._software_item import SoftwareItem
|
|
19
20
|
from ni.datastore.metadata._types._test import Test
|
|
@@ -28,6 +29,7 @@ from ni.measurements.metadata.v1.client import (
|
|
|
28
29
|
)
|
|
29
30
|
from ni.measurements.metadata.v1.metadata_store_service_pb2 import (
|
|
30
31
|
CreateAliasRequest,
|
|
32
|
+
CreateFromJsonDocumentRequest,
|
|
31
33
|
CreateHardwareItemRequest,
|
|
32
34
|
CreateOperatorRequest,
|
|
33
35
|
CreateSoftwareItemRequest,
|
|
@@ -84,7 +86,10 @@ class MetadataStoreClient:
|
|
|
84
86
|
"_metadata_store_client_lock",
|
|
85
87
|
)
|
|
86
88
|
|
|
87
|
-
_METADATA_STORE_CLIENT_CLOSED_ERROR =
|
|
89
|
+
_METADATA_STORE_CLIENT_CLOSED_ERROR = (
|
|
90
|
+
"This MetadataStoreClient has been closed. Create a new MetadataStoreClient for "
|
|
91
|
+
"further interaction with the metadata store."
|
|
92
|
+
)
|
|
88
93
|
|
|
89
94
|
_closed: bool
|
|
90
95
|
_discovery_client: DiscoveryClient | None
|
|
@@ -525,6 +530,34 @@ class MetadataStoreClient:
|
|
|
525
530
|
list_response = self._get_metadata_store_client().list_schemas(list_request)
|
|
526
531
|
return [ExtensionSchema.from_protobuf(schema) for schema in list_response.schemas]
|
|
527
532
|
|
|
533
|
+
def get_alias(self, alias_name: str) -> Alias:
|
|
534
|
+
"""Get an alias and its target (the underlying metadata it represents).
|
|
535
|
+
|
|
536
|
+
Args:
|
|
537
|
+
alias_name: The name of the alias to retrieve.
|
|
538
|
+
|
|
539
|
+
Returns:
|
|
540
|
+
Alias: The alias containing the alias name, target type, and
|
|
541
|
+
target ID of the underlying metadata.
|
|
542
|
+
"""
|
|
543
|
+
get_request = GetAliasRequest(alias_name=alias_name)
|
|
544
|
+
get_response = self._get_metadata_store_client().get_alias(get_request)
|
|
545
|
+
return Alias.from_protobuf(get_response.alias)
|
|
546
|
+
|
|
547
|
+
def query_aliases(self, odata_query: str = "") -> Sequence[Alias]:
|
|
548
|
+
"""Perform an OData query on the registered aliases.
|
|
549
|
+
|
|
550
|
+
Args:
|
|
551
|
+
odata_query: An OData query string. Example: "$filter=name eq
|
|
552
|
+
'Value'". $expand is not supported.
|
|
553
|
+
|
|
554
|
+
Returns:
|
|
555
|
+
Sequence[Alias]: The list of aliases that match the query.
|
|
556
|
+
"""
|
|
557
|
+
query_request = QueryAliasesRequest(odata_query=odata_query)
|
|
558
|
+
query_response = self._get_metadata_store_client().query_aliases(query_request)
|
|
559
|
+
return [Alias.from_protobuf(alias) for alias in query_response.aliases]
|
|
560
|
+
|
|
528
561
|
def create_alias(
|
|
529
562
|
self,
|
|
530
563
|
alias_name: str,
|
|
@@ -580,20 +613,6 @@ class MetadataStoreClient:
|
|
|
580
613
|
response = self._get_metadata_store_client().create_alias(create_request)
|
|
581
614
|
return Alias.from_protobuf(response.alias)
|
|
582
615
|
|
|
583
|
-
def get_alias(self, alias_name: str) -> Alias:
|
|
584
|
-
"""Get an alias and its target (the underlying metadata it represents).
|
|
585
|
-
|
|
586
|
-
Args:
|
|
587
|
-
alias_name: The name of the alias to retrieve.
|
|
588
|
-
|
|
589
|
-
Returns:
|
|
590
|
-
Alias: The alias containing the alias name, target type, and
|
|
591
|
-
target ID of the underlying metadata.
|
|
592
|
-
"""
|
|
593
|
-
get_request = GetAliasRequest(alias_name=alias_name)
|
|
594
|
-
get_response = self._get_metadata_store_client().get_alias(get_request)
|
|
595
|
-
return Alias.from_protobuf(get_response.alias)
|
|
596
|
-
|
|
597
616
|
def delete_alias(self, alias_name: str) -> bool:
|
|
598
617
|
"""Remove a registered alias.
|
|
599
618
|
|
|
@@ -608,19 +627,41 @@ class MetadataStoreClient:
|
|
|
608
627
|
delete_response = self._get_metadata_store_client().delete_alias(delete_request)
|
|
609
628
|
return delete_response.unregistered
|
|
610
629
|
|
|
611
|
-
def
|
|
612
|
-
"""
|
|
630
|
+
def create_from_json_file(self, metadata_file_path: Path | str) -> MetadataItems:
|
|
631
|
+
"""Create metadata items from a JSON file.
|
|
613
632
|
|
|
614
633
|
Args:
|
|
615
|
-
|
|
616
|
-
'Value'". $expand is not supported.
|
|
634
|
+
metadata_file_path: The path to the JSON file containing metadata definitions.
|
|
617
635
|
|
|
618
636
|
Returns:
|
|
619
|
-
|
|
637
|
+
MetadataItems: A collection of metadata items created from the JSON document.
|
|
638
|
+
|
|
639
|
+
Raises:
|
|
640
|
+
FileNotFoundError: If the JSON file does not exist.
|
|
620
641
|
"""
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
642
|
+
if isinstance(metadata_file_path, str):
|
|
643
|
+
metadata_file_path = Path(metadata_file_path)
|
|
644
|
+
|
|
645
|
+
if not metadata_file_path.exists():
|
|
646
|
+
raise FileNotFoundError(f"Metadata file not found: {metadata_file_path}")
|
|
647
|
+
|
|
648
|
+
metadata_contents = metadata_file_path.read_text(encoding="utf-8-sig")
|
|
649
|
+
return self.create_from_json(metadata_contents)
|
|
650
|
+
|
|
651
|
+
def create_from_json(self, metadata_file_contents: str) -> MetadataItems:
|
|
652
|
+
"""Create metadata items from a JSON document.
|
|
653
|
+
|
|
654
|
+
Args:
|
|
655
|
+
metadata_file_contents: The JSON document content containing metadata definitions.
|
|
656
|
+
|
|
657
|
+
Returns:
|
|
658
|
+
MetadataItems: A collection of metadata items created from the JSON document.
|
|
659
|
+
"""
|
|
660
|
+
create_request = CreateFromJsonDocumentRequest(json_document=metadata_file_contents)
|
|
661
|
+
create_response = self._get_metadata_store_client().create_from_json_document(
|
|
662
|
+
create_request
|
|
663
|
+
)
|
|
664
|
+
return MetadataItems.from_protobuf(create_response)
|
|
624
665
|
|
|
625
666
|
def _get_metadata_store_client(self) -> MetadataStoreServiceClient:
|
|
626
667
|
if self._closed:
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""MetadataItems data type for the Data Store Client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
|
|
7
|
+
from ni.datastore.metadata._types._hardware_item import HardwareItem
|
|
8
|
+
from ni.datastore.metadata._types._operator import Operator
|
|
9
|
+
from ni.datastore.metadata._types._software_item import SoftwareItem
|
|
10
|
+
from ni.datastore.metadata._types._test import Test
|
|
11
|
+
from ni.datastore.metadata._types._test_adapter import TestAdapter
|
|
12
|
+
from ni.datastore.metadata._types._test_description import TestDescription
|
|
13
|
+
from ni.datastore.metadata._types._test_station import TestStation
|
|
14
|
+
from ni.datastore.metadata._types._uut import Uut
|
|
15
|
+
from ni.datastore.metadata._types._uut_instance import UutInstance
|
|
16
|
+
from ni.measurements.metadata.v1.metadata_store_service_pb2 import (
|
|
17
|
+
CreateFromJsonDocumentResponse,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class MetadataItems:
|
|
22
|
+
"""Represents a collection of metadata items created from a JSON document.
|
|
23
|
+
|
|
24
|
+
This class contains the results of creating metadata items from a JSON document,
|
|
25
|
+
organizing them by type for easy access.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
__slots__ = (
|
|
29
|
+
"uut_instances",
|
|
30
|
+
"uuts",
|
|
31
|
+
"operators",
|
|
32
|
+
"test_descriptions",
|
|
33
|
+
"tests",
|
|
34
|
+
"test_stations",
|
|
35
|
+
"hardware_items",
|
|
36
|
+
"software_items",
|
|
37
|
+
"test_adapters",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
*,
|
|
43
|
+
uut_instances: Sequence[UutInstance] = (),
|
|
44
|
+
uuts: Sequence[Uut] = (),
|
|
45
|
+
operators: Sequence[Operator] = (),
|
|
46
|
+
test_descriptions: Sequence[TestDescription] = (),
|
|
47
|
+
tests: Sequence[Test] = (),
|
|
48
|
+
test_stations: Sequence[TestStation] = (),
|
|
49
|
+
hardware_items: Sequence[HardwareItem] = (),
|
|
50
|
+
software_items: Sequence[SoftwareItem] = (),
|
|
51
|
+
test_adapters: Sequence[TestAdapter] = (),
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Initialize a MetadataItems instance.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
uut_instances: A sequence of UUT instances created from the JSON document.
|
|
57
|
+
uuts: A sequence of UUTs created from the JSON document.
|
|
58
|
+
operators: A sequence of operators created from the JSON document.
|
|
59
|
+
test_descriptions: A sequence of test descriptions created from the JSON document.
|
|
60
|
+
tests: A sequence of tests created from the JSON document.
|
|
61
|
+
test_stations: A sequence of test stations created from the JSON document.
|
|
62
|
+
hardware_items: A sequence of hardware items created from the JSON document.
|
|
63
|
+
software_items: A sequence of software items created from the JSON document.
|
|
64
|
+
test_adapters: A sequence of test adapters created from the JSON document.
|
|
65
|
+
"""
|
|
66
|
+
self.uut_instances = uut_instances
|
|
67
|
+
self.uuts = uuts
|
|
68
|
+
self.operators = operators
|
|
69
|
+
self.test_descriptions = test_descriptions
|
|
70
|
+
self.tests = tests
|
|
71
|
+
self.test_stations = test_stations
|
|
72
|
+
self.hardware_items = hardware_items
|
|
73
|
+
self.software_items = software_items
|
|
74
|
+
self.test_adapters = test_adapters
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def from_protobuf(response: CreateFromJsonDocumentResponse) -> "MetadataItems":
|
|
78
|
+
"""Create a MetadataItems instance from a protobuf CreateFromJsonDocumentResponse.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
response: The protobuf response containing the created metadata items.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
MetadataItems: A new MetadataItems instance with all the created items.
|
|
85
|
+
"""
|
|
86
|
+
return MetadataItems(
|
|
87
|
+
uut_instances=[
|
|
88
|
+
UutInstance.from_protobuf(uut_instance) for uut_instance in response.uut_instances
|
|
89
|
+
],
|
|
90
|
+
uuts=[Uut.from_protobuf(uut) for uut in response.uuts],
|
|
91
|
+
operators=[Operator.from_protobuf(operator) for operator in response.operators],
|
|
92
|
+
test_descriptions=[
|
|
93
|
+
TestDescription.from_protobuf(test_description)
|
|
94
|
+
for test_description in response.test_descriptions
|
|
95
|
+
],
|
|
96
|
+
tests=[Test.from_protobuf(test) for test in response.tests],
|
|
97
|
+
test_stations=[
|
|
98
|
+
TestStation.from_protobuf(test_station) for test_station in response.test_stations
|
|
99
|
+
],
|
|
100
|
+
hardware_items=[
|
|
101
|
+
HardwareItem.from_protobuf(hardware_item)
|
|
102
|
+
for hardware_item in response.hardware_items
|
|
103
|
+
],
|
|
104
|
+
software_items=[
|
|
105
|
+
SoftwareItem.from_protobuf(software_item)
|
|
106
|
+
for software_item in response.software_items
|
|
107
|
+
],
|
|
108
|
+
test_adapters=[
|
|
109
|
+
TestAdapter.from_protobuf(test_adapter) for test_adapter in response.test_adapters
|
|
110
|
+
],
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
def __eq__(self, other: object) -> bool:
|
|
114
|
+
"""Determine equality between MetadataItems instances."""
|
|
115
|
+
if not isinstance(other, MetadataItems):
|
|
116
|
+
return False
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
list(self.uut_instances) == list(other.uut_instances)
|
|
120
|
+
and list(self.uuts) == list(other.uuts)
|
|
121
|
+
and list(self.operators) == list(other.operators)
|
|
122
|
+
and list(self.test_descriptions) == list(other.test_descriptions)
|
|
123
|
+
and list(self.tests) == list(other.tests)
|
|
124
|
+
and list(self.test_stations) == list(other.test_stations)
|
|
125
|
+
and list(self.hardware_items) == list(other.hardware_items)
|
|
126
|
+
and list(self.software_items) == list(other.software_items)
|
|
127
|
+
and list(self.test_adapters) == list(other.test_adapters)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def __str__(self) -> str:
|
|
131
|
+
"""Return a string representation of the MetadataItems."""
|
|
132
|
+
counts = []
|
|
133
|
+
if self.uut_instances:
|
|
134
|
+
counts.append(f"{len(self.uut_instances)} UUT instances")
|
|
135
|
+
if self.uuts:
|
|
136
|
+
counts.append(f"{len(self.uuts)} UUTs")
|
|
137
|
+
if self.operators:
|
|
138
|
+
counts.append(f"{len(self.operators)} operators")
|
|
139
|
+
if self.test_descriptions:
|
|
140
|
+
counts.append(f"{len(self.test_descriptions)} test descriptions")
|
|
141
|
+
if self.tests:
|
|
142
|
+
counts.append(f"{len(self.tests)} tests")
|
|
143
|
+
if self.test_stations:
|
|
144
|
+
counts.append(f"{len(self.test_stations)} test stations")
|
|
145
|
+
if self.hardware_items:
|
|
146
|
+
counts.append(f"{len(self.hardware_items)} hardware items")
|
|
147
|
+
if self.software_items:
|
|
148
|
+
counts.append(f"{len(self.software_items)} software items")
|
|
149
|
+
if self.test_adapters:
|
|
150
|
+
counts.append(f"{len(self.test_adapters)} test adapters")
|
|
151
|
+
|
|
152
|
+
if counts:
|
|
153
|
+
return f"MetadataItems({', '.join(counts)})"
|
|
154
|
+
else:
|
|
155
|
+
return "MetadataItems(empty)"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_grpc_conversion.py
RENAMED
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/_moniker.py
RENAMED
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/_outcome.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/data/_types/_test_result.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_grpc_conversion.py
RENAMED
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/__init__.py
RENAMED
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_alias.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_operator.py
RENAMED
|
File without changes
|
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/_uut.py
RENAMED
|
File without changes
|
|
File without changes
|
{ni_datastore-0.1.0.dev5 → ni_datastore-0.1.0.dev6}/src/ni/datastore/metadata/_types/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|