ni.datastore 0.1.0.dev2__tar.gz → 0.1.0.dev4__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.dev2 → ni_datastore-0.1.0.dev4}/PKG-INFO +5 -5
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/pyproject.toml +5 -5
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/_data_store_client.py +77 -15
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/_grpc_conversion.py +11 -5
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/_types/_published_condition.py +6 -6
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/_types/_published_measurement.py +43 -23
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/_types/_step.py +17 -10
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/_types/_test_result.py +44 -22
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_metadata_store_client.py +63 -18
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_hardware_item.py +22 -5
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_operator.py +22 -5
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_software_item.py +22 -5
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_test.py +22 -5
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_test_adapter.py +27 -10
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_test_description.py +22 -5
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_test_station.py +22 -5
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_uut.py +32 -8
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_uut_instance.py +22 -5
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/LICENSE +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/README.md +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/__init__.py +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/__init__.py +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/_types/__init__.py +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/_types/py.typed +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/py.typed +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/__init__.py +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_grpc_conversion.py +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/__init__.py +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_alias.py +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/_extension_schema.py +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/_types/py.typed +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/metadata/py.typed +0 -0
- {ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/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.dev4
|
|
4
4
|
Summary: APIs for publishing and retrieving data from the NI Measurement Data Store
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: datastore
|
|
@@ -24,10 +24,10 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
25
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
26
26
|
Requires-Dist: hightime (>=0.3.0.dev0)
|
|
27
|
-
Requires-Dist: ni-datamonikers-v1-client (>=0.1.0.
|
|
28
|
-
Requires-Dist: ni-measurements-data-v1-client (>=0.1.0.
|
|
29
|
-
Requires-Dist: ni-measurements-metadata-v1-client (>=0.1.0.
|
|
30
|
-
Requires-Dist: ni-protobuf-types (>=0.1.
|
|
27
|
+
Requires-Dist: ni-datamonikers-v1-client (>=0.1.0.dev1)
|
|
28
|
+
Requires-Dist: ni-measurements-data-v1-client (>=0.1.0.dev2)
|
|
29
|
+
Requires-Dist: ni-measurements-metadata-v1-client (>=0.1.0.dev2)
|
|
30
|
+
Requires-Dist: ni-protobuf-types (>=1.0.1.dev0)
|
|
31
31
|
Requires-Dist: protobuf (>=4.21)
|
|
32
32
|
Description-Content-Type: text/markdown
|
|
33
33
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ni.datastore"
|
|
3
|
-
version = "0.1.0
|
|
3
|
+
version = "0.1.0.dev4"
|
|
4
4
|
license = "MIT"
|
|
5
5
|
description = "APIs for publishing and retrieving data from the NI Measurement Data Store"
|
|
6
6
|
authors = [{name = "NI", email = "opensource@ni.com"}]
|
|
@@ -37,10 +37,10 @@ requires-poetry = '>=2.1,<3.0'
|
|
|
37
37
|
[tool.poetry.dependencies]
|
|
38
38
|
python = "^3.9"
|
|
39
39
|
protobuf = {version=">=4.21"}
|
|
40
|
-
ni-datamonikers-v1-client = { version = ">=0.1.0.
|
|
41
|
-
ni-measurements-data-v1-client = { version = ">=0.1.0.
|
|
42
|
-
ni-measurements-metadata-v1-client = { version = ">=0.1.0.
|
|
43
|
-
ni-protobuf-types = { version = ">=0.1.
|
|
40
|
+
ni-datamonikers-v1-client = { version = ">=0.1.0.dev1", allow-prereleases = true }
|
|
41
|
+
ni-measurements-data-v1-client = { version = ">=0.1.0.dev2", allow-prereleases = true }
|
|
42
|
+
ni-measurements-metadata-v1-client = { version = ">=0.1.0.dev2", allow-prereleases = true }
|
|
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
|
|
|
46
46
|
[tool.poetry.group.dev.dependencies]
|
{ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/_data_store_client.py
RENAMED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
|
-
|
|
6
|
+
import sys
|
|
7
|
+
from collections.abc import Iterable, Sequence
|
|
7
8
|
from threading import Lock
|
|
8
|
-
from
|
|
9
|
+
from types import TracebackType
|
|
10
|
+
from typing import TYPE_CHECKING, Type, TypeVar, overload
|
|
9
11
|
from urllib.parse import urlparse
|
|
10
12
|
|
|
11
13
|
import hightime as ht
|
|
@@ -42,12 +44,19 @@ from ni.measurements.data.v1.data_store_service_pb2 import (
|
|
|
42
44
|
QueryConditionsRequest,
|
|
43
45
|
QueryMeasurementsRequest,
|
|
44
46
|
QueryStepsRequest,
|
|
47
|
+
QueryTestResultsRequest,
|
|
45
48
|
)
|
|
46
49
|
from ni.protobuf.types.precision_timestamp_conversion import (
|
|
47
50
|
hightime_datetime_to_protobuf,
|
|
48
51
|
)
|
|
49
52
|
from ni_grpc_extensions.channelpool import GrpcChannelPool
|
|
50
53
|
|
|
54
|
+
if TYPE_CHECKING:
|
|
55
|
+
if sys.version_info >= (3, 11):
|
|
56
|
+
from typing import Self
|
|
57
|
+
else:
|
|
58
|
+
from typing_extensions import Self
|
|
59
|
+
|
|
51
60
|
TRead = TypeVar("TRead")
|
|
52
61
|
|
|
53
62
|
_logger = logging.getLogger(__name__)
|
|
@@ -57,6 +66,7 @@ class DataStoreClient:
|
|
|
57
66
|
"""Data store client for publishing and reading data."""
|
|
58
67
|
|
|
59
68
|
__slots__ = (
|
|
69
|
+
"_closed",
|
|
60
70
|
"_discovery_client",
|
|
61
71
|
"_grpc_channel",
|
|
62
72
|
"_grpc_channel_pool",
|
|
@@ -66,6 +76,9 @@ class DataStoreClient:
|
|
|
66
76
|
"_moniker_clients_lock",
|
|
67
77
|
)
|
|
68
78
|
|
|
79
|
+
_DATA_STORE_CLIENT_CLOSED_ERROR = "This DataStoreClient has been closed. Create a new DataStoreClient for further interaction with the data store."
|
|
80
|
+
|
|
81
|
+
_closed: bool
|
|
69
82
|
_discovery_client: DiscoveryClient | None
|
|
70
83
|
_grpc_channel: Channel | None
|
|
71
84
|
_grpc_channel_pool: GrpcChannelPool | None
|
|
@@ -102,6 +115,35 @@ class DataStoreClient:
|
|
|
102
115
|
self._data_store_client_lock = Lock()
|
|
103
116
|
self._moniker_clients_lock = Lock()
|
|
104
117
|
|
|
118
|
+
self._closed = False
|
|
119
|
+
|
|
120
|
+
def __enter__(self) -> Self:
|
|
121
|
+
"""Enter the runtime context of the data store client."""
|
|
122
|
+
return self
|
|
123
|
+
|
|
124
|
+
def __exit__(
|
|
125
|
+
self,
|
|
126
|
+
exc_type: type[BaseException] | None,
|
|
127
|
+
exc_val: BaseException | None,
|
|
128
|
+
traceback: TracebackType | None,
|
|
129
|
+
) -> None:
|
|
130
|
+
"""Exit the runtime context of the data store client."""
|
|
131
|
+
self.close()
|
|
132
|
+
|
|
133
|
+
def close(self) -> None:
|
|
134
|
+
"""Close the data store client and clean up resources that it owns."""
|
|
135
|
+
self._closed = True
|
|
136
|
+
|
|
137
|
+
with self._data_store_client_lock:
|
|
138
|
+
if self._data_store_client is not None:
|
|
139
|
+
self._data_store_client.close()
|
|
140
|
+
self._data_store_client = None
|
|
141
|
+
|
|
142
|
+
with self._moniker_clients_lock:
|
|
143
|
+
for _, moniker_client in self._moniker_clients_by_service_location.items():
|
|
144
|
+
moniker_client.close()
|
|
145
|
+
self._moniker_clients_by_service_location.clear()
|
|
146
|
+
|
|
105
147
|
def publish_condition(
|
|
106
148
|
self,
|
|
107
149
|
condition_name: str,
|
|
@@ -174,7 +216,7 @@ class DataStoreClient:
|
|
|
174
216
|
hardware_item_ids: Iterable[str] = tuple(),
|
|
175
217
|
test_adapter_ids: Iterable[str] = tuple(),
|
|
176
218
|
software_item_ids: Iterable[str] = tuple(),
|
|
177
|
-
) ->
|
|
219
|
+
) -> Sequence[PublishedMeasurement]:
|
|
178
220
|
"""Publish a batch of N values of a measurement to the data store."""
|
|
179
221
|
publish_request = PublishMeasurementBatchRequest(
|
|
180
222
|
measurement_name=measurement_name,
|
|
@@ -253,7 +295,7 @@ class DataStoreClient:
|
|
|
253
295
|
get_response = self._get_data_store_client().get_test_result(get_request)
|
|
254
296
|
return TestResult.from_protobuf(get_response.test_result)
|
|
255
297
|
|
|
256
|
-
def query_conditions(self, odata_query: str) ->
|
|
298
|
+
def query_conditions(self, odata_query: str = "") -> Sequence[PublishedCondition]:
|
|
257
299
|
"""Query conditions from the data store."""
|
|
258
300
|
query_request = QueryConditionsRequest(odata_query=odata_query)
|
|
259
301
|
query_response = self._get_data_store_client().query_conditions(query_request)
|
|
@@ -262,7 +304,7 @@ class DataStoreClient:
|
|
|
262
304
|
for published_condition in query_response.published_conditions
|
|
263
305
|
]
|
|
264
306
|
|
|
265
|
-
def query_measurements(self, odata_query: str) ->
|
|
307
|
+
def query_measurements(self, odata_query: str = "") -> Sequence[PublishedMeasurement]:
|
|
266
308
|
"""Query measurements from the data store."""
|
|
267
309
|
query_request = QueryMeasurementsRequest(odata_query=odata_query)
|
|
268
310
|
query_response = self._get_data_store_client().query_measurements(query_request)
|
|
@@ -271,32 +313,52 @@ class DataStoreClient:
|
|
|
271
313
|
for published_measurement in query_response.published_measurements
|
|
272
314
|
]
|
|
273
315
|
|
|
274
|
-
def
|
|
316
|
+
def query_test_results(self, odata_query: str = "") -> Sequence[TestResult]:
|
|
317
|
+
"""Query test results from the data store."""
|
|
318
|
+
query_request = QueryTestResultsRequest(odata_query=odata_query)
|
|
319
|
+
query_response = self._get_data_store_client().query_test_results(query_request)
|
|
320
|
+
return [
|
|
321
|
+
TestResult.from_protobuf(test_result) for test_result in query_response.test_results
|
|
322
|
+
]
|
|
323
|
+
|
|
324
|
+
def query_steps(self, odata_query: str = "") -> Sequence[Step]:
|
|
275
325
|
"""Query steps from the data store."""
|
|
276
326
|
query_request = QueryStepsRequest(odata_query=odata_query)
|
|
277
327
|
query_response = self._get_data_store_client().query_steps(query_request)
|
|
278
328
|
return [Step.from_protobuf(step) for step in query_response.steps]
|
|
279
329
|
|
|
280
330
|
def _get_data_store_client(self) -> DataStoreServiceClient:
|
|
331
|
+
if self._closed:
|
|
332
|
+
raise RuntimeError(self._DATA_STORE_CLIENT_CLOSED_ERROR)
|
|
333
|
+
|
|
281
334
|
if self._data_store_client is None:
|
|
282
335
|
with self._data_store_client_lock:
|
|
283
336
|
if self._data_store_client is None:
|
|
284
|
-
self._data_store_client =
|
|
285
|
-
discovery_client=self._discovery_client,
|
|
286
|
-
grpc_channel=self._grpc_channel,
|
|
287
|
-
grpc_channel_pool=self._grpc_channel_pool,
|
|
288
|
-
)
|
|
337
|
+
self._data_store_client = self._instantiate_data_store_client()
|
|
289
338
|
return self._data_store_client
|
|
290
339
|
|
|
340
|
+
def _instantiate_data_store_client(self) -> DataStoreServiceClient:
|
|
341
|
+
return DataStoreServiceClient(
|
|
342
|
+
discovery_client=self._discovery_client,
|
|
343
|
+
grpc_channel=self._grpc_channel,
|
|
344
|
+
grpc_channel_pool=self._grpc_channel_pool,
|
|
345
|
+
)
|
|
346
|
+
|
|
291
347
|
def _get_moniker_client(self, service_location: str) -> MonikerClient:
|
|
348
|
+
if self._closed:
|
|
349
|
+
raise RuntimeError(self._DATA_STORE_CLIENT_CLOSED_ERROR)
|
|
350
|
+
|
|
292
351
|
parsed_service_location = urlparse(service_location).netloc
|
|
293
352
|
if parsed_service_location not in self._moniker_clients_by_service_location:
|
|
294
353
|
with self._moniker_clients_lock:
|
|
295
354
|
if parsed_service_location not in self._moniker_clients_by_service_location:
|
|
296
355
|
self._moniker_clients_by_service_location[parsed_service_location] = (
|
|
297
|
-
|
|
298
|
-
service_location=parsed_service_location,
|
|
299
|
-
grpc_channel_pool=self._grpc_channel_pool,
|
|
300
|
-
)
|
|
356
|
+
self._instantiate_moniker_client(parsed_service_location)
|
|
301
357
|
)
|
|
302
358
|
return self._moniker_clients_by_service_location[parsed_service_location]
|
|
359
|
+
|
|
360
|
+
def _instantiate_moniker_client(self, parsed_service_location: str) -> MonikerClient:
|
|
361
|
+
return MonikerClient(
|
|
362
|
+
service_location=parsed_service_location,
|
|
363
|
+
grpc_channel_pool=self._grpc_channel_pool,
|
|
364
|
+
)
|
{ni_datastore-0.1.0.dev2 → ni_datastore-0.1.0.dev4}/src/ni/datastore/data/_grpc_conversion.py
RENAMED
|
@@ -44,11 +44,16 @@ from ni.protobuf.types.waveform_pb2 import (
|
|
|
44
44
|
I16AnalogWaveform,
|
|
45
45
|
I16ComplexWaveform,
|
|
46
46
|
)
|
|
47
|
+
from ni.protobuf.types.xydata_conversion import (
|
|
48
|
+
float64_xydata_from_protobuf,
|
|
49
|
+
float64_xydata_to_protobuf,
|
|
50
|
+
)
|
|
47
51
|
from ni.protobuf.types.xydata_pb2 import DoubleXYData
|
|
48
52
|
from nitypes.complex import ComplexInt32DType
|
|
49
53
|
from nitypes.scalar import Scalar
|
|
50
54
|
from nitypes.vector import Vector
|
|
51
55
|
from nitypes.waveform import AnalogWaveform, ComplexWaveform, DigitalWaveform, Spectrum
|
|
56
|
+
from nitypes.xy_data import XYData
|
|
52
57
|
|
|
53
58
|
_logger = logging.getLogger(__name__)
|
|
54
59
|
|
|
@@ -137,6 +142,11 @@ def populate_publish_measurement_request_value(
|
|
|
137
142
|
raise TypeError(f"Unsupported Spectrum dtype: {value.dtype}")
|
|
138
143
|
elif isinstance(value, DigitalWaveform):
|
|
139
144
|
publish_request.digital_waveform.CopyFrom(digital_waveform_to_protobuf(value))
|
|
145
|
+
elif isinstance(value, XYData):
|
|
146
|
+
if value.dtype == np.float64:
|
|
147
|
+
publish_request.x_y_data.CopyFrom(float64_xydata_to_protobuf(value))
|
|
148
|
+
else:
|
|
149
|
+
raise TypeError(f"Unsupported XYData dtype: {value.dtype}")
|
|
140
150
|
elif isinstance(value, Iterable):
|
|
141
151
|
if not value:
|
|
142
152
|
raise ValueError("Cannot publish an empty Iterable.")
|
|
@@ -152,7 +162,6 @@ def populate_publish_measurement_request_value(
|
|
|
152
162
|
raise TypeError(
|
|
153
163
|
f"Unsupported measurement value type: {type(value)}. Please consult the documentation."
|
|
154
164
|
)
|
|
155
|
-
# TODO: Implement conversion from proper XYData type
|
|
156
165
|
|
|
157
166
|
|
|
158
167
|
def populate_publish_measurement_batch_request_values(
|
|
@@ -208,10 +217,7 @@ def unpack_and_convert_from_protobuf_any(read_value: Any) -> object:
|
|
|
208
217
|
elif value_type == DoubleXYData.DESCRIPTOR.full_name:
|
|
209
218
|
xydata = DoubleXYData()
|
|
210
219
|
read_value.Unpack(xydata)
|
|
211
|
-
|
|
212
|
-
"DoubleXYData conversion is not yet implemented. Returning the raw protobuf object."
|
|
213
|
-
)
|
|
214
|
-
return xydata
|
|
220
|
+
return float64_xydata_from_protobuf(xydata)
|
|
215
221
|
elif value_type == VectorProto.DESCRIPTOR.full_name:
|
|
216
222
|
vector = VectorProto()
|
|
217
223
|
read_value.Unpack(vector)
|
|
@@ -13,7 +13,7 @@ class PublishedCondition:
|
|
|
13
13
|
|
|
14
14
|
__slots__ = (
|
|
15
15
|
"moniker",
|
|
16
|
-
"
|
|
16
|
+
"id",
|
|
17
17
|
"condition_name",
|
|
18
18
|
"condition_type",
|
|
19
19
|
"step_id",
|
|
@@ -24,7 +24,7 @@ class PublishedCondition:
|
|
|
24
24
|
self,
|
|
25
25
|
*,
|
|
26
26
|
moniker: Moniker | None = None,
|
|
27
|
-
|
|
27
|
+
id: str = "",
|
|
28
28
|
condition_name: str = "",
|
|
29
29
|
condition_type: str = "",
|
|
30
30
|
step_id: str = "",
|
|
@@ -32,7 +32,7 @@ class PublishedCondition:
|
|
|
32
32
|
) -> None:
|
|
33
33
|
"""Initialize a PublishedCondition instance."""
|
|
34
34
|
self.moniker = moniker
|
|
35
|
-
self.
|
|
35
|
+
self.id = id
|
|
36
36
|
self.condition_name = condition_name
|
|
37
37
|
self.condition_type = condition_type
|
|
38
38
|
self.step_id = step_id
|
|
@@ -47,7 +47,7 @@ class PublishedCondition:
|
|
|
47
47
|
if published_condition_proto.HasField("moniker")
|
|
48
48
|
else None
|
|
49
49
|
),
|
|
50
|
-
|
|
50
|
+
id=published_condition_proto.id,
|
|
51
51
|
condition_name=published_condition_proto.condition_name,
|
|
52
52
|
condition_type=published_condition_proto.condition_type,
|
|
53
53
|
step_id=published_condition_proto.step_id,
|
|
@@ -58,7 +58,7 @@ class PublishedCondition:
|
|
|
58
58
|
"""Convert this PublishedCondition instance to a protobuf PublishedCondition message."""
|
|
59
59
|
return PublishedConditionProto(
|
|
60
60
|
moniker=self.moniker,
|
|
61
|
-
|
|
61
|
+
id=self.id,
|
|
62
62
|
condition_name=self.condition_name,
|
|
63
63
|
condition_type=self.condition_type,
|
|
64
64
|
step_id=self.step_id,
|
|
@@ -71,7 +71,7 @@ class PublishedCondition:
|
|
|
71
71
|
return NotImplemented
|
|
72
72
|
return (
|
|
73
73
|
self.moniker == other.moniker
|
|
74
|
-
and self.
|
|
74
|
+
and self.id == other.id
|
|
75
75
|
and self.condition_name == other.condition_name
|
|
76
76
|
and self.condition_type == other.condition_type
|
|
77
77
|
and self.step_id == other.step_id
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import Iterable
|
|
5
|
+
from typing import Iterable, MutableSequence
|
|
6
6
|
|
|
7
7
|
import hightime as ht
|
|
8
8
|
from ni.datamonikers.v1.data_moniker_pb2 import Moniker
|
|
@@ -23,13 +23,13 @@ class PublishedMeasurement:
|
|
|
23
23
|
|
|
24
24
|
__slots__ = (
|
|
25
25
|
"moniker",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
26
|
+
"_published_conditions",
|
|
27
|
+
"id",
|
|
28
28
|
"test_result_id",
|
|
29
29
|
"step_id",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
30
|
+
"_software_item_ids",
|
|
31
|
+
"_hardware_item_ids",
|
|
32
|
+
"_test_adapter_ids",
|
|
33
33
|
"measurement_name",
|
|
34
34
|
"data_type",
|
|
35
35
|
"measurement_notes",
|
|
@@ -40,12 +40,32 @@ class PublishedMeasurement:
|
|
|
40
40
|
"error_information",
|
|
41
41
|
)
|
|
42
42
|
|
|
43
|
+
@property
|
|
44
|
+
def published_conditions(self) -> MutableSequence[PublishedCondition]:
|
|
45
|
+
"""The published conditions associated with the published measurement."""
|
|
46
|
+
return self._published_conditions
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def software_item_ids(self) -> MutableSequence[str]:
|
|
50
|
+
"""The software item IDs associated with the published measurement."""
|
|
51
|
+
return self._software_item_ids
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def hardware_item_ids(self) -> MutableSequence[str]:
|
|
55
|
+
"""The hardware item IDs associated with the published measurement."""
|
|
56
|
+
return self._hardware_item_ids
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def test_adapter_ids(self) -> MutableSequence[str]:
|
|
60
|
+
"""The test adapter IDs associated with the published measurement."""
|
|
61
|
+
return self._test_adapter_ids
|
|
62
|
+
|
|
43
63
|
def __init__(
|
|
44
64
|
self,
|
|
45
65
|
*,
|
|
46
66
|
moniker: Moniker | None = None,
|
|
47
67
|
published_conditions: Iterable[PublishedCondition] | None = None,
|
|
48
|
-
|
|
68
|
+
id: str = "",
|
|
49
69
|
test_result_id: str = "",
|
|
50
70
|
step_id: str = "",
|
|
51
71
|
software_item_ids: Iterable[str] | None = None,
|
|
@@ -62,20 +82,20 @@ class PublishedMeasurement:
|
|
|
62
82
|
) -> None:
|
|
63
83
|
"""Initialize a PublishedMeasurement instance."""
|
|
64
84
|
self.moniker = moniker
|
|
65
|
-
self.
|
|
66
|
-
published_conditions if published_conditions is not None else []
|
|
85
|
+
self._published_conditions: MutableSequence[PublishedCondition] = (
|
|
86
|
+
list(published_conditions) if published_conditions is not None else []
|
|
67
87
|
)
|
|
68
|
-
self.
|
|
88
|
+
self.id = id
|
|
69
89
|
self.test_result_id = test_result_id
|
|
70
90
|
self.step_id = step_id
|
|
71
|
-
self.
|
|
72
|
-
software_item_ids if software_item_ids is not None else []
|
|
91
|
+
self._software_item_ids: MutableSequence[str] = (
|
|
92
|
+
list(software_item_ids) if software_item_ids is not None else []
|
|
73
93
|
)
|
|
74
|
-
self.
|
|
75
|
-
hardware_item_ids if hardware_item_ids is not None else []
|
|
94
|
+
self._hardware_item_ids: MutableSequence[str] = (
|
|
95
|
+
list(hardware_item_ids) if hardware_item_ids is not None else []
|
|
76
96
|
)
|
|
77
|
-
self.
|
|
78
|
-
test_adapter_ids if test_adapter_ids is not None else []
|
|
97
|
+
self._test_adapter_ids: MutableSequence[str] = (
|
|
98
|
+
list(test_adapter_ids) if test_adapter_ids is not None else []
|
|
79
99
|
)
|
|
80
100
|
self.measurement_name = measurement_name
|
|
81
101
|
self.data_type = data_type
|
|
@@ -101,7 +121,7 @@ class PublishedMeasurement:
|
|
|
101
121
|
PublishedCondition.from_protobuf(cond)
|
|
102
122
|
for cond in published_measurement_proto.published_conditions
|
|
103
123
|
],
|
|
104
|
-
|
|
124
|
+
id=published_measurement_proto.id,
|
|
105
125
|
test_result_id=published_measurement_proto.test_result_id,
|
|
106
126
|
step_id=published_measurement_proto.step_id,
|
|
107
127
|
software_item_ids=published_measurement_proto.software_item_ids,
|
|
@@ -136,7 +156,7 @@ class PublishedMeasurement:
|
|
|
136
156
|
published_conditions=[
|
|
137
157
|
condition.to_protobuf() for condition in self.published_conditions
|
|
138
158
|
],
|
|
139
|
-
|
|
159
|
+
id=self.id,
|
|
140
160
|
test_result_id=self.test_result_id,
|
|
141
161
|
step_id=self.step_id,
|
|
142
162
|
software_item_ids=self.software_item_ids,
|
|
@@ -166,13 +186,13 @@ class PublishedMeasurement:
|
|
|
166
186
|
return NotImplemented
|
|
167
187
|
return (
|
|
168
188
|
self.moniker == other.moniker
|
|
169
|
-
and
|
|
170
|
-
and self.
|
|
189
|
+
and self.published_conditions == other.published_conditions
|
|
190
|
+
and self.id == other.id
|
|
171
191
|
and self.test_result_id == other.test_result_id
|
|
172
192
|
and self.step_id == other.step_id
|
|
173
|
-
and
|
|
174
|
-
and
|
|
175
|
-
and
|
|
193
|
+
and self.software_item_ids == other.software_item_ids
|
|
194
|
+
and self.hardware_item_ids == other.hardware_item_ids
|
|
195
|
+
and self.test_adapter_ids == other.test_adapter_ids
|
|
176
196
|
and self.measurement_name == other.measurement_name
|
|
177
197
|
and self.data_type == other.data_type
|
|
178
198
|
and self.measurement_notes == other.measurement_notes
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import MutableMapping
|
|
5
|
+
from typing import Mapping, MutableMapping
|
|
6
6
|
|
|
7
7
|
import hightime as ht
|
|
8
8
|
from ni.datastore.metadata._grpc_conversion import (
|
|
@@ -22,7 +22,7 @@ class Step:
|
|
|
22
22
|
"""Information about a step into which measurements and conditions are published."""
|
|
23
23
|
|
|
24
24
|
__slots__ = (
|
|
25
|
-
"
|
|
25
|
+
"id",
|
|
26
26
|
"parent_step_id",
|
|
27
27
|
"test_result_id",
|
|
28
28
|
"test_id",
|
|
@@ -32,7 +32,7 @@ class Step:
|
|
|
32
32
|
"_start_date_time",
|
|
33
33
|
"_end_date_time",
|
|
34
34
|
"link",
|
|
35
|
-
"
|
|
35
|
+
"_extensions",
|
|
36
36
|
"schema_id",
|
|
37
37
|
)
|
|
38
38
|
|
|
@@ -46,10 +46,15 @@ class Step:
|
|
|
46
46
|
"""Get the end date and time of the step execution."""
|
|
47
47
|
return self._end_date_time
|
|
48
48
|
|
|
49
|
+
@property
|
|
50
|
+
def extensions(self) -> MutableMapping[str, str]:
|
|
51
|
+
"""The extensions of the step."""
|
|
52
|
+
return self._extensions
|
|
53
|
+
|
|
49
54
|
def __init__(
|
|
50
55
|
self,
|
|
51
56
|
*,
|
|
52
|
-
|
|
57
|
+
id: str = "",
|
|
53
58
|
parent_step_id: str = "",
|
|
54
59
|
test_result_id: str = "",
|
|
55
60
|
test_id: str = "",
|
|
@@ -57,11 +62,11 @@ class Step:
|
|
|
57
62
|
step_type: str = "",
|
|
58
63
|
notes: str = "",
|
|
59
64
|
link: str = "",
|
|
60
|
-
extensions:
|
|
65
|
+
extensions: Mapping[str, str] | None = None,
|
|
61
66
|
schema_id: str = "",
|
|
62
67
|
) -> None:
|
|
63
68
|
"""Initialize a Step instance."""
|
|
64
|
-
self.
|
|
69
|
+
self.id = id
|
|
65
70
|
self.parent_step_id = parent_step_id
|
|
66
71
|
self.test_result_id = test_result_id
|
|
67
72
|
self.test_id = test_id
|
|
@@ -69,7 +74,9 @@ class Step:
|
|
|
69
74
|
self.step_type = step_type
|
|
70
75
|
self.notes = notes
|
|
71
76
|
self.link = link
|
|
72
|
-
self.
|
|
77
|
+
self._extensions: MutableMapping[str, str] = (
|
|
78
|
+
dict(extensions) if extensions is not None else {}
|
|
79
|
+
)
|
|
73
80
|
self.schema_id = schema_id
|
|
74
81
|
|
|
75
82
|
self._start_date_time: ht.datetime | None = None
|
|
@@ -79,7 +86,7 @@ class Step:
|
|
|
79
86
|
def from_protobuf(step_proto: StepProto) -> "Step":
|
|
80
87
|
"""Create a Step instance from a protobuf Step message."""
|
|
81
88
|
step = Step(
|
|
82
|
-
|
|
89
|
+
id=step_proto.id,
|
|
83
90
|
parent_step_id=step_proto.parent_step_id,
|
|
84
91
|
test_result_id=step_proto.test_result_id,
|
|
85
92
|
test_id=step_proto.test_id,
|
|
@@ -105,7 +112,7 @@ class Step:
|
|
|
105
112
|
def to_protobuf(self) -> StepProto:
|
|
106
113
|
"""Convert this Step to a protobuf Step message."""
|
|
107
114
|
step_proto = StepProto(
|
|
108
|
-
|
|
115
|
+
id=self.id,
|
|
109
116
|
parent_step_id=self.parent_step_id,
|
|
110
117
|
test_result_id=self.test_result_id,
|
|
111
118
|
test_id=self.test_id,
|
|
@@ -131,7 +138,7 @@ class Step:
|
|
|
131
138
|
if not isinstance(other, Step):
|
|
132
139
|
return NotImplemented
|
|
133
140
|
return (
|
|
134
|
-
self.
|
|
141
|
+
self.id == other.id
|
|
135
142
|
and self.parent_step_id == other.parent_step_id
|
|
136
143
|
and self.test_result_id == other.test_result_id
|
|
137
144
|
and self.test_id == other.test_id
|