def test_merge_signals_with_duplicate_attributes(self):
     """ input_2 attributes override input_1 attributes """
     blk = MergeStreams()
     signal_1 = Signal({"A": 1})
     signal_2 = Signal({"A": 2})
     blk._signals["null"]["input_1"] = signal_1
     blk._signals["null"]["input_2"] = signal_2
     merged_signal = blk._merge_signals(group="null")
     self.assertDictEqual(merged_signal.to_dict(), signal_2.to_dict())
Esempio n. 2
0
 def test_buffer(self):
     event = Event()
     block = EventBuffer(event)
     block._backup = MagicMock()
     self.configure_block(block, {"interval": {"milliseconds": 200}})
     block.start()
     block.process_signals([Signal(), Signal(), Signal(), Signal()])
     self.assert_num_signals_notified(0, block)
     event.wait(.3)
     self.assert_num_signals_notified(4, block)
     block.stop()
 def test_debounce(self):
     block = Debouncer()
     block._backup = MagicMock()
     self.configure_block(block, {"interval": {"milliseconds": 200}})
     block.start()
     block.process_signals([Signal(), Signal()])
     block.process_signals([Signal()])
     self.assert_num_signals_notified(1, block)
     sleep(.3)
     block.process_signals([Signal()])
     self.assert_num_signals_notified(2, block)
     block.stop()
Esempio n. 4
0
 def test_interval_duration(self):
     event = Event()
     block = EventBuffer(event)
     block._backup = MagicMock()
     self.configure_block(
         block, {
             "interval": {
                 "milliseconds": 1000
             },
             "interval_duration": {
                 "milliseconds": 2000
             }
         })
     block.start()
     # process 4 signals (first group)
     block.process_signals([Signal(), Signal(), Signal(), Signal()])
     self.assert_num_signals_notified(0, block)
     event.wait(1.3)
     # first emit notifies first group
     self.assert_num_signals_notified(4, block)
     # process 2 more signals (second group)
     block.process_signals([Signal(), Signal()])
     event.wait(1.3)
     # second emit notifies first group and second group
     self.assert_num_signals_notified(10, block)
     # process 2 more signals (thrid group)
     block.process_signals([Signal(), Signal()])
     event.wait(1.3)
     # third emit notifies second group and third group
     self.assert_num_signals_notified(14, block)
     block.stop()
 def test_hash(self):
     signals = [{
         'flavor': 'cherry'
     }, {
         'flavor': 'cherry',
         'size': 'S'
     }, {
         'flavor': 'cherry',
         'size': 'M'
     }, {
         'flavor': 'cherry',
         'size': 'L'
     }, {
         'flavor': 'banana',
         'size': 'S'
     }, {
         'flavor': 'apple',
         'size': 'S'
     }]
     blk = HashTable()
     config = {
         "key": "{{$flavor}}",
         "value": "{{$size}}",
     }
     self.configure_block(blk, config)
     blk.start()
     blk.process_signals([Signal(s) for s in signals])
     self.assert_num_signals_notified(1, blk)
     self.assertEqual(['S', 'M', 'L'], self.notified_signals[0].cherry)
     self.assertEqual(['S'], self.notified_signals[0].banana)
     self.assertEqual(['S'], self.notified_signals[0].apple)
     blk.stop()
 def test_defaults(self):
     signals = [{
         'key': 'cherry',
         'value': 'S'
     }, {
         'key': 'cherry',
         'value': 'M'
     }, {
         'key': 'cherry',
         'value': 'L'
     }, {
         'key': 'banana',
         'value': 'S'
     }, {
         'key': 'apple',
         'value': 'S'
     }, {
         'flavor': 'bad'
     }]
     blk = HashTable()
     config = {}
     self.configure_block(blk, config)
     blk.start()
     blk.process_signals([Signal(s) for s in signals])
     self.assert_num_signals_notified(1, blk)
     self.assertEqual(['S', 'M', 'L'], self.notified_signals[0].cherry)
     self.assertEqual(['S'], self.notified_signals[0].banana)
     self.assertEqual(['S'], self.notified_signals[0].apple)
    def test_one_value(self):
        signals = [{
            'key': 'cherry',
            'value': 'S'
        }, {
            'key': 'cherry',
            'value': 'M'
        }, {
            'key': 'cherry',
            'value': 'L'
        }, {
            'key': 'banana',
            'value': 'S'
        }, {
            'key': 'apple',
            'value': 'S'
        }, {
            'flavor': 'bad'
        }]
        blk = HashTable()
        config = {'one_value': True}
        self.configure_block(blk, config)
        blk.start()
        blk.process_signals([Signal(s) for s in signals])
        self.assert_num_signals_notified(1, blk)
        self.assertEqual('L', self.notified_signals[0].cherry)
        self.assertEqual('S', self.notified_signals[0].banana)
        self.assertEqual('S', self.notified_signals[0].apple)

        # Make sure the bad one didn't make its way into the output signal
        self.assertFalse(hasattr(self.notified_signals[0], 'flavor'))
        blk.stop()
Esempio n. 8
0
    def _perform_hash(self, signals):
        hash_dict = defaultdict(None) if self.one_value else defaultdict(list)

        for signal in signals:
            try:
                sig_key = self.key(signal)
                # Signal keys need to be strings
                sig_key = str(sig_key)
                sig_value = self.value(signal)
            except AttributeError:
                # If we don't have the value on the signal, don't add it to the
                # hash table
                continue
            except Exception as e:
                self._logger.warning("Failed to evaluate props: {}".format(e))

            # Add sig_value to the proper hash key
            try:
                if sig_key is not None:
                    if self.one_value:
                        hash_dict[sig_key] = sig_value
                    else:
                        hash_dict[sig_key].append(sig_value)
                else:
                    self._logger.debug("Skipping key: {}".format(sig_key))
            except Exception as e:
                self._logger.warning(
                    "Failed to add value {} to key {}: {}".format(
                        sig_value, sig_key, e))

        if len(hash_dict):
            return Signal(hash_dict)
Esempio n. 9
0
 def test_process_signals(self):
     blk = Example()
     self.configure_block(blk, {})
     blk.start()
     blk.process_signals([Signal()])
     blk.stop()
     self.assert_num_signals_notified(1)
     self.assertDictEqual(self.last_notified['default'][0].to_dict(), {})
 def test_invalid_dest_addr(self, mock_serial, mock_xbee):
     blk = XBeeRemoteAT()
     self.configure_block(blk, {"dest_addr": "0"})
     blk.start()
     blk.process_signals([Signal({'iama': 'signal'})])
     # send is never called because of the odd length dest_addr
     # It needs to be a byte, represented as two ascii chars
     self.assertFalse(blk._xbee.send.called)
     blk.stop()
 def test_invalid_command(self, mock_serial, mock_xbee):
     blk = XBeeRemoteAT()
     self.configure_block(blk, {"command": "{{ 1 }}"})
     blk.start()
     blk.process_signals([Signal({'iama': 'signal'})])
     # send is never called because of the command not being ascii encodable
     # It needs to be a two ascii characters
     self.assertFalse(blk._xbee.send.called)
     blk.stop()
Esempio n. 12
0
 def test_debounce_group(self):
     block = Debouncer()
     block._backup = MagicMock()
     self.configure_block(block, {
         "interval": {
             "milliseconds": 200
         },
         "group_by": "{{$foo}}"
     })
     block.start()
     block.process_signals([
         Signal({'foo': 'bar'}),
     ])
     self.assert_num_signals_notified(1, block)
     block.process_signals([Signal({'foo': 'bar'}), Signal({'foo': 'qux'})])
     self.assert_num_signals_notified(2, block)
     sleep(.3)
     block.process_signals([Signal({'foo': 'bar'})])
     self.assert_num_signals_notified(3, block)
     block.stop()
 def test_defaults(self, mock_serial, mock_xbee):
     blk = XBeeRemoteAT()
     self.configure_block(blk, {})
     blk.start()
     blk.process_signals([Signal({'iama': 'signal'})])
     blk._xbee.send.assert_called_once_with('remote_at',
                                            frame_id=b'\x01',
                                            dest_addr=b'\xFF\xFF',
                                            command=b'ID',
                                            parameter=b'')
     self.assertFalse(len(self.signals['default']))
     blk.stop()
    def test_no_copy(self):
        """ Make sure that incoming signals can be copied """
        blk = DummyBlock()
        self.set_up_block(blk, False, 'results')
        incoming_signal = Signal({
            'key1': 'val1',
            'key2': 'val2'
        })

        result_dict = {'a': 1, 'b': 2}
        out_sig = blk.get_output_signal(result_dict, incoming_signal,
                                        copy=False)

        incoming_signal.key1 = 'updated val1'

        # Both signals should have the results now
        self.assertTrue(hasattr(out_sig, 'results'))
        self.assertTrue(hasattr(incoming_signal, 'results'))

        # The updated value should also afect our output signal
        self.assertEqual(out_sig.key1, 'updated val1')
        self.assertEqual(incoming_signal.key1, 'updated val1')
Esempio n. 15
0
 def process_signals(self, signals):
     return_signals = []
     for signal in signals:
         try:
             values = self.list(signal)
         except Exception as e:
             values = [None]
         values = [None] if not values else values
         for value in values:
             sig = Signal(signal.to_dict())
             setattr(sig, self.title, value)
             return_signals.append(sig)
     if return_signals:
         self.notify_signals(return_signals)
    def test_grouping(self):
        signals = [{
            'group': 'fruit',
            'key': 'cherry',
            'value': 'S'
        }, {
            'group': 'fruit',
            'key': 'cherry',
            'value': 'M'
        }, {
            'group': 'fruit',
            'key': 'cherry',
            'value': 'L'
        }, {
            'group': 'pie',
            'key': 'banana',
            'value': 'S'
        }, {
            'group': 'pie',
            'key': 'cherry',
            'value': 'M'
        }, {
            'group': 'pie',
            'key': 'cherry',
            'value': 'L'
        }, {
            'group': 'fruit',
            'key': 'banana',
            'value': 'S'
        }]
        blk = HashTable()
        config = {
            'group_attr': 'my_group',
            'group_by': '{{$group}}',
            'log_level': 'DEBUG'
        }
        self.configure_block(blk, config)
        blk.process_signals([Signal(s) for s in signals])
        self.assert_num_signals_notified(2, blk)
        for sig_out in self.notified_signals:
            # Make sure the group got assigned to the right attr
            self.assertIn(sig_out.my_group, ['fruit', 'pie'])

            # Assert the right values went to the right groups
            if sig_out.my_group == 'fruit':
                self.assertEqual(len(sig_out.cherry), 3)
                self.assertEqual(len(sig_out.banana), 1)
            elif sig_out.my_group == 'pie':
                self.assertEqual(len(sig_out.cherry), 2)
                self.assertEqual(len(sig_out.banana), 1)
 def test_expression_props(self, mock_serial, mock_xbee):
     blk = XBeeRemoteAT()
     self.configure_block(blk, {
         "dest_addr": "00 42",
         "command": "D0",
         "parameter": "05"
     })
     blk.start()
     blk.process_signals([Signal({'iama': 'signal'})])
     blk._xbee.send.assert_called_once_with('remote_at',
                                            frame_id=b'\x01',
                                            dest_addr=b'\x00\x42',
                                            command=b'D0',
                                            parameter=b'\x05')
     self.assertFalse(len(self.signals['default']))
     blk.stop()
 def test_non_string_attributes(self):
     now = datetime.datetime.utcnow()
     signals = [
         {
             'name': 123,
             'value': 456
         },
         {
             'name': 'str',
             'value': 'string'
         },
         {
             'name': {},
             'value': {}
         },
         {
             'name': None,
             'value': None
         },
         {
             'name': now,
             'value': now
         },
     ]
     blk = HashTable()
     self.configure_block(blk, {
         "key": "{{ $name }}",
         "value": "{{ $value }}",
         "one_value": True
     })
     blk.start()
     blk.process_signals([Signal(s) for s in signals])
     self.assert_num_signals_notified(1, blk)
     self.assertDictEqual(
         self.notified_signals[0].to_dict(), {
             "group": "null",
             "123": 456,
             "str": "string",
             "{}": {},
             "None": None,
             str(now): now
         })
     blk.stop()
Esempio n. 19
0
 def emit(self, reset=False):
     self._logger.debug('Emitting signals')
     if reset:
         self._emission_job.cancel()
         self._emission_job = Job(
             self.emit,
             self.interval,
             True
         )
     self._last_emission = datetime.utcnow()
     signals = self._get_emit_signals()
     if signals:
         self._logger.debug('Notifying {} signals'.format(len(signals)))
         self.notify_signals(signals)
     elif self.timeout:
         self._logger.debug('Notifying timeout signal')
         self.notify_signals([Signal({self.timeout_attr: True})])
     else:
         self._logger.debug('No signals to notify')
     if self.use_persistence:
         self.persistence.store('last_emission', self._last_emission)
         self._backup()
Esempio n. 20
0
 def _callback(self, response):
     try:
         self.notify_signals([Signal(response)])
     except:
         self._logger.exception(
             'Response is not valid: {}'.format(response))