diff --git a/src/ni/datastore/data/_data_store_client.py b/src/ni/datastore/data/_data_store_client.py index 6cde16b..bd9b176 100644 --- a/src/ni/datastore/data/_data_store_client.py +++ b/src/ni/datastore/data/_data_store_client.py @@ -37,9 +37,9 @@ from ni_grpc_extensions.channelpool import GrpcChannelPool from ni.datastore.data._grpc_conversion import ( + convert_measurement_timestamp_to_protobuf, convert_read_condition_response_from_protobuf, convert_read_measurement_response_from_protobuf, - get_publish_measurement_timestamp, populate_publish_condition_batch_request_values, populate_publish_condition_request_value, populate_publish_measurement_batch_request_values, @@ -238,8 +238,8 @@ def publish_measurement( step_id: The ID of the step associated with this measurement. This value is expected to be a parsable GUID. - timestamp: The timestamp of the measurement. If None, the current - time will be used. + timestamp: The timestamp of the measurement. If None, no timestamp + will be specified. outcome: The outcome of the measurement (PASSED, FAILED, INDETERMINATE, or UNSPECIFIED). @@ -275,11 +275,9 @@ def publish_measurement( test_adapter_ids=test_adapter_ids, software_item_ids=software_item_ids, notes=notes, + timestamp=convert_measurement_timestamp_to_protobuf(timestamp), ) populate_publish_measurement_request_value(publish_request, value) - publish_request.timestamp.CopyFrom( - get_publish_measurement_timestamp(publish_request, timestamp) - ) publish_response = self._get_data_store_client().publish_measurement(publish_request) return publish_response.measurement_id diff --git a/src/ni/datastore/data/_grpc_conversion.py b/src/ni/datastore/data/_grpc_conversion.py index 70bb863..1d36795 100644 --- a/src/ni/datastore/data/_grpc_conversion.py +++ b/src/ni/datastore/data/_grpc_conversion.py @@ -2,7 +2,6 @@ from __future__ import annotations -import datetime as std_datetime import logging from itertools import chain from typing import Any, Callable, cast, Iterable @@ -364,32 +363,11 @@ def convert_read_condition_response_from_protobuf(response: ReadConditionValueRe raise TypeError(f"Invalid read type: {read_data_type}") -def get_publish_measurement_timestamp( - publish_request: PublishMeasurementRequest, client_provided_timestamp: ht.datetime | None -) -> PrecisionTimestamp: - """Determine the correct timestamp to use for publishing a measurement.""" - no_client_timestamp_provided = client_provided_timestamp is None - if no_client_timestamp_provided: - publish_time = hightime_datetime_to_protobuf(ht.datetime.now(std_datetime.timezone.utc)) +def convert_measurement_timestamp_to_protobuf( + client_provided_timestamp: ht.datetime | None, +) -> PrecisionTimestamp | None: + """Convert the provided timestamp to PrecisionTimestamp if it's not None.""" + if client_provided_timestamp is not None: + return hightime_datetime_to_protobuf(client_provided_timestamp) else: - publish_time = hightime_datetime_to_protobuf(cast(ht.datetime, client_provided_timestamp)) - - waveform_t0: PrecisionTimestamp | None = None - value_case = publish_request.WhichOneof("value") - if value_case == "double_analog_waveform": - waveform_t0 = publish_request.double_analog_waveform.t0 - elif value_case == "i16_analog_waveform": - waveform_t0 = publish_request.i16_analog_waveform.t0 - elif value_case == "double_complex_waveform": - waveform_t0 = publish_request.double_complex_waveform.t0 - elif value_case == "i16_complex_waveform": - waveform_t0 = publish_request.i16_complex_waveform.t0 - elif value_case == "digital_waveform": - waveform_t0 = publish_request.digital_waveform.t0 - - # If an initialized waveform t0 value is present and no client timestamp was provided, - # use the waveform t0 as the measurement start time. - if waveform_t0 is not None and waveform_t0 != PrecisionTimestamp(): - if no_client_timestamp_provided: - publish_time = waveform_t0 - return publish_time + return None diff --git a/tests/unit/data/test_publish_measurement.py b/tests/unit/data/test_publish_measurement.py index b4c9f7f..d437457 100644 --- a/tests/unit/data/test_publish_measurement.py +++ b/tests/unit/data/test_publish_measurement.py @@ -3,7 +3,6 @@ from __future__ import annotations import datetime as std_datetime -import unittest.mock from typing import Any, cast, Iterable from unittest.mock import NonCallableMock @@ -23,6 +22,7 @@ from ni.protobuf.types.precision_timestamp_conversion import ( hightime_datetime_to_protobuf, ) +from ni.protobuf.types.precision_timestamp_pb2 import PrecisionTimestamp from ni.protobuf.types.vector_conversion import vector_to_protobuf from ni.protobuf.types.vector_pb2 import Vector as VectorProto from ni.protobuf.types.waveform_conversion import float64_analog_waveform_to_protobuf @@ -65,7 +65,7 @@ def test___publish_boolean_data___calls_data_store_service_client( assert request.step_id == "step_id" assert request.name == "name" assert request.notes == "notes" - assert request.timestamp == unittest.mock.ANY + assert request.timestamp == hightime_datetime_to_protobuf(timestamp) assert request.scalar.bool_value == value assert request.outcome == OutcomeProto.OUTCOME_PASSED assert request.error_information == ErrorInformationProto() @@ -184,7 +184,7 @@ def test___unsupported_list___publish_measurement___raises_type_error( assert exc.value.args[0].startswith("Unsupported iterable:") -def test___publish_analog_waveform_data_without_timestamp_parameter___uses_waveform_t0( +def test___publish_analog_waveform_data_without_timestamp_parameter___timestamp_is_unset( data_store_client: DataStoreClient, mocked_data_store_service_client: NonCallableMock, ) -> None: @@ -203,7 +203,8 @@ def test___publish_analog_waveform_data_without_timestamp_parameter___uses_wavef args, __ = mocked_data_store_service_client.publish_measurement.call_args request = cast(PublishMeasurementRequest, args[0]) # The PublishMeasurementRequest object assert measurement_id == "response_id" - assert request.timestamp == hightime_datetime_to_protobuf(timestamp) + assert not request.HasField("timestamp") + assert request.timestamp == PrecisionTimestamp() def test___publish_analog_waveform_data_without_t0___uses_timestamp_parameter( @@ -251,23 +252,21 @@ def test___publish_analog_waveform_data_with_mismatched_timestamp_parameter___us assert request.timestamp == hightime_datetime_to_protobuf(mismatched_timestamp) -def test___publish_analog_waveform_data_without_t0_or_timestamp___uses_now( +def test___publish_analog_waveform_data_without_t0_or_timestamp___timestamp_is_unset( data_store_client: DataStoreClient, mocked_data_store_service_client: NonCallableMock, ) -> None: - now = datetime.now(tz=std_datetime.timezone.utc) analog_waveform = AnalogWaveform.from_array_1d([1.0, 2.0, 3.0], dtype=float) mocked_data_store_service_client.publish_measurement.return_value = PublishMeasurementResponse( measurement_id="response_id" ) - with unittest.mock.patch("ni.datastore.data._grpc_conversion.ht.datetime") as mock_ht_datetime: - mock_ht_datetime.now.return_value = now - data_store_client.publish_measurement("name", analog_waveform, "step_id") + data_store_client.publish_measurement("name", analog_waveform, "step_id") args, __ = mocked_data_store_service_client.publish_measurement.call_args request = cast(PublishMeasurementRequest, args[0]) - assert request.timestamp == hightime_datetime_to_protobuf(now) + assert not request.HasField("timestamp") + assert request.timestamp == PrecisionTimestamp() def test___none___publish_measurement___raises_type_error(