Skip to content

Commit

Permalink
Switched to Namespace from WeakNamespace for signals. Added signal te…
Browse files Browse the repository at this point in the history
…st cases. Raised version to 0.1.12
  • Loading branch information
danwos committed Jul 26, 2017
1 parent 0a6049d commit 52de439
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 12 deletions.
26 changes: 17 additions & 9 deletions groundwork/signals.py
@@ -1,8 +1,14 @@
import logging
from blinker import WeakNamespace

# from blinker import Namespace

class SignalsApplication():
# Used in groundwork <= 0.1.11
# Used WeakNamespace could also be Namespace.
# But doc says, Weaknamespace gets clean up, if no reference exists anymore.
from blinker import WeakNamespace as Namespace


class SignalsApplication:
"""
Signal and Receiver management class on application level.
This class is initialised once per groundwork application object.
Expand Down Expand Up @@ -32,11 +38,9 @@ def __init__(self, app):
# How to use namespace in blinker? See:
# http://flask.pocoo.org/docs/0.11/signals/#creating-signals for blinker namespace usage
# https://github.com/jek/blinker/blob/master/blinker/base.py#L432
# Used WeakNamespace could also be Namespace.
# But doc says, Weaknamespace gets clean up, if no reference exists anymore.
#: Used blinker namespace object to register signals only for the context of a single groundwork application
#: instance
self.__namespace = WeakNamespace()
self._namespace = Namespace()

self.__log.info("Application signals initialised")

Expand All @@ -52,7 +56,7 @@ def register(self, signal, plugin, description=""):
if signal in self.signals.keys():
raise Exception("Signal %s was already registered by %s" % (signal, self.signals[signal].plugin.name))

self.signals[signal] = Signal(signal, plugin, self.__namespace, description)
self.signals[signal] = Signal(signal, plugin, self._namespace, description)
self.__log.debug("Signal %s registered by %s" % (signal, plugin.name))
return self.signals[signal]

Expand Down Expand Up @@ -86,7 +90,7 @@ def connect(self, receiver, signal, function, plugin, description="", sender=Non
if receiver in self.receivers.keys():
raise Exception("Receiver %s was already registered by %s" % (receiver,
self.receivers[receiver].plugin.name))
self.receivers[receiver] = Receiver(receiver, signal, function, plugin, self.__namespace, description, sender)
self.receivers[receiver] = Receiver(receiver, signal, function, plugin, self._namespace, description, sender)
self.__log.debug("Receiver %s registered for signal %s" % (receiver, signal))
return self.receivers[receiver]

Expand All @@ -113,7 +117,7 @@ def send(self, signal, plugin, **kwargs):
:type plugin: GwBasePattern
"""
if signal not in self.signals.keys():
raise Exception("Unknown signal %s" % signal)
raise UnknownSignal("Unknown signal %s" % signal)
self.__log.debug("Sending signal %s for %s" % (signal, plugin.name))
rv = self.signals[signal].send(plugin, **kwargs)
return rv
Expand Down Expand Up @@ -153,7 +157,7 @@ def get(self, signal=None, plugin=None):

def get_receiver(self, receiver=None, plugin=None):
"""
Get one or more signals.
Get one or more receivers.
:param receiver: Name of the signal
:type receiver: str
Expand Down Expand Up @@ -249,3 +253,7 @@ def connect(self):

def disconnect(self):
self.namespace.signal(self.signal).disconnect(self.function)


class UnknownSignal(Exception):
pass
2 changes: 1 addition & 1 deletion groundwork/version.py
@@ -1 +1 @@
__version__ = "0.1.11"
__version__ = "0.1.12"
86 changes: 84 additions & 2 deletions tests/test_signals.py
@@ -1,3 +1,6 @@
import pytest


def test_signal_registration(basicApp):
plugin = basicApp.plugins.get("BasicPlugin")
signals = plugin.signals.get()
Expand All @@ -15,7 +18,6 @@ def test_signal_send(basicApp):


def test_signal_connect(basicApp):

def _test_command(plugin, **kwargs):
return "12345"

Expand Down Expand Up @@ -61,7 +63,6 @@ def _test_command(plugin, **kwargs):


def test_multi_plugin_deactivations(basicApp, EmptyPlugin):

def test():
pass

Expand All @@ -75,6 +76,7 @@ def test():
assert len(plugin2_signals) == 1

plugin_signals = plugin.signals.get()
# BasicPlugin has already registered a signal during init
assert len(plugin_signals) == 1

plugin2.deactivate()
Expand All @@ -84,3 +86,83 @@ def test():

assert len(plugin_signals) == 1
assert plugin.active is True


def test_signal_registration(basicApp, EmptyPlugin):
from blinker import NamedSignal
from groundwork.signals import UnknownSignal

def sig_reg_test(plugin, **kwargs):
return ["data_1", "data_2"]

plugin1 = EmptyPlugin(app=basicApp, name="EmptyPlugin")

# This creates a gw receiver and a blinker internal signal called "test"
plugin1.signals.connect("sig_reg_receiver", "sig_reg_test", sig_reg_test, "receiver sig_reg for test")

# Check the blinker internal registration
signal_namespace = basicApp.signals._namespace
assert "sig_reg_test" in signal_namespace.keys()
test_signal = signal_namespace["sig_reg_test"]
assert isinstance(test_signal, NamedSignal)

# Check the gw registration
plugin_signals = plugin1.signals.get()
# This must be 0, because gw has not registered a signal, this was done in blinker only
assert len(plugin_signals) == 0

app_signals = basicApp.signals.get()
assert "sig_reg_test" not in app_signals.keys()

# Check if signal sending throws an error (without a registered gw signal)
with pytest.raises(UnknownSignal):
plugin1.signals.send("sig_reg_test")

# Check if gw has a registered receiver
plugin_receivers = plugin1.signals.get_receiver()
assert "sig_reg_receiver" in plugin_receivers.keys()

# Register the missing gw signal
plugin_signal = plugin1.signals.register("sig_reg_test", "signal for sig_reg_test")
assert plugin_signal is not None

# Recheck the gw registration
plugin_signals = plugin1.signals.get()
# This must be 1, because gw has registered a signal now
assert len(plugin_signals) == 1

# Sending should work now
return_values = plugin1.signals.send("sig_reg_test")
# Check if the receivers sends back needed data
assert len(return_values) == 1
assert return_values[0][1][0] == "data_1"


def test_signal_handling_via_plugins(basicApp, EmptyPlugin):
def sig_reg_test_1(plugin, **kwargs):
return ["data_1", "data_2"]

def sig_reg_test_2(plugin, **kwargs):
return ["data_3", "data_4"]

plugin_send = EmptyPlugin(app=basicApp, name="Plugin_send")

plugin_receive_pre = EmptyPlugin(app=basicApp, name="Plugin_receive_pre")
plugin_receive_post = EmptyPlugin(app=basicApp, name="Plugin_receive_post")

plugin_receive_pre.activate()
plugin_receive_pre.signals.connect("sig_reg_pre_receiver", "signal_test",
sig_reg_test_1, "receiver signal_test for test")

plugin_send.activate()
plugin_send.signals.register("signal_test", "signal_test doc")

return_values = plugin_send.signals.send("signal_test")
assert len(return_values) == 1

plugin_receive_post.activate()
plugin_receive_post.signals.connect("sig_reg_post_receiver", "signal_test",
sig_reg_test_2, "receiver signal_test for test")

return_values = plugin_send.signals.send("signal_test")
assert len(return_values) == 2

0 comments on commit 52de439

Please sign in to comment.