[Pkg-bitcoin-commits] [python-quamash] 64/78: Change how event loop base classes are assigned.

Jonas Smedegaard dr at jones.dk
Tue Dec 19 01:19:56 UTC 2017


This is an automated email from the git hooks/post-receive script.

js pushed a commit to annotated tag debian/0.6.0_dfsg-1
in repository python-quamash.

commit 6517f5a9c6633476b8c4b74049a1f83d7ecacf4c
Author: Mark Harviston <Mark.T.Harviston.-ND at disney.com>
Date:   Thu Jan 14 12:36:20 2016 -0800

    Change how event loop base classes are assigned.
    
    This lets you use the SelectorEventLoop on windows.
---
 quamash/__init__.py |  50 +++---
 quamash/_unix.py    | 441 ++++++++++++++++++++++++++--------------------------
 quamash/_windows.py |   3 -
 3 files changed, 249 insertions(+), 245 deletions(-)

diff --git a/quamash/__init__.py b/quamash/__init__.py
index 94acfac..cb4220c 100644
--- a/quamash/__init__.py
+++ b/quamash/__init__.py
@@ -171,14 +171,6 @@ def _make_signaller(qtimpl_qtcore, *args):
 	return Signaller()
 
 
-if os.name == 'nt':
-	from . import _windows
-	_baseclass = _windows.baseclass
-else:
-	from . import _unix
-	_baseclass = _unix.baseclass
-
-
 class _SimpleTimer(QtCore.QObject):
 	def __init__(self, timeout, callback):
 		super().__init__()
@@ -307,8 +299,9 @@ class QEventLoop(_baseclass):
 		super().close()
 
 		for timer in self.__timers:
-			timer.stop()
-
+			if timer.isActive():
+				timer.stop()
+			del timer
 		self.__timers = None
 
 		self.__app = None
@@ -335,20 +328,21 @@ class QEventLoop(_baseclass):
 		def upon_timeout():
 			nonlocal timer
 			nonlocal handle
-			if timer in self.__timers:
-				self.__timers.remove(timer)
-			else:
-				self._logger.warn('Timer {} not among {}'.format(timer, self.__timers))
+			assert timer in self.__timers, 'Timer {} not among {}'.format(timer, self.__timers)
+			self.__timers.remove(timer)
 			timer = None
 			self._logger.debug('Callback timer fired, calling {}'.format(handle))
 			handle._run()
 			handle = None
 
 		self._logger.debug('Adding callback {} with delay {}'.format(handle, delay))
-		timer = _SimpleTimer(delay * 1000, upon_timeout)
+		timer = QtCore.QTimer(self.__app)
+		timer.timeout.connect(upon_timeout)
+		timer.setSingleShot(True)
+		timer.start(delay * 1000)
 		self.__timers.append(timer)
 
-		return timer
+		return _Cancellable(timer, self)
 
 	def call_soon(self, callback, *args):
 		"""Register a callback to be run on the next iteration of the event loop."""
@@ -510,9 +504,7 @@ class QEventLoop(_baseclass):
 		self.__exception_handler = handler
 
 	def default_exception_handler(self, context):
-		"""Handle exceptions.
-
-		This is the default exception handler.
+		"""Default exception handler.
 
 		This is called when an exception occurs and no exception
 		handler is set, and can be called by a custom exception
@@ -592,3 +584,23 @@ class QEventLoop(_baseclass):
 			cls._logger.error(*args, **kwds)
 		except:
 			sys.stderr.write('{!r}, {!r}\n'.format(args, kwds))
+
+from .unix import _SelectorEventLoop
+class QSelectorEventLoop(_QEventLoop, _SelectorEventLoop):
+	pass
+
+if os.name == 'nt':
+	from ._windows import _ProactorEventLoop
+	class QIOCPEventLoop(_QEventLoop, _ProactorEventLoop):
+		pass
+	QEventLoop = QIOCPEventLoop
+else:
+	QEventLoop = QSelectorEventLoop
+
+class _Cancellable:
+	def __init__(self, timer, loop):
+		self.__timer = timer
+		self.__loop = loop
+
+	def cancel(self):
+		self.__timer.stop()
diff --git a/quamash/_unix.py b/quamash/_unix.py
index b471899..913cd44 100644
--- a/quamash/_unix.py
+++ b/quamash/_unix.py
@@ -1,223 +1,218 @@
-# © 2014 Mark Harviston <mark.harviston at gmail.com>
-# © 2014 Arve Knudsen <arve.knudsen at gmail.com>
-# BSD License
-
-"""UNIX specific Quamash functionality."""
-
-import asyncio
-from asyncio import selectors
-import collections
-
-from . import QtCore, with_logger
-
-
-EVENT_READ = (1 << 0)
-EVENT_WRITE = (1 << 1)
-
-
-def _fileobj_to_fd(fileobj):
-	"""
-	Return a file descriptor from a file object.
-
-	Parameters:
-	fileobj -- file object or file descriptor
-
-	Returns:
-	corresponding file descriptor
-
-	Raises:
-	ValueError if the object is invalid
-
-	"""
-	if isinstance(fileobj, int):
-		fd = fileobj
-	else:
-		try:
-			fd = int(fileobj.fileno())
-		except (AttributeError, TypeError, ValueError) as ex:
-			raise ValueError("Invalid file object: {!r}".format(fileobj)) from ex
-	if fd < 0:
-		raise ValueError("Invalid file descriptor: {}".format(fd))
-	return fd
-
-
-class _SelectorMapping(collections.Mapping):
-
-	"""Mapping of file objects to selector keys."""
-
-	def __init__(self, selector):
-		self._selector = selector
-
-	def __len__(self):
-		return len(self._selector._fd_to_key)
-
-	def __getitem__(self, fileobj):
-		try:
-			fd = self._selector._fileobj_lookup(fileobj)
-			return self._selector._fd_to_key[fd]
-		except KeyError:
-			raise KeyError("{!r} is not registered".format(fileobj)) from None
-
-	def __iter__(self):
-		return iter(self._selector._fd_to_key)
-
-
- at with_logger
-class _Selector(selectors.BaseSelector):
-	def __init__(self, parent):
-		# this maps file descriptors to keys
-		self._fd_to_key = {}
-		# read-only mapping returned by get_map()
-		self.__map = _SelectorMapping(self)
-		self.__read_notifiers = {}
-		self.__write_notifiers = {}
-		self.__parent = parent
-
-	def select(self, *args, **kwargs):
-		"""Implement abstract method even though we don't need it."""
-		raise NotImplementedError
-
-	def _fileobj_lookup(self, fileobj):
-		"""Return a file descriptor from a file object.
-
-		This wraps _fileobj_to_fd() to do an exhaustive search in case
-		the object is invalid but we still have it in our map.  This
-		is used by unregister() so we can unregister an object that
-		was previously registered even if it is closed.  It is also
-		used by _SelectorMapping.
-		"""
-		try:
-			return _fileobj_to_fd(fileobj)
-		except ValueError:
-			# Do an exhaustive search.
-			for key in self._fd_to_key.values():
-				if key.fileobj is fileobj:
-					return key.fd
-			# Raise ValueError after all.
-			raise
-
-	def register(self, fileobj, events, data=None):
-		if (not events) or (events & ~(EVENT_READ | EVENT_WRITE)):
-			raise ValueError("Invalid events: {!r}".format(events))
-
-		key = selectors.SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
-
-		if key.fd in self._fd_to_key:
-			raise KeyError("{!r} (FD {}) is already registered".format(fileobj, key.fd))
-
-		self._fd_to_key[key.fd] = key
-
-		if events & EVENT_READ:
-			notifier = QtCore.QSocketNotifier(key.fd, QtCore.QSocketNotifier.Read)
-			notifier.activated.connect(self.__on_read_activated)
-			self.__read_notifiers[key.fd] = notifier
-		if events & EVENT_WRITE:
-			notifier = QtCore.QSocketNotifier(key.fd, QtCore.QSocketNotifier.Write)
-			notifier.activated.connect(self.__on_write_activated)
-			self.__write_notifiers[key.fd] = notifier
-
-		return key
-
-	def __on_read_activated(self, fd):
-		self._logger.debug('File {} ready to read'.format(fd))
-		key = self._key_from_fd(fd)
-		if key:
-			self.__parent._process_event(key, EVENT_READ & key.events)
-
-	def __on_write_activated(self, fd):
-		self._logger.debug('File {} ready to write'.format(fd))
-		key = self._key_from_fd(fd)
-		if key:
-			self.__parent._process_event(key, EVENT_WRITE & key.events)
-
-	def unregister(self, fileobj):
-		def drop_notifier(notifiers):
-			try:
-				notifier = notifiers.pop(key.fd)
-			except KeyError:
-				pass
-			else:
-				notifier.activated.disconnect()
-
-		try:
-			key = self._fd_to_key.pop(self._fileobj_lookup(fileobj))
-		except KeyError:
-			raise KeyError("{!r} is not registered".format(fileobj)) from None
-
-		drop_notifier(self.__read_notifiers)
-		drop_notifier(self.__write_notifiers)
-
-		return key
-
-	def modify(self, fileobj, events, data=None):
-		try:
-			key = self._fd_to_key[self._fileobj_lookup(fileobj)]
-		except KeyError:
-			raise KeyError("{!r} is not registered".format(fileobj)) from None
-		if events != key.events:
-			self.unregister(fileobj)
-			key = self.register(fileobj, events, data)
-		elif data != key.data:
-			# Use a shortcut to update the data.
-			key = key._replace(data=data)
-			self._fd_to_key[key.fd] = key
-		return key
-
-	def close(self):
-		self._logger.debug('Closing')
-		self._fd_to_key.clear()
-		self.__read_notifiers.clear()
-		self.__write_notifiers.clear()
-
-	def get_map(self):
-		return self.__map
-
-	def _key_from_fd(self, fd):
-		"""
-		Return the key associated to a given file descriptor.
-
-		Parameters:
-		fd -- file descriptor
-
-		Returns:
-		corresponding key, or None if not found
-
-		"""
-		try:
-			return self._fd_to_key[fd]
-		except KeyError:
-			return None
-
-
-class _SelectorEventLoop(asyncio.SelectorEventLoop):
-	def __init__(self):
-		self._signal_safe_callbacks = []
-
-		selector = _Selector(self)
-		asyncio.SelectorEventLoop.__init__(self, selector)
-
-	def _before_run_forever(self):
-		pass
-
-	def _after_run_forever(self):
-		pass
-
-	def _process_event(self, key, mask):
-		"""Selector has delivered us an event."""
-		self._logger.debug('Processing event with key {} and mask {}'.format(key, mask))
-		fileobj, (reader, writer) = key.fileobj, key.data
-		if mask & selectors.EVENT_READ and reader is not None:
-			if reader._cancelled:
-				self.remove_reader(fileobj)
-			else:
-				self._logger.debug('Invoking reader callback: {}'.format(reader))
-				reader._run()
-		if mask & selectors.EVENT_WRITE and writer is not None:
-			if writer._cancelled:
-				self.remove_writer(fileobj)
-			else:
-				self._logger.debug('Invoking writer callback: {}'.format(writer))
-				writer._run()
-
-
-baseclass = _SelectorEventLoop
+# © 2014 Mark Harviston <mark.harviston at gmail.com>
+# © 2014 Arve Knudsen <arve.knudsen at gmail.com>
+# BSD License
+
+"""UNIX specific Quamash functionality."""
+
+import asyncio
+from asyncio import selectors
+import collections
+
+from . import QtCore, with_logger
+
+
+EVENT_READ = (1 << 0)
+EVENT_WRITE = (1 << 1)
+
+
+def _fileobj_to_fd(fileobj):
+	"""
+	Return a file descriptor from a file object.
+
+	Parameters:
+	fileobj -- file object or file descriptor
+
+	Returns:
+	corresponding file descriptor
+
+	Raises:
+	ValueError if the object is invalid
+	"""
+	if isinstance(fileobj, int):
+		fd = fileobj
+	else:
+		try:
+			fd = int(fileobj.fileno())
+		except (AttributeError, TypeError, ValueError) as ex:
+			raise ValueError("Invalid file object: {!r}".format(fileobj)) from ex
+	if fd < 0:
+		raise ValueError("Invalid file descriptor: {}".format(fd))
+	return fd
+
+
+class _SelectorMapping(collections.Mapping):
+
+	"""Mapping of file objects to selector keys."""
+
+	def __init__(self, selector):
+		self._selector = selector
+
+	def __len__(self):
+		return len(self._selector._fd_to_key)
+
+	def __getitem__(self, fileobj):
+		try:
+			fd = self._selector._fileobj_lookup(fileobj)
+			return self._selector._fd_to_key[fd]
+		except KeyError:
+			raise KeyError("{!r} is not registered".format(fileobj)) from None
+
+	def __iter__(self):
+		return iter(self._selector._fd_to_key)
+
+
+ at with_logger
+class _Selector(selectors.BaseSelector):
+	def __init__(self, parent):
+		# this maps file descriptors to keys
+		self._fd_to_key = {}
+		# read-only mapping returned by get_map()
+		self.__map = _SelectorMapping(self)
+		self.__read_notifiers = {}
+		self.__write_notifiers = {}
+		self.__parent = parent
+
+	def select(self, *args, **kwargs):
+		"""Implement abstract method even though we don't need it."""
+		raise NotImplementedError
+
+	def _fileobj_lookup(self, fileobj):
+		"""Return a file descriptor from a file object.
+
+		This wraps _fileobj_to_fd() to do an exhaustive search in case
+		the object is invalid but we still have it in our map.  This
+		is used by unregister() so we can unregister an object that
+		was previously registered even if it is closed.  It is also
+		used by _SelectorMapping.
+		"""
+		try:
+			return _fileobj_to_fd(fileobj)
+		except ValueError:
+			# Do an exhaustive search.
+			for key in self._fd_to_key.values():
+				if key.fileobj is fileobj:
+					return key.fd
+			# Raise ValueError after all.
+			raise
+
+	def register(self, fileobj, events, data=None):
+		if (not events) or (events & ~(EVENT_READ | EVENT_WRITE)):
+			raise ValueError("Invalid events: {!r}".format(events))
+
+		key = selectors.SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
+
+		if key.fd in self._fd_to_key:
+			raise KeyError("{!r} (FD {}) is already registered".format(fileobj, key.fd))
+
+		self._fd_to_key[key.fd] = key
+
+		if events & EVENT_READ:
+			notifier = QtCore.QSocketNotifier(key.fd, QtCore.QSocketNotifier.Read)
+			notifier.activated.connect(self.__on_read_activated)
+			self.__read_notifiers[key.fd] = notifier
+		if events & EVENT_WRITE:
+			notifier = QtCore.QSocketNotifier(key.fd, QtCore.QSocketNotifier.Write)
+			notifier.activated.connect(self.__on_write_activated)
+			self.__write_notifiers[key.fd] = notifier
+
+		return key
+
+	def __on_read_activated(self, fd):
+		self._logger.debug('File {} ready to read'.format(fd))
+		key = self._key_from_fd(fd)
+		if key:
+			self.__parent._process_event(key, EVENT_READ & key.events)
+
+	def __on_write_activated(self, fd):
+		self._logger.debug('File {} ready to write'.format(fd))
+		key = self._key_from_fd(fd)
+		if key:
+			self.__parent._process_event(key, EVENT_WRITE & key.events)
+
+	def unregister(self, fileobj):
+		def drop_notifier(notifiers):
+			try:
+				notifier = notifiers.pop(key.fd)
+			except KeyError:
+				pass
+			else:
+				notifier.activated.disconnect()
+
+		try:
+			key = self._fd_to_key.pop(self._fileobj_lookup(fileobj))
+		except KeyError:
+			raise KeyError("{!r} is not registered".format(fileobj)) from None
+
+		drop_notifier(self.__read_notifiers)
+		drop_notifier(self.__write_notifiers)
+
+		return key
+
+	def modify(self, fileobj, events, data=None):
+		try:
+			key = self._fd_to_key[self._fileobj_lookup(fileobj)]
+		except KeyError:
+			raise KeyError("{!r} is not registered".format(fileobj)) from None
+		if events != key.events:
+			self.unregister(fileobj)
+			key = self.register(fileobj, events, data)
+		elif data != key.data:
+			# Use a shortcut to update the data.
+			key = key._replace(data=data)
+			self._fd_to_key[key.fd] = key
+		return key
+
+	def close(self):
+		self._logger.debug('Closing')
+		self._fd_to_key.clear()
+		self.__read_notifiers.clear()
+		self.__write_notifiers.clear()
+
+	def get_map(self):
+		return self.__map
+
+	def _key_from_fd(self, fd):
+		"""
+		Return the key associated to a given file descriptor.
+
+		Parameters:
+		fd -- file descriptor
+
+		Returns:
+		corresponding key, or None if not found
+		"""
+		try:
+			return self._fd_to_key[fd]
+		except KeyError:
+			return None
+
+
+class _SelectorEventLoop(asyncio.SelectorEventLoop):
+	def __init__(self):
+		self._signal_safe_callbacks = []
+
+		selector = _Selector(self)
+		asyncio.SelectorEventLoop.__init__(self, selector)
+
+	def _before_run_forever(self):
+		pass
+
+	def _after_run_forever(self):
+		pass
+
+	def _process_event(self, key, mask):
+		"""Selector has delivered us an event."""
+		self._logger.debug('Processing event with key {} and mask {}'.format(key, mask))
+		fileobj, (reader, writer) = key.fileobj, key.data
+		if mask & selectors.EVENT_READ and reader is not None:
+			if reader._cancelled:
+				self.remove_reader(fileobj)
+			else:
+				self._logger.debug('Invoking reader callback: {}'.format(reader))
+				reader._run()
+		if mask & selectors.EVENT_WRITE and writer is not None:
+			if writer._cancelled:
+				self.remove_writer(fileobj)
+			else:
+				self._logger.debug('Invoking writer callback: {}'.format(writer))
+				writer._run()

diff --git a/quamash/_windows.py b/quamash/_windows.py
index fb586ef..a474161 100644
--- a/quamash/_windows.py
+++ b/quamash/_windows.py
@@ -52,9 +52,6 @@ class _ProactorEventLoop(asyncio.ProactorEventLoop):
 		self.__event_poller.stop()
 
 
-baseclass = _ProactorEventLoop
-
-
 @with_logger
 class _IocpProactor(windows_events.IocpProactor):
 	def __init__(self):

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-bitcoin/python-quamash.git



More information about the Pkg-bitcoin-commits mailing list