summaryrefslogtreecommitdiff
path: root/urwid
diff options
context:
space:
mode:
authorAndrew Dunai <andunai@gmail.com>2018-01-07 02:31:03 +0200
committerGitHub <noreply@github.com>2018-01-07 02:31:03 +0200
commit1704e374ba55e6fdfe8d68870bd1781ce8afedcd (patch)
treec415bbc54580a315eeb6241eedba6bc60ed76735 /urwid
parent9c3d68da020b028a55d38b1061db8aacae74ba89 (diff)
parent626deb940841f57d331e5a9d2f023f3461c97cb7 (diff)
downloadurwid-1704e374ba55e6fdfe8d68870bd1781ce8afedcd.tar.gz
Merge pull request #270 from federicotdn/master
Allow Screen class to set signal handlers using a function provided by the event loop
Diffstat (limited to 'urwid')
-rwxr-xr-xurwid/main_loop.py65
-rw-r--r--urwid/raw_display.py21
2 files changed, 80 insertions, 6 deletions
diff --git a/urwid/main_loop.py b/urwid/main_loop.py
index 442c27d..3d18c52 100755
--- a/urwid/main_loop.py
+++ b/urwid/main_loop.py
@@ -27,6 +27,7 @@ import time
import heapq
import select
import os
+import signal
from functools import wraps
from itertools import count
from weakref import WeakKeyDictionary
@@ -129,6 +130,11 @@ class MainLoop(object):
event_loop = SelectEventLoop()
self.event_loop = event_loop
+ if hasattr(self.screen, 'signal_handler_setter'):
+ # Tell the screen what function it must use to set
+ # signal handlers
+ self.screen.signal_handler_setter = self.event_loop.set_signal_handler
+
self._watch_pipes = {}
def _set_widget(self, widget):
@@ -645,6 +651,12 @@ class SelectEventLoop(object):
return True
return False
+ def set_signal_handler(self, signum, handler):
+ """
+ Proxy function to signal.signal()
+ """
+ return signal.signal(signum, handler)
+
def enter_idle(self, callback):
"""
Add a callback for entering idle.
@@ -740,6 +752,7 @@ class GLibEventLoop(object):
self._loop = GLib.MainLoop()
self._exc_info = None
self._enable_glib_idle()
+ self._signal_handlers = {}
def alarm(self, seconds, callback):
"""
@@ -760,6 +773,40 @@ class GLibEventLoop(object):
self._alarms.append(fd)
return (fd, callback)
+ def set_signal_handler(self, signum, handler):
+ """
+ Sets a handler for a specified signal. This method's behaviour
+ method tries to imitate the signal() function from the signal
+ module.
+ """
+ glib_signals = [
+ signal.SIGHUP,
+ signal.SIGINT,
+ signal.SIGTERM,
+ signal.SIGUSR1,
+ signal.SIGUSR2,
+ signal.SIGWINCH
+ ]
+
+ if signum not in glib_signals:
+ # The GLib event loop supports only the signals listed above
+ return
+
+ if signum in self._signal_handlers:
+ self.GLib.source_remove(self._signal_handlers.pop(signum))
+
+ if handler == signal.SIG_IGN:
+ handler = lambda x: None
+ elif handler == signal.SIG_DFL:
+ return
+
+ def final_handler(signal_number):
+ handler(signal_number)
+ return self.GLib.SOURCE_CONTINUE
+
+ source = self.GLib.unix_signal_add(self.GLib.PRIORITY_DEFAULT, signum, final_handler, signum)
+ self._signal_handlers[signum] = source
+
def remove_alarm(self, handle):
"""
Remove an alarm.
@@ -987,6 +1034,12 @@ class TornadoEventLoop(object):
self._ioloop.remove_handler(fd)
return True
+ def set_signal_handler(self, signum, handler):
+ """
+ Proxy function to signal.signal()
+ """
+ return signal.signal(signum, handler)
+
def enter_idle(self, callback):
self._max_idle_handle += 1
handle = self._max_idle_handle
@@ -1132,6 +1185,12 @@ class TwistedEventLoop(object):
return True
return False
+ def set_signal_handler(self, signum, handler):
+ """
+ Proxy function to signal.signal()
+ """
+ return signal.signal(signum, handler)
+
def enter_idle(self, callback):
"""
Add a callback for entering idle.
@@ -1279,6 +1338,12 @@ class AsyncioEventLoop(object):
"""
return self._loop.remove_reader(handle)
+ def set_signal_handler(self, signum, handler):
+ """
+ Proxy function to signal.signal()
+ """
+ return signal.signal(signum, handler)
+
def enter_idle(self, callback):
"""
Add a callback for entering idle.
diff --git a/urwid/raw_display.py b/urwid/raw_display.py
index 365e311..626891d 100644
--- a/urwid/raw_display.py
+++ b/urwid/raw_display.py
@@ -81,6 +81,7 @@ class Screen(BaseScreen, RealTerminal):
self.back_color_erase = not self.term.startswith("screen")
self.register_palette_entry( None, 'default','default')
self._next_timeout = None
+ self.signal_handler_setter = signal.signal
# Our connections to the world
self._term_output_file = output
@@ -121,13 +122,21 @@ class Screen(BaseScreen, RealTerminal):
self.complete_wait = complete_wait
self.resize_wait = resize_wait
- def _sigwinch_handler(self, signum, frame):
+ def _sigwinch_handler(self, signum, frame=None):
+ """
+ frame -- will always be None when the GLib event loop is being used.
+ """
+
if not self._resized:
os.write(self._resize_pipe_wr, B('R'))
self._resized = True
self.screen_buf = None
- def _sigcont_handler(self, signum, frame):
+ def _sigcont_handler(self, signum, frame=None):
+ """
+ frame -- will always be None when the GLib event loop is being used.
+ """
+
self.stop()
self.start()
self._sigwinch_handler(None, None)
@@ -140,8 +149,8 @@ class Screen(BaseScreen, RealTerminal):
Override this function to call from main thread in threaded
applications.
"""
- signal.signal(signal.SIGWINCH, self._sigwinch_handler)
- signal.signal(signal.SIGCONT, self._sigcont_handler)
+ self.signal_handler_setter(signal.SIGWINCH, self._sigwinch_handler)
+ self.signal_handler_setter(signal.SIGCONT, self._sigcont_handler)
def signal_restore(self):
"""
@@ -151,8 +160,8 @@ class Screen(BaseScreen, RealTerminal):
Override this function to call from main thread in threaded
applications.
"""
- signal.signal(signal.SIGCONT, signal.SIG_DFL)
- signal.signal(signal.SIGWINCH, signal.SIG_DFL)
+ self.signal_handler_setter(signal.SIGCONT, signal.SIG_DFL)
+ self.signal_handler_setter(signal.SIGWINCH, signal.SIG_DFL)
def set_mouse_tracking(self, enable=True):
"""