def test_coalesce_widget_states(self): old_states = WidgetStates() _create_widget("old_set_trigger", old_states).trigger_value = True _create_widget("old_unset_trigger", old_states).trigger_value = False _create_widget("missing_in_new", old_states).int_value = 123 _create_widget("shape_changing_trigger", old_states).trigger_value = True new_states = WidgetStates() _create_widget("old_set_trigger", new_states).trigger_value = False _create_widget("new_set_trigger", new_states).trigger_value = True _create_widget("added_in_new", new_states).int_value = 456 _create_widget("shape_changing_trigger", new_states).int_value = 3 widgets = Widgets() widgets.set_state(coalesce_widget_states(old_states, new_states)) self.assertIsNone(widgets.get_widget_value("old_unset_trigger")) self.assertIsNone(widgets.get_widget_value("missing_in_new")) self.assertEqual(True, widgets.get_widget_value("old_set_trigger")) self.assertEqual(True, widgets.get_widget_value("new_set_trigger")) self.assertEqual(456, widgets.get_widget_value("added_in_new")) # Widgets that were triggers before, but no longer are, will *not* # be coalesced self.assertEqual(3, widgets.get_widget_value("shape_changing_trigger"))
def enqueue(self, event, data=None): """Enqueue a new event to the end of the queue. This event may be coalesced with an existing event if appropriate. For example, multiple consecutive RERUN requests will be combined so that there's only ever one pending RERUN request in the queue at a time. Parameters ---------- event : ScriptEvent The type of event data : Any Data associated with the event, if any """ with self._cond: if event == ScriptEvent.SHUTDOWN: # If we get a shutdown request, it goes to the front of the # queue to be processed immediately. self._queue.append((event, data)) elif event == ScriptEvent.RERUN: index = _index_if(self._queue, lambda item: item[0] == event) if index >= 0: _, old_data = self._queue[index] if old_data.widget_state is None: # The existing request's widget_state is None, which # means it wants to rerun with whatever the most # recent script execution's widget state was. # We have no meaningful state to merge with, and # so we simply overwrite the existing request. self._queue[index] = ( event, RerunData(argv=data.argv, widget_state=data.widget_state)) elif data.widget_state is None: # If this request's widget_state is None, and the # existing request's widget_state was not, this # new request is entirely redundant and can be dropped. pass else: # Both the existing and the new request have # non-null widget_states. Merge them together. coalesced_state = coalesce_widget_states( old_data.widget_state, data.widget_state) self._queue[index] = ( event, RerunData(argv=data.argv, widget_state=coalesced_state)) else: self._queue.appendleft((event, data)) else: self._queue.appendleft((event, data)) # Let any consumers know that we have new data self._cond.notify()
def enqueue(self, request, data=None): """Enqueue a new request to the end of the queue. This request may be coalesced with an existing request if appropriate. For example, multiple consecutive RERUN requests will be combined so that there's only ever one pending RERUN request in the queue at a time. Parameters ---------- request : ScriptRequest The type of request data : Any Data associated with the request, if any. For example, could be of type RerunData. """ with self._lock: if request == ScriptRequest.SHUTDOWN: # If we get a shutdown request, it jumps to the front of the # queue to be processed immediately. self._queue.appendleft((request, data)) elif request == ScriptRequest.RERUN: index = _index_if(self._queue, lambda item: item[0] == request) if index >= 0: _, old_data = self._queue[index] if old_data.widget_states is None: # The existing request's widget_states is None, which # means it wants to rerun with whatever the most # recent script execution's widget state was. # We have no meaningful state to merge with, and # so we simply overwrite the existing request. self._queue[index] = ( request, RerunData( query_string=data.query_string, widget_states=data.widget_states, ), ) elif data.widget_states is None: # If this request's widget_states is None, and the # existing request's widget_states was not, this # new request is entirely redundant and can be dropped. # TODO: Figure out if this should even happen. This sounds like it should # raise an exception... pass else: # Both the existing and the new request have # non-null widget_states. Merge them together. coalesced_states = coalesce_widget_states( old_data.widget_states, data.widget_states ) self._queue[index] = ( request, RerunData( query_string=data.query_string, widget_states=coalesced_states, ), ) else: self._queue.append((request, data)) else: self._queue.append((request, data))