Skip to content

Commit 1a61b7e

Browse files
author
Michael Johansen
committed
Refactor python type names to use brackets and include module names for Collection. Type name logic moved into base class.
Signed-off-by: Michael Johansen <[email protected]>
1 parent 189791b commit 1a61b7e

File tree

5 files changed

+178
-82
lines changed

5 files changed

+178
-82
lines changed

src/nipanel/_convert.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,12 @@ def _get_best_matching_type(python_value: object) -> str:
101101
value_is_collection = any(
102102
_CONVERTIBLE_COLLECTION_TYPES.intersection(underlying_parents)
103103
)
104-
container_types.append(Collection.__name__)
104+
container_types.append(Collection)
105105

106106
best_matching_type = None
107107
candidates = _get_candidate_strings(underlying_parents)
108108
for candidate in candidates:
109-
containers_str = ".".join(container_types)
110-
python_typename = f"{containers_str}.{candidate}" if containers_str else candidate
109+
python_typename = _create_python_typename(candidate, container_types)
111110
if python_typename not in _SUPPORTED_PYTHON_TYPES:
112111
continue
113112
best_matching_type = python_typename
@@ -150,3 +149,10 @@ def _get_candidate_strings(candidates: Iterable[type]) -> list[str]:
150149
candidate_names.append(f"{candidate.__module__}.{candidate.__name__}")
151150

152151
return candidate_names
152+
153+
154+
def _create_python_typename(candidate_name: str, container_types: Iterable[type]) -> str:
155+
name = candidate_name
156+
for container_type in container_types:
157+
name = f"{container_type.__module__}.{container_type.__name__}[{name}]"
158+
return name

src/nipanel/converters/__init__.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
from __future__ import annotations
44

55
from abc import ABC, abstractmethod
6+
from collections.abc import Collection
67
from typing import Generic, Type, TypeVar
78

89
from google.protobuf import any_pb2
910
from google.protobuf.message import Message
1011

12+
_TItemType = TypeVar("_TItemType")
1113
_TPythonType = TypeVar("_TPythonType")
1214
_TProtobufType = TypeVar("_TProtobufType", bound=Message)
1315

@@ -17,9 +19,14 @@ class Converter(Generic[_TPythonType, _TProtobufType], ABC):
1719

1820
@property
1921
@abstractmethod
20-
def python_typename(self) -> str:
22+
def python_type(self) -> type:
2123
"""The Python type that this converter handles."""
2224

25+
@property
26+
def python_typename(self) -> str:
27+
"""The Python type name that this converter handles."""
28+
return f"{self.python_type.__module__}.{self.python_type.__name__}"
29+
2330
@property
2431
@abstractmethod
2532
def protobuf_message(self) -> Type[_TProtobufType]:
@@ -52,3 +59,56 @@ def to_python(self, protobuf_value: any_pb2.Any) -> _TPythonType:
5259
@abstractmethod
5360
def to_python_value(self, protobuf_message: _TProtobufType) -> _TPythonType:
5461
"""Convert the protobuf wrapper message to its matching Python type."""
62+
63+
64+
class CollectionConverter(
65+
Generic[_TItemType, _TProtobufType],
66+
Converter[Collection[_TItemType], _TProtobufType],
67+
ABC,
68+
):
69+
"""A converter between a collection of Python objects and protobuf Any messages."""
70+
71+
@property
72+
@abstractmethod
73+
def item_type(self) -> type:
74+
"""The Python item type that this converter handles."""
75+
76+
@property
77+
def python_type(self) -> type:
78+
"""The Python type that this converter handles."""
79+
return Collection
80+
81+
@property
82+
def python_typename(self) -> str:
83+
"""The Python type name that this converter handles."""
84+
return "{}[{}]".format(
85+
f"{Collection.__module__}.{Collection.__name__}",
86+
f"{self.item_type.__module__}.{self.item_type.__name__}",
87+
)
88+
89+
90+
class CollectionConverter2D(
91+
Generic[_TItemType, _TProtobufType],
92+
Converter[Collection[Collection[_TItemType]], _TProtobufType],
93+
ABC,
94+
):
95+
"""A converter between a 2D collection of Python objects and protobuf Any messages."""
96+
97+
@property
98+
@abstractmethod
99+
def item_type(self) -> type:
100+
"""The Python item type that this converter handles."""
101+
102+
@property
103+
def python_type(self) -> type:
104+
"""The Python type that this converter handles."""
105+
return Collection
106+
107+
@property
108+
def python_typename(self) -> str:
109+
"""The Python type name that this converter handles."""
110+
return "{}[{}[{}]]".format(
111+
f"{Collection.__module__}.{Collection.__name__}",
112+
f"{Collection.__module__}.{Collection.__name__}",
113+
f"{self.item_type.__module__}.{self.item_type.__name__}",
114+
)

src/nipanel/converters/builtin.py

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
from google.protobuf import duration_pb2, timestamp_pb2, wrappers_pb2
88
from ni.panels.v1 import panel_types_pb2
99

10-
from nipanel.converters import Converter
10+
from nipanel.converters import Converter, CollectionConverter
1111

1212

1313
class BoolConverter(Converter[bool, wrappers_pb2.BoolValue]):
1414
"""A converter for boolean types."""
1515

1616
@property
17-
def python_typename(self) -> str:
17+
def python_type(self) -> type:
1818
"""The Python type that this converter handles."""
19-
return f"{bool.__module__}.{bool.__name__}"
19+
return bool
2020

2121
@property
2222
def protobuf_message(self) -> Type[wrappers_pb2.BoolValue]:
@@ -36,9 +36,9 @@ class BytesConverter(Converter[bytes, wrappers_pb2.BytesValue]):
3636
"""A converter for byte string types."""
3737

3838
@property
39-
def python_typename(self) -> str:
39+
def python_type(self) -> type:
4040
"""The Python type that this converter handles."""
41-
return f"{bytes.__module__}.{bytes.__name__}"
41+
return bytes
4242

4343
@property
4444
def protobuf_message(self) -> Type[wrappers_pb2.BytesValue]:
@@ -58,9 +58,9 @@ class FloatConverter(Converter[float, wrappers_pb2.DoubleValue]):
5858
"""A converter for floating point types."""
5959

6060
@property
61-
def python_typename(self) -> str:
61+
def python_type(self) -> type:
6262
"""The Python type that this converter handles."""
63-
return f"{float.__module__}.{float.__name__}"
63+
return float
6464

6565
@property
6666
def protobuf_message(self) -> Type[wrappers_pb2.DoubleValue]:
@@ -80,9 +80,9 @@ class IntConverter(Converter[int, wrappers_pb2.Int64Value]):
8080
"""A converter for integer types."""
8181

8282
@property
83-
def python_typename(self) -> str:
83+
def python_type(self) -> type:
8484
"""The Python type that this converter handles."""
85-
return f"{int.__module__}.{int.__name__}"
85+
return int
8686

8787
@property
8888
def protobuf_message(self) -> Type[wrappers_pb2.Int64Value]:
@@ -102,9 +102,9 @@ class StrConverter(Converter[str, wrappers_pb2.StringValue]):
102102
"""A converter for text string types."""
103103

104104
@property
105-
def python_typename(self) -> str:
105+
def python_type(self) -> type:
106106
"""The Python type that this converter handles."""
107-
return f"{str.__module__}.{str.__name__}"
107+
return str
108108

109109
@property
110110
def protobuf_message(self) -> Type[wrappers_pb2.StringValue]:
@@ -124,9 +124,9 @@ class DTDateTimeConverter(Converter[dt.datetime, timestamp_pb2.Timestamp]):
124124
"""A converter for datetime.datetime types."""
125125

126126
@property
127-
def python_typename(self) -> str:
127+
def python_type(self) -> type:
128128
"""The Python type that this converter handles."""
129-
return f"{dt.datetime.__module__}.{dt.datetime.__name__}"
129+
return dt.datetime
130130

131131
@property
132132
def protobuf_message(self) -> Type[timestamp_pb2.Timestamp]:
@@ -148,9 +148,9 @@ class DTTimeDeltaConverter(Converter[dt.timedelta, duration_pb2.Duration]):
148148
"""A converter for datetime.timedelta types."""
149149

150150
@property
151-
def python_typename(self) -> str:
151+
def python_type(self) -> type:
152152
"""The Python type that this converter handles."""
153-
return f"{dt.timedelta.__module__}.{dt.timedelta.__name__}"
153+
return dt.timedelta
154154

155155
@property
156156
def protobuf_message(self) -> Type[duration_pb2.Duration]:
@@ -168,13 +168,13 @@ def to_python_value(self, protobuf_message: duration_pb2.Duration) -> dt.timedel
168168
return protobuf_message.ToTimedelta()
169169

170170

171-
class BoolCollectionConverter(Converter[Collection[bool], panel_types_pb2.BoolCollection]):
171+
class BoolCollectionConverter(CollectionConverter[bool, panel_types_pb2.BoolCollection]):
172172
"""A converter for a Collection of bools."""
173173

174174
@property
175-
def python_typename(self) -> str:
175+
def item_type(self) -> type:
176176
"""The Python type that this converter handles."""
177-
return f"{Collection.__name__}.{bool.__module__}.{bool.__name__}"
177+
return bool
178178

179179
@property
180180
def protobuf_message(self) -> Type[panel_types_pb2.BoolCollection]:
@@ -190,13 +190,13 @@ def to_python_value(self, protobuf_message: panel_types_pb2.BoolCollection) -> C
190190
return list(protobuf_message.values)
191191

192192

193-
class BytesCollectionConverter(Converter[Collection[bytes], panel_types_pb2.ByteStringCollection]):
193+
class BytesCollectionConverter(CollectionConverter[bytes, panel_types_pb2.ByteStringCollection]):
194194
"""A converter for a Collection of byte strings."""
195195

196196
@property
197-
def python_typename(self) -> str:
197+
def item_type(self) -> type:
198198
"""The Python type that this converter handles."""
199-
return f"{Collection.__name__}.{bytes.__module__}.{bytes.__name__}"
199+
return bytes
200200

201201
@property
202202
def protobuf_message(self) -> Type[panel_types_pb2.ByteStringCollection]:
@@ -216,13 +216,13 @@ def to_python_value(
216216
return list(protobuf_message.values)
217217

218218

219-
class FloatCollectionConverter(Converter[Collection[float], panel_types_pb2.FloatCollection]):
219+
class FloatCollectionConverter(CollectionConverter[float, panel_types_pb2.FloatCollection]):
220220
"""A converter for a Collection of floats."""
221221

222222
@property
223-
def python_typename(self) -> str:
223+
def item_type(self) -> type:
224224
"""The Python type that this converter handles."""
225-
return f"{Collection.__name__}.{float.__module__}.{float.__name__}"
225+
return float
226226

227227
@property
228228
def protobuf_message(self) -> Type[panel_types_pb2.FloatCollection]:
@@ -242,13 +242,13 @@ def to_python_value(
242242
return list(protobuf_message.values)
243243

244244

245-
class IntCollectionConverter(Converter[Collection[int], panel_types_pb2.IntCollection]):
245+
class IntCollectionConverter(CollectionConverter[int, panel_types_pb2.IntCollection]):
246246
"""A converter for a Collection of integers."""
247247

248248
@property
249-
def python_typename(self) -> str:
249+
def item_type(self) -> type:
250250
"""The Python type that this converter handles."""
251-
return f"{Collection.__name__}.{int.__module__}.{int.__name__}"
251+
return int
252252

253253
@property
254254
def protobuf_message(self) -> Type[panel_types_pb2.IntCollection]:
@@ -264,13 +264,13 @@ def to_python_value(self, protobuf_message: panel_types_pb2.IntCollection) -> Co
264264
return list(protobuf_message.values)
265265

266266

267-
class StrCollectionConverter(Converter[Collection[str], panel_types_pb2.StringCollection]):
267+
class StrCollectionConverter(CollectionConverter[str, panel_types_pb2.StringCollection]):
268268
"""A converter for a Collection of strings."""
269269

270270
@property
271-
def python_typename(self) -> str:
271+
def item_type(self) -> type:
272272
"""The Python type that this converter handles."""
273-
return f"{Collection.__name__}.{str.__module__}.{str.__name__}"
273+
return str
274274

275275
@property
276276
def protobuf_message(self) -> Type[panel_types_pb2.StringCollection]:

src/nipanel/converters/protobuf_types.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from nitypes.waveform.typing import ExtendedPropertyValue
3232
from typing_extensions import TypeAlias
3333

34-
from nipanel.converters import Converter
34+
from nipanel.converters import Converter, CollectionConverter2D
3535

3636
_AnyScalarType: TypeAlias = Union[bool, int, float, str]
3737
_SCALAR_TYPE_TO_PB_ATTR_MAP = {
@@ -42,13 +42,13 @@
4242
}
4343

4444

45-
class Double2DArrayConverter(Converter[Collection[Collection[float]], Double2DArray]):
45+
class Double2DArrayConverter(CollectionConverter2D[float, Double2DArray]):
4646
"""A converter between Collection[Collection[float]] and Double2DArray."""
4747

4848
@property
49-
def python_typename(self) -> str:
50-
"""The Python type that this converter handles."""
51-
return f"{Collection.__name__}.{Collection.__name__}.{float.__module__}.{float.__name__}"
49+
def item_type(self) -> type:
50+
"""The Python item type that this converter handles."""
51+
return float
5252

5353
@property
5454
def protobuf_message(self) -> Type[Double2DArray]:
@@ -95,9 +95,9 @@ def __init__(self) -> None:
9595
self._pt_converter = PrecisionTimestampConverter()
9696

9797
@property
98-
def python_typename(self) -> str:
98+
def python_type(self) -> type:
9999
"""The Python type that this converter handles."""
100-
return f"{AnalogWaveform.__module__}.{AnalogWaveform.__name__}"
100+
return AnalogWaveform
101101

102102
@property
103103
def protobuf_message(self) -> Type[DoubleAnalogWaveform]:
@@ -192,9 +192,9 @@ class PrecisionTimestampConverter(Converter[bt.DateTime, PrecisionTimestamp]):
192192
"""A converter for bintime.DateTime types."""
193193

194194
@property
195-
def python_typename(self) -> str:
195+
def python_type(self) -> type:
196196
"""The Python type that this converter handles."""
197-
return f"{bt.DateTime.__module__}.{bt.DateTime.__name__}"
197+
return bt.DateTime
198198

199199
@property
200200
def protobuf_message(self) -> Type[PrecisionTimestamp]:
@@ -218,9 +218,9 @@ class ScalarConverter(Converter[Scalar[_AnyScalarType], scalar_pb2.ScalarData]):
218218
"""A converter for Scalar objects."""
219219

220220
@property
221-
def python_typename(self) -> str:
221+
def python_type(self) -> type:
222222
"""The Python type that this converter handles."""
223-
return f"{Scalar.__module__}.{Scalar.__name__}"
223+
return Scalar
224224

225225
@property
226226
def protobuf_message(self) -> Type[scalar_pb2.ScalarData]:

0 commit comments

Comments
 (0)