Skip to content

Commit d2a957b

Browse files
mjohanse-emrMichael Johansen
andauthored
Add new protobuf converters to _convert.py. (#88)
Signed-off-by: Michael Johansen <michael.johansen@ni.com> Co-authored-by: Michael Johansen <michael.johansen@ni.com>
1 parent f11d190 commit d2a957b

File tree

2 files changed

+112
-51
lines changed

2 files changed

+112
-51
lines changed

src/nipanel/_convert.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
IntCollectionConverter,
2222
StrCollectionConverter,
2323
)
24+
from nipanel.converters.protobuf_types import DoubleAnalogWaveformConverter, ScalarConverter
2425

2526
_logger = logging.getLogger(__name__)
2627

@@ -38,6 +39,9 @@
3839
FloatCollectionConverter(),
3940
IntCollectionConverter(),
4041
StrCollectionConverter(),
42+
# Protobuf Types
43+
DoubleAnalogWaveformConverter(),
44+
ScalarConverter(),
4145
]
4246

4347
_CONVERTIBLE_COLLECTION_TYPES = {

tests/unit/test_convert.py

Lines changed: 108 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
from typing import Any, Type, Union
1+
from typing import Any, Union
22

3+
import numpy as np
34
import pytest
45
from google.protobuf import any_pb2, wrappers_pb2
6+
from google.protobuf.message import Message
7+
from ni.protobuf.types.scalar_pb2 import ScalarData
58
from ni.pythonpanel.v1 import python_panel_types_pb2
9+
from ni_measurement_plugin_sdk_service._internal.stubs.ni.protobuf.types.waveform_pb2 import (
10+
DoubleAnalogWaveform,
11+
)
12+
from nitypes.scalar import Scalar
13+
from nitypes.waveform import AnalogWaveform
614
from typing_extensions import TypeAlias
715

816
import nipanel._convert
@@ -25,51 +33,6 @@
2533
]
2634

2735

28-
# ========================================================
29-
# Python to Protobuf
30-
# ========================================================
31-
@pytest.mark.parametrize(
32-
"proto_type, default_value, expected_value",
33-
[
34-
(wrappers_pb2.BoolValue, False, True),
35-
(wrappers_pb2.BytesValue, b"", b"mystr"),
36-
(wrappers_pb2.DoubleValue, 0.0, 456.2),
37-
(wrappers_pb2.Int64Value, 0, 123),
38-
(wrappers_pb2.StringValue, "", "mystr"),
39-
],
40-
)
41-
def test___python_builtin_scalar___to_any___valid_wrapperpb2_value(
42-
proto_type: Type[_AnyWrappersPb2], default_value: Any, expected_value: Any
43-
) -> None:
44-
result = nipanel._convert.to_any(expected_value)
45-
unpack_dest = proto_type(value=default_value)
46-
_assert_any_and_unpack(result, unpack_dest)
47-
48-
assert isinstance(unpack_dest, proto_type)
49-
assert unpack_dest.value == expected_value
50-
51-
52-
@pytest.mark.parametrize(
53-
"proto_type, default_value, expected_value",
54-
[
55-
(python_panel_types_pb2.BoolCollection, [False, False, False], [True, True, True]),
56-
(python_panel_types_pb2.ByteStringCollection, [b"", b"", b""], [b"a", b"b", b"c"]),
57-
(python_panel_types_pb2.FloatCollection, [0.0, 0.0, 0.0], [1.0, 2.0, 3.0]),
58-
(python_panel_types_pb2.IntCollection, [0, 0, 0], [1, 2, 3]),
59-
(python_panel_types_pb2.StringCollection, ["", "", ""], ["a", "b", "c"]),
60-
],
61-
)
62-
def test___python_panel_collection___to_any___valid_paneltype_value(
63-
proto_type: Type[_AnyPanelPbTypes], default_value: Any, expected_value: Any
64-
) -> None:
65-
result = nipanel._convert.to_any(expected_value)
66-
unpack_dest = proto_type(values=default_value)
67-
_assert_any_and_unpack(result, unpack_dest)
68-
69-
assert isinstance(unpack_dest, proto_type)
70-
assert unpack_dest.values == expected_value
71-
72-
7336
# ========================================================
7437
# _get_best_matching_type() tests
7538
# ========================================================
@@ -116,7 +79,52 @@ def test___various_python_objects___get_best_matching_type___returns_correct_typ
11679

11780

11881
# ========================================================
119-
# Protobuf to Python
82+
# Built-in Types: Python to Protobuf
83+
# ========================================================
84+
@pytest.mark.parametrize(
85+
"proto_type, default_value, expected_value",
86+
[
87+
(wrappers_pb2.BoolValue, False, True),
88+
(wrappers_pb2.BytesValue, b"", b"mystr"),
89+
(wrappers_pb2.DoubleValue, 0.0, 456.2),
90+
(wrappers_pb2.Int64Value, 0, 123),
91+
(wrappers_pb2.StringValue, "", "mystr"),
92+
],
93+
)
94+
def test___python_builtin_scalar___to_any___valid_wrapperpb2_value(
95+
proto_type: type[_AnyWrappersPb2], default_value: Any, expected_value: Any
96+
) -> None:
97+
result = nipanel._convert.to_any(expected_value)
98+
unpack_dest = proto_type(value=default_value)
99+
_assert_any_and_unpack(result, unpack_dest)
100+
101+
assert isinstance(unpack_dest, proto_type)
102+
assert unpack_dest.value == expected_value
103+
104+
105+
@pytest.mark.parametrize(
106+
"proto_type, default_value, expected_value",
107+
[
108+
(python_panel_types_pb2.BoolCollection, [False, False, False], [True, True, True]),
109+
(python_panel_types_pb2.ByteStringCollection, [b"", b"", b""], [b"a", b"b", b"c"]),
110+
(python_panel_types_pb2.FloatCollection, [0.0, 0.0, 0.0], [1.0, 2.0, 3.0]),
111+
(python_panel_types_pb2.IntCollection, [0, 0, 0], [1, 2, 3]),
112+
(python_panel_types_pb2.StringCollection, ["", "", ""], ["a", "b", "c"]),
113+
],
114+
)
115+
def test___python_panel_collection___to_any___valid_paneltype_value(
116+
proto_type: type[_AnyPanelPbTypes], default_value: Any, expected_value: Any
117+
) -> None:
118+
result = nipanel._convert.to_any(expected_value)
119+
unpack_dest = proto_type(values=default_value)
120+
_assert_any_and_unpack(result, unpack_dest)
121+
122+
assert isinstance(unpack_dest, proto_type)
123+
assert unpack_dest.values == expected_value
124+
125+
126+
# ========================================================
127+
# Built-in Types: Protobuf to Python
120128
# ========================================================
121129
@pytest.mark.parametrize(
122130
"proto_type, expected_value",
@@ -129,7 +137,7 @@ def test___various_python_objects___get_best_matching_type___returns_correct_typ
129137
],
130138
)
131139
def test___wrapperpb2_value___from_any___valid_python_value(
132-
proto_type: Type[_AnyWrappersPb2], expected_value: Any
140+
proto_type: type[_AnyWrappersPb2], expected_value: Any
133141
) -> None:
134142
pb_value = proto_type(value=expected_value)
135143
packed_any = _pack_into_any(pb_value)
@@ -151,7 +159,7 @@ def test___wrapperpb2_value___from_any___valid_python_value(
151159
],
152160
)
153161
def test___paneltype_value___from_any___valid_python_value(
154-
proto_type: Type[_AnyPanelPbTypes], expected_value: Any
162+
proto_type: type[_AnyPanelPbTypes], expected_value: Any
155163
) -> None:
156164
pb_value = proto_type(values=expected_value)
157165
packed_any = _pack_into_any(pb_value)
@@ -162,15 +170,64 @@ def test___paneltype_value___from_any___valid_python_value(
162170
assert result == expected_value
163171

164172

173+
# ========================================================
174+
# Protobuf Types: Python to Protobuf
175+
# ========================================================
176+
def test___python_scalar_object___to_any___valid_scalar_data_value() -> None:
177+
scalar_obj = Scalar(1.0, "amps")
178+
result = nipanel._convert.to_any(scalar_obj)
179+
unpack_dest = ScalarData()
180+
_assert_any_and_unpack(result, unpack_dest)
181+
182+
assert isinstance(unpack_dest, ScalarData)
183+
assert unpack_dest.double_value == 1.0
184+
assert unpack_dest.units == "amps"
185+
186+
187+
def test___python_analog_waveform___to_any___valid_double_analog_waveform() -> None:
188+
wfm_obj = AnalogWaveform(3)
189+
result = nipanel._convert.to_any(wfm_obj)
190+
unpack_dest = DoubleAnalogWaveform()
191+
_assert_any_and_unpack(result, unpack_dest)
192+
193+
assert isinstance(unpack_dest, DoubleAnalogWaveform)
194+
assert list(unpack_dest.y_data) == [0.0, 0.0, 0.0]
195+
196+
197+
# ========================================================
198+
# Protobuf Types: Protobuf to Python
199+
# ========================================================
200+
def test___scalar_data___from_any___valid_python_scalar_object() -> None:
201+
pb_value = ScalarData(units="amps", double_value=1.0)
202+
packed_any = _pack_into_any(pb_value)
203+
204+
result = nipanel._convert.from_any(packed_any)
205+
206+
assert isinstance(result, Scalar)
207+
assert result.value == 1.0
208+
assert result.units == "amps"
209+
210+
211+
def test___double_analog_waveform___from_any___valid_python_analog_waveform() -> None:
212+
pb_value = DoubleAnalogWaveform(y_data=[0.0, 0.0, 0.0])
213+
packed_any = _pack_into_any(pb_value)
214+
215+
result = nipanel._convert.from_any(packed_any)
216+
217+
assert isinstance(result, AnalogWaveform)
218+
assert result.sample_count == result.capacity == len(result.raw_data) == 3
219+
assert result.dtype == np.float64
220+
221+
165222
# ========================================================
166223
# Pack/Unpack Helpers
167224
# ========================================================
168-
def _assert_any_and_unpack(packed_message: any_pb2.Any, unpack_destination: Any) -> None:
225+
def _assert_any_and_unpack(packed_message: any_pb2.Any, unpack_destination: Message) -> None:
169226
assert isinstance(packed_message, any_pb2.Any)
170227
assert packed_message.Unpack(unpack_destination)
171228

172229

173-
def _pack_into_any(proto_value: Union[_AnyWrappersPb2, _AnyPanelPbTypes]) -> any_pb2.Any:
230+
def _pack_into_any(proto_value: Message) -> any_pb2.Any:
174231
as_any = any_pb2.Any()
175232
as_any.Pack(proto_value)
176233
return as_any

0 commit comments

Comments
 (0)