Source code for spinnman.connections.listeners.scp_listener

import inspect
from threading import Thread

from spinnman.connections.listeners._callback_queue import _CallbackQueue
from spinnman.exceptions import SpinnmanInvalidParameterException


def _function_has_free_argument_count(func, count):
    """ Determines if a function has a given free argument count (such that the
        function can be called with the given number of arguments)

    :param func: The function to determine the free argument count of
    :type func: callable
    :param count: The amount of free arguments to check for
    :type count: int
    :return: True if func has count free arguments, false otherwise
    :rtype: bool
    """
    (args, varargs, keywords, defaults) = inspect.getargspec(func)

    # If the function has count args, it is fine
    if len(args) == count:
        return True

    # If the function has count args once the defaults are assigned, it is fine
    if defaults and len(args) - len(defaults) == count:
        return True

    # Otherwise, if the function has a "varargs" or "keywords", it is fine
    if varargs is not None or keywords is not None:
        return True

    # Otherwise it must not match
    return False


[docs]class SCPListener(Thread): """ Listens for SCP packets received from a connection,\ calling a callback function with received packets """ def __init__(self, scp_receiver, response_class, callback, error_callback=None): """ :param scp_receiver: The SCP Receiver to receive packets from :type scp_receiver:\ :py:class:`spinnman.connections.abstract_scp_receiver.AbstractSCPReceiver` :param response_class: The SCP response :type response_class: class of implementation of\ :py:class:`spinnman.messages.scp.abstract_scp_response.AbstractSCPResponse` :param callback: The callback function to call on reception of each\ packet; the function should take one parameter, which is\ the SCP packet received :type callback: function(\ :py:class:`spinnman.messages.scp.abstract_scp_response.AbstractSCPResponse`) :param error_callback: The callback function to call if there is an\ error receiving a packet; the function should take two\ parameters: * The exception received * A message indicating what the problem was :type error_callback: function(Exception, str) :raise spinnman.exceptions.SpinnmanInvalidParameterException: If\ the callback or the error_callback do not take the\ expected number of arguments """ Thread.__init__(self) if not _function_has_free_argument_count(callback, 1): raise SpinnmanInvalidParameterException( "callback", repr(callback), "Incorrect number of parameters") if (error_callback is not None and not _function_has_free_argument_count(error_callback, 2)): raise SpinnmanInvalidParameterException( "error_callback", repr(error_callback), "Incorrect number of parameters") self._scp_receiver = scp_receiver self._response_class = response_class self._error_callback = error_callback self._queue_consumer = _CallbackQueue(callback) self._running = False self.setDaemon(True)
[docs] def start(self): """ Starts listening and sending callbacks :return: Nothing is returned :rtype: None :raise None: No known exceptions are raised """ self._queue_consumer.start() super(SCPListener, self).start()
[docs] def run(self): """ Overridden method of Thread that runs this listener """ self._running = True scp_response = self._response_class() while self._running and self._scp_receiver.is_connected(): try: self._scp_receiver.receive_scp_response(scp_response) self._queue_consumer.add_item(scp_response) except Exception as exception: self._running = False self._error_callback(exception, "Error receiving packet") self.stop()
[docs] def stop(self): """ Stops the reception of packets :return: Nothing is returned :rtype: None :raise None: No known exceptions are raised """ self._running = False self._queue_consumer.stop()