summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/ext/signals.py103
1 files changed, 103 insertions, 0 deletions
diff --git a/ranger/ext/signals.py b/ranger/ext/signals.py
new file mode 100644
index 00000000..3f407bff
--- /dev/null
+++ b/ranger/ext/signals.py
@@ -0,0 +1,103 @@
+# Copyright (C) 2009, 2010  Roman Zimbelmann <romanz@lavabit.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import weakref
+from types import MethodType
+
+class Signal(dict):
+	stopped = False
+	def __init__(self, **keywords):
+		dict.__init__(self, keywords)
+		self.__dict__ = self
+
+	def stop(self):
+		self.stopped = True
+
+
+class SignalHandler(object):
+	active = True
+	def __init__(self, signal_name, function, priority, pass_signal):
+		self.priority = max(0, min(1, priority))
+		self.signal_name = signal_name
+		self.function = function
+		self.pass_signal = pass_signal
+
+
+class SignalDispatcher(object):
+	def __init__(self):
+		self._signals = dict()
+
+	signal_clear = __init__
+
+	def signal_bind(self, signal_name, function, priority=0.5, weak=False):
+		assert isinstance(signal_name, str)
+		try:
+			handlers = self._signals[signal_name]
+		except:
+			handlers = self._signals[signal_name] = []
+		nargs = function.__code__.co_argcount
+
+		try:
+			instance = function.__self__
+		except:
+			if weak:
+				function = weakref.proxy(function)
+		else:
+			nargs -= 1
+			if weak:
+				function = (function.__func__, weakref.proxy(function.__self__))
+		handler = SignalHandler(signal_name, function, priority, nargs > 0)
+		handlers.append(handler)
+		handlers.sort(key=lambda handler: -handler.priority)
+		return handler
+
+	def signal_unbind(self, signal_handler):
+		try:
+			handlers = self._signals[signal_handler.signal_name]
+		except:
+			pass
+		else:
+			try:
+				handlers.remove(signal_handler)
+			except:
+				pass
+
+	def signal_emit(self, signal_name, **kw):
+		assert isinstance(signal_name, str)
+		if signal_name not in self._signals:
+			return True
+		handlers = self._signals[signal_name]
+		if not handlers:
+			return True
+
+		signal = Signal(origin=self, name=signal_name, **kw)
+
+		# propagate
+		for handler in tuple(handlers):
+			if handler.active:
+				try:
+					if isinstance(handler.function, tuple):
+						fnc = MethodType(*handler.function)
+					else:
+						fnc = handler.function
+					if handler.pass_signal:
+						fnc(signal)
+					else:
+						fnc()
+					if signal.stopped:
+						return False
+				except ReferenceError:
+					handlers.remove(handler)
+		return True