Skip to content

Commit f9095a0

Browse files
committed
address review comments
1 parent e35610a commit f9095a0

File tree

2 files changed

+38
-28
lines changed

2 files changed

+38
-28
lines changed

can/notifier.py

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
List,
1919
NamedTuple,
2020
Optional,
21+
Tuple,
2122
Type,
2223
Union,
2324
)
@@ -85,25 +86,25 @@ def unregister(self, bus: BusABC, notifier: "Notifier") -> None:
8586
for pair in registered_pairs_to_remove:
8687
self.pairs.remove(pair)
8788

88-
def find_instance(self, bus: BusABC) -> Optional["Notifier"]:
89-
"""Find the :class:`~can.Notifier` instance associated with a given CAN bus.
89+
def find_instances(self, bus: BusABC) -> Tuple["Notifier", ...]:
90+
"""Find the :class:`~can.Notifier` instances associated with a given CAN bus.
9091
9192
This method searches the registry for the :class:`~can.Notifier`
9293
that is linked to the specified bus. If the bus is found, the
93-
corresponding :class:`~can.Notifier` instance is returned. If the bus is not
94-
found in the registry, `None` is returned.
94+
corresponding :class:`~can.Notifier` instances are returned. If the bus is not
95+
found in the registry, an empty tuple is returned.
9596
9697
:param bus:
9798
The CAN bus for which to find the associated :class:`~can.Notifier` .
9899
:return:
99-
The :class:`~can.Notifier` instance associated with the given bus,
100-
or `None` if no such association exists.
100+
A tuple of :class:`~can.Notifier` instances associated with the given bus.
101101
"""
102+
instance_list = []
102103
with self.lock:
103104
for pair in self.pairs:
104105
if bus is pair.bus:
105-
return pair.notifier
106-
return None
106+
instance_list.append(pair.notifier)
107+
return tuple(instance_list)
107108

108109

109110
class Notifier(AbstractContextManager):
@@ -128,7 +129,7 @@ def __init__(
128129
129130
130131
:param bus:
131-
A :ref:`bus` or a list of buses to listen to.
132+
A :ref:`bus` or a list of buses to consume messages from.
132133
:param listeners:
133134
An iterable of :class:`~can.Listener` or callables that receive a :class:`~can.Message`
134135
and return nothing.
@@ -137,10 +138,10 @@ def __init__(
137138
:param loop:
138139
An :mod:`asyncio` event loop to schedule the ``listeners`` in.
139140
:raises ValueError:
140-
If the *bus* is already assigned to an active :class:`~can.Notifier`.
141+
If a passed in *bus* is already assigned to an active :class:`~can.Notifier`.
141142
"""
142143
self.listeners: List[MessageRecipient] = list(listeners)
143-
self.bus = bus
144+
self._bus_list: List[BusABC] = []
144145
self.timeout = timeout
145146
self._loop = loop
146147

@@ -151,10 +152,17 @@ def __init__(
151152
self._lock = threading.Lock()
152153

153154
self._readers: List[Union[int, threading.Thread]] = []
154-
self._bus_list = self.bus if isinstance(self.bus, list) else [self.bus]
155-
for each_bus in self._bus_list:
155+
_bus_list: List[BusABC] = bus if isinstance(bus, list) else [bus]
156+
for each_bus in _bus_list:
156157
self.add_bus(each_bus)
157158

159+
@property
160+
def bus(self) -> Union[BusABC, Tuple["BusABC", ...]]:
161+
"""Return the associated bus or a tuple of buses."""
162+
if len(self._bus_list) == 1:
163+
return self._bus_list[0]
164+
return tuple(self._bus_list)
165+
158166
def add_bus(self, bus: BusABC) -> None:
159167
"""Add a bus for notification.
160168
@@ -164,7 +172,10 @@ def add_bus(self, bus: BusABC) -> None:
164172
If the *bus* is already assigned to an active :class:`~can.Notifier`.
165173
"""
166174
# add bus to notifier registry
167-
self._registry.register(bus, self)
175+
Notifier._registry.register(bus, self)
176+
177+
# add bus to internal bus list
178+
self._bus_list.append(bus)
168179

169180
file_descriptor: int = -1
170181
try:
@@ -181,7 +192,7 @@ def add_bus(self, bus: BusABC) -> None:
181192
reader_thread = threading.Thread(
182193
target=self._rx_thread,
183194
args=(bus,),
184-
name=f'can.notifier for bus "{bus.channel_info}"',
195+
name=f'{self.__class__.__qualname__} for bus "{bus.channel_info}"',
185196
)
186197
reader_thread.daemon = True
187198
reader_thread.start()
@@ -211,7 +222,7 @@ def stop(self, timeout: float = 5.0) -> None:
211222

212223
# remove bus from registry
213224
for bus in self._bus_list:
214-
self._registry.unregister(bus, self)
225+
Notifier._registry.unregister(bus, self)
215226

216227
def _rx_thread(self, bus: BusABC) -> None:
217228
# determine message handling callable early, not inside while loop
@@ -294,22 +305,21 @@ def stopped(self) -> bool:
294305
"""Return ``True``, if Notifier was properly shut down with :meth:`~can.Notifier.stop`."""
295306
return self._stopped
296307

297-
@classmethod
298-
def find_instance(cls, bus: BusABC) -> Optional["Notifier"]:
299-
"""Find the :class:`~can.Notifier` instance associated with a given CAN bus.
308+
@staticmethod
309+
def find_instances(bus: BusABC) -> Tuple["Notifier", ...]:
310+
"""Find :class:`~can.Notifier` instances associated with a given CAN bus.
300311
301312
This method searches the registry for the :class:`~can.Notifier`
302313
that is linked to the specified bus. If the bus is found, the
303-
corresponding :class:`~can.Notifier` instance is returned. If the bus is not
304-
found in the registry, `None` is returned.
314+
corresponding :class:`~can.Notifier` instances are returned. If the bus is not
315+
found in the registry, an empty tuple is returned.
305316
306317
:param bus:
307318
The CAN bus for which to find the associated :class:`~can.Notifier` .
308319
:return:
309-
The :class:`~can.Notifier` instance associated with the given bus,
310-
or `None` if no such association exists.
320+
A tuple of :class:`~can.Notifier` instances associated with the given bus.
311321
"""
312-
return cls._registry.find_instance(bus)
322+
return Notifier._registry.find_instances(bus)
313323

314324
def __exit__(
315325
self,

test/notifier_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,18 @@ def test_registry(self):
5757
self.assertRaises(ValueError, can.Notifier, bus, [reader], 0.1)
5858

5959
# find_instance must return the existing instance
60-
self.assertIs(can.Notifier.find_instance(bus), notifier)
60+
self.assertEqual(can.Notifier.find_instances(bus), (notifier,))
6161

62-
# Notifier is stopped, find instance must return None
63-
self.assertIsNone(can.Notifier.find_instance(bus))
62+
# Notifier is stopped, find_instances() must return an empty tuple
63+
self.assertEqual(can.Notifier.find_instances(bus), ())
6464

6565
# now the first notifier is stopped, a new notifier can be created without error:
6666
with can.Notifier(bus, [reader], 0.1) as notifier:
6767
# the next notifier call should fail again since there is an active notifier already
6868
self.assertRaises(ValueError, can.Notifier, bus, [reader], 0.1)
6969

7070
# find_instance must return the existing instance
71-
self.assertIs(can.Notifier.find_instance(bus), notifier)
71+
self.assertEqual(can.Notifier.find_instances(bus), (notifier,))
7272

7373

7474
class AsyncNotifierTest(unittest.TestCase):

0 commit comments

Comments
 (0)