18
18
List ,
19
19
NamedTuple ,
20
20
Optional ,
21
+ Tuple ,
21
22
Type ,
22
23
Union ,
23
24
)
@@ -85,25 +86,25 @@ def unregister(self, bus: BusABC, notifier: "Notifier") -> None:
85
86
for pair in registered_pairs_to_remove :
86
87
self .pairs .remove (pair )
87
88
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.
90
91
91
92
This method searches the registry for the :class:`~can.Notifier`
92
93
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.
95
96
96
97
:param bus:
97
98
The CAN bus for which to find the associated :class:`~can.Notifier` .
98
99
: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.
101
101
"""
102
+ instance_list = []
102
103
with self .lock :
103
104
for pair in self .pairs :
104
105
if bus is pair .bus :
105
- return pair .notifier
106
- return None
106
+ instance_list . append ( pair .notifier )
107
+ return tuple ( instance_list )
107
108
108
109
109
110
class Notifier (AbstractContextManager ):
@@ -128,7 +129,7 @@ def __init__(
128
129
129
130
130
131
: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 .
132
133
:param listeners:
133
134
An iterable of :class:`~can.Listener` or callables that receive a :class:`~can.Message`
134
135
and return nothing.
@@ -137,10 +138,10 @@ def __init__(
137
138
:param loop:
138
139
An :mod:`asyncio` event loop to schedule the ``listeners`` in.
139
140
: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`.
141
142
"""
142
143
self .listeners : List [MessageRecipient ] = list (listeners )
143
- self .bus = bus
144
+ self ._bus_list : List [ BusABC ] = []
144
145
self .timeout = timeout
145
146
self ._loop = loop
146
147
@@ -151,10 +152,17 @@ def __init__(
151
152
self ._lock = threading .Lock ()
152
153
153
154
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 :
156
157
self .add_bus (each_bus )
157
158
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
+
158
166
def add_bus (self , bus : BusABC ) -> None :
159
167
"""Add a bus for notification.
160
168
@@ -164,7 +172,10 @@ def add_bus(self, bus: BusABC) -> None:
164
172
If the *bus* is already assigned to an active :class:`~can.Notifier`.
165
173
"""
166
174
# 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 )
168
179
169
180
file_descriptor : int = - 1
170
181
try :
@@ -181,7 +192,7 @@ def add_bus(self, bus: BusABC) -> None:
181
192
reader_thread = threading .Thread (
182
193
target = self ._rx_thread ,
183
194
args = (bus ,),
184
- name = f'can.notifier for bus "{ bus .channel_info } "' ,
195
+ name = f'{ self . __class__ . __qualname__ } for bus "{ bus .channel_info } "' ,
185
196
)
186
197
reader_thread .daemon = True
187
198
reader_thread .start ()
@@ -211,7 +222,7 @@ def stop(self, timeout: float = 5.0) -> None:
211
222
212
223
# remove bus from registry
213
224
for bus in self ._bus_list :
214
- self ._registry .unregister (bus , self )
225
+ Notifier ._registry .unregister (bus , self )
215
226
216
227
def _rx_thread (self , bus : BusABC ) -> None :
217
228
# determine message handling callable early, not inside while loop
@@ -294,22 +305,21 @@ def stopped(self) -> bool:
294
305
"""Return ``True``, if Notifier was properly shut down with :meth:`~can.Notifier.stop`."""
295
306
return self ._stopped
296
307
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.
300
311
301
312
This method searches the registry for the :class:`~can.Notifier`
302
313
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.
305
316
306
317
:param bus:
307
318
The CAN bus for which to find the associated :class:`~can.Notifier` .
308
319
: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.
311
321
"""
312
- return cls ._registry .find_instance (bus )
322
+ return Notifier ._registry .find_instances (bus )
313
323
314
324
def __exit__ (
315
325
self ,
0 commit comments