Skip to content

Commit 9c5ea4d

Browse files
committed
magicbot: Use return type hint to type feedback topics
This allows using feedbacks to create integer and integer array topics.
1 parent 59e0804 commit 9c5ea4d

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

magicbot/magic_tunable.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import functools
22
import inspect
3+
import typing
34
import warnings
45
from typing import Callable, Generic, Optional, TypeVar, overload
56

7+
import ntcore
68
from ntcore import NetworkTableInstance, Value
79
from ntcore.types import ValueT
810

@@ -222,6 +224,40 @@ class MyRobot(magicbot.MagicRobot):
222224
return f
223225

224226

227+
_topic_types = {
228+
bool: ntcore.BooleanTopic,
229+
int: ntcore.IntegerTopic,
230+
float: ntcore.DoubleTopic,
231+
str: ntcore.StringTopic,
232+
bytes: ntcore.RawTopic,
233+
}
234+
_array_topic_types = {
235+
bool: ntcore.BooleanArrayTopic,
236+
int: ntcore.IntegerArrayTopic,
237+
float: ntcore.DoubleArrayTopic,
238+
str: ntcore.StringArrayTopic,
239+
}
240+
241+
242+
def _get_topic_type(
243+
return_annotation,
244+
) -> Optional[Callable[[ntcore.Topic], typing.Any]]:
245+
if return_annotation in _topic_types:
246+
return _topic_types[return_annotation]
247+
248+
# Check for PEP 484 generic types
249+
origin = getattr(return_annotation, "__origin__", None)
250+
args = typing.get_args(return_annotation)
251+
if origin in (list, tuple) and args:
252+
# Ensure tuples are tuple[T, ...]
253+
if origin is tuple and not (len(args) == 2 and args[1] is Ellipsis):
254+
return None
255+
256+
inner_type = args[0]
257+
if inner_type in _array_topic_types:
258+
return _array_topic_types[inner_type]
259+
260+
225261
def collect_feedbacks(component, cname: str, prefix: Optional[str] = "components"):
226262
"""
227263
Finds all methods decorated with :func:`feedback` on an object
@@ -246,8 +282,19 @@ def collect_feedbacks(component, cname: str, prefix: Optional[str] = "components
246282
else:
247283
key = name
248284

249-
entry = nt.getEntry(key)
250-
setter = entry.setValue
285+
return_annotation = typing.get_type_hints(method).get("return", None)
286+
if return_annotation is not None:
287+
topic_type = _get_topic_type(return_annotation)
288+
else:
289+
topic_type = None
290+
291+
if topic_type is None:
292+
entry = nt.getEntry(key)
293+
setter = entry.setValue
294+
else:
295+
publisher = topic_type(nt.getTopic(key)).publish()
296+
setter = publisher.set
297+
251298
feedbacks.append((method, setter))
252299

253300
return feedbacks

0 commit comments

Comments
 (0)