Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/nipanel/_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
IntCollectionConverter,
StrCollectionConverter,
)
from nipanel.converters.protobuf_types import DoubleAnalogWaveformConverter, ScalarConverter

_logger = logging.getLogger(__name__)

Expand All @@ -38,6 +39,9 @@
FloatCollectionConverter(),
IntCollectionConverter(),
StrCollectionConverter(),
# Protobuf Types
DoubleAnalogWaveformConverter(),
ScalarConverter(),
]

_CONVERTIBLE_COLLECTION_TYPES = {
Expand Down
75 changes: 66 additions & 9 deletions tests/unit/test_convert.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
from typing import Any, Type, Union
from typing import Any, Union

import numpy as np
import pytest
from google.protobuf import any_pb2, wrappers_pb2
from google.protobuf.message import Message
from ni.protobuf.types.scalar_pb2 import ScalarData
from ni.pythonpanel.v1 import python_panel_types_pb2
from ni_measurement_plugin_sdk_service._internal.stubs.ni.protobuf.types.waveform_pb2 import (
DoubleAnalogWaveform,
)
from nitypes.scalar import Scalar
from nitypes.waveform import AnalogWaveform
from typing_extensions import TypeAlias

import nipanel._convert
Expand All @@ -26,7 +34,7 @@


# ========================================================
# Python to Protobuf
# Built-in Types: Python to Protobuf
# ========================================================
@pytest.mark.parametrize(
"proto_type, default_value, expected_value",
Expand All @@ -39,7 +47,7 @@
],
)
def test___python_builtin_scalar___to_any___valid_wrapperpb2_value(
proto_type: Type[_AnyWrappersPb2], default_value: Any, expected_value: Any
proto_type: type[_AnyWrappersPb2], default_value: Any, expected_value: Any
) -> None:
result = nipanel._convert.to_any(expected_value)
unpack_dest = proto_type(value=default_value)
Expand All @@ -60,7 +68,7 @@ def test___python_builtin_scalar___to_any___valid_wrapperpb2_value(
],
)
def test___python_panel_collection___to_any___valid_paneltype_value(
proto_type: Type[_AnyPanelPbTypes], default_value: Any, expected_value: Any
proto_type: type[_AnyPanelPbTypes], default_value: Any, expected_value: Any
) -> None:
result = nipanel._convert.to_any(expected_value)
unpack_dest = proto_type(values=default_value)
Expand All @@ -71,7 +79,7 @@ def test___python_panel_collection___to_any___valid_paneltype_value(


# ========================================================
# Protobuf to Python
# Built-in Types: Protobuf to Python
# ========================================================
@pytest.mark.parametrize(
"proto_type, expected_value",
Expand All @@ -84,7 +92,7 @@ def test___python_panel_collection___to_any___valid_paneltype_value(
],
)
def test___wrapperpb2_value___from_any___valid_python_value(
proto_type: Type[_AnyWrappersPb2], expected_value: Any
proto_type: type[_AnyWrappersPb2], expected_value: Any
) -> None:
pb_value = proto_type(value=expected_value)
packed_any = _pack_into_any(pb_value)
Expand All @@ -106,7 +114,7 @@ def test___wrapperpb2_value___from_any___valid_python_value(
],
)
def test___paneltype_value___from_any___valid_python_value(
proto_type: Type[_AnyPanelPbTypes], expected_value: Any
proto_type: type[_AnyPanelPbTypes], expected_value: Any
) -> None:
pb_value = proto_type(values=expected_value)
packed_any = _pack_into_any(pb_value)
Expand All @@ -117,15 +125,64 @@ def test___paneltype_value___from_any___valid_python_value(
assert result == expected_value


# ========================================================
# Protobuf Types: Python to Protobuf
# ========================================================
def test___python_scalar_object___to_any___valid_scalar_data_value() -> None:
scalar_obj = Scalar(1.0, "amps")
result = nipanel._convert.to_any(scalar_obj)
unpack_dest = ScalarData()
_assert_any_and_unpack(result, unpack_dest)

assert isinstance(unpack_dest, ScalarData)
assert unpack_dest.double_value == 1.0
assert unpack_dest.units == "amps"


def test___python_analog_waveform___to_any___valid_double_analog_waveform() -> None:
wfm_obj = AnalogWaveform(3)
result = nipanel._convert.to_any(wfm_obj)
unpack_dest = DoubleAnalogWaveform()
_assert_any_and_unpack(result, unpack_dest)

assert isinstance(unpack_dest, DoubleAnalogWaveform)
assert list(unpack_dest.y_data) == [0.0, 0.0, 0.0]


# ========================================================
# Protobuf Types: Protobuf to Python
# ========================================================
def test___scalar_data___from_any___valid_python_scalar_object() -> None:
pb_value = ScalarData(units="amps", double_value=1.0)
packed_any = _pack_into_any(pb_value)

result = nipanel._convert.from_any(packed_any)

assert isinstance(result, Scalar)
assert result.value == 1.0
assert result.units == "amps"


def test___double_analog_waveform___from_any___valid_python_analog_waveform() -> None:
pb_value = DoubleAnalogWaveform(y_data=[0.0, 0.0, 0.0])
packed_any = _pack_into_any(pb_value)

result = nipanel._convert.from_any(packed_any)

assert isinstance(result, AnalogWaveform)
assert result.sample_count == result.capacity == len(result.raw_data) == 3
assert result.dtype == np.float64


# ========================================================
# Pack/Unpack Helpers
# ========================================================
def _assert_any_and_unpack(packed_message: any_pb2.Any, unpack_destination: Any) -> None:
def _assert_any_and_unpack(packed_message: any_pb2.Any, unpack_destination: Message) -> None:
assert isinstance(packed_message, any_pb2.Any)
assert packed_message.Unpack(unpack_destination)


def _pack_into_any(proto_value: Union[_AnyWrappersPb2, _AnyPanelPbTypes]) -> any_pb2.Any:
def _pack_into_any(proto_value: Message) -> any_pb2.Any:
as_any = any_pb2.Any()
as_any.Pack(proto_value)
return as_any