Skip to content

Commit 9db2b27

Browse files
authored
can.Notifier enhancements (#266)
* prepended an underscore to private fields/methdos of can.Notifier * added add_listener and remove_listener to can.Notifier. closes #265 * added tests for can.Notifier.add_listener() and remove_listener() * added tests for can.Notifier.add_listener() and remove_listener() * fix an import problem that was cuased by pervious merge * attempt fixing Sqlite tests
1 parent 1051f1e commit 9db2b27

File tree

4 files changed

+52
-10
lines changed

4 files changed

+52
-10
lines changed

can/notifier.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# coding: utf-8
33

44
"""
5-
This module contains the implementation of `can.Notifier`.
5+
This module contains the implementation of :class:`~can.Notifier`.
66
"""
77

88
import threading
@@ -18,7 +18,7 @@ def __init__(self, bus, listeners, timeout=None):
1818
list of listeners.
1919
2020
:param bus: The :ref:`bus` to listen too.
21-
:param listeners: An iterable of :class:`~can.Listeners`
21+
:param listeners: An iterable of :class:`~can.Listener`s
2222
:param timeout: An optional maximum number of seconds to wait for any message.
2323
"""
2424
self.listeners = listeners
@@ -28,23 +28,25 @@ def __init__(self, bus, listeners, timeout=None):
2828
# exception raised in thread
2929
self.exception = None
3030

31-
self.running = threading.Event()
32-
self.running.set()
31+
self._running = threading.Event()
32+
self._running.set()
3333

34-
self._reader = threading.Thread(target=self.rx_thread, name="can.notifier")
34+
self._reader = threading.Thread(target=self._rx_thread,
35+
name='can.notifier for bus "{}"'.format(self.bus.channel_info))
3536
self._reader.daemon = True
3637
self._reader.start()
3738

3839
def stop(self):
3940
"""Stop notifying Listeners when new :class:`~can.Message` objects arrive
40-
and call :meth:`~can.Listener.stop` on each Listener."""
41-
self.running.clear()
41+
and call :meth:`~can.Listener.stop` on each Listener.
42+
"""
43+
self._running.clear()
4244
if self.timeout is not None:
4345
self._reader.join(self.timeout + 0.1)
4446

45-
def rx_thread(self):
47+
def _rx_thread(self):
4648
try:
47-
while self.running.is_set():
49+
while self._running.is_set():
4850
msg = self.bus.recv(self.timeout)
4951
if msg is not None:
5052
for callback in self.listeners:
@@ -55,3 +57,24 @@ def rx_thread(self):
5557
finally:
5658
for listener in self.listeners:
5759
listener.stop()
60+
61+
def add_listener(self, listener):
62+
"""Add new Listener to the notification list.
63+
If it is already present, it will be called two times
64+
each time a message arrives.
65+
66+
:param listener: a :class:`~can.Listener` object to be added to
67+
the list to be notified
68+
"""
69+
self.listeners.append(listener)
70+
71+
def remove_listener(self, listener):
72+
"""Remove a listener from the notification list. This method
73+
trows an exception if the given listener is not part of the
74+
stored listeners.
75+
76+
:param listener: a :class:`~can.Listener` object to be removed from
77+
the list to be notified
78+
:raises ValueError: if `listener` was never added to this notifier
79+
"""
80+
self.listeners.remove(listener)

test/back2back_test.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313

1414
import can
1515

16+
from .data.example_data import generate_message
17+
1618
from .config import *
1719
from .data.example_data import generate_message
1820

21+
1922
BITRATE = 500000
2023
TIMEOUT = 0.1
2124

test/listener_test.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ def testBasicListenerCanBeAddedToNotifier(self):
7373
notifier = can.Notifier(self.bus, [a_listener], 0.1)
7474
notifier.stop()
7575
self.assertIn(a_listener, notifier.listeners)
76+
77+
def testAddListenerToNotifier(self):
78+
a_listener = can.Listener()
79+
notifier = can.Notifier(self.bus, [], 0.1)
80+
notifier.stop()
81+
self.assertNotIn(a_listener, notifier.listeners)
82+
notifier.add_listener(a_listener)
83+
self.assertIn(a_listener, notifier.listeners)
84+
85+
def testRemoveListenerFromNotifier(self):
86+
a_listener = can.Listener()
87+
notifier = can.Notifier(self.bus, [a_listener], 0.1)
88+
notifier.stop()
89+
self.assertIn(a_listener, notifier.listeners)
90+
notifier.remove_listener(a_listener)
91+
self.assertNotIn(a_listener, notifier.listeners)
7692

7793
def testPlayerTypeResolution(self):
7894
def test_filetype_to_instance(extension, klass):

test/logformats_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ class TestSqliteDatabaseFormat(unittest.TestCase):
166166

167167
def test_writer_and_reader(self):
168168
_test_writer_and_reader(self, can.SqliteWriter, can.SqliteReader,
169-
sleep_time=can.SqliteWriter.MAX_TIME_BETWEEN_WRITES,
169+
sleep_time=can.SqliteWriter.MAX_TIME_BETWEEN_WRITES + 0.5,
170170
check_comments=False)
171171

172172
def testSQLWriterWritesToSameFile(self):

0 commit comments

Comments
 (0)