Esempio n. 1
0
    def test_coalesce_widget_states(self):
        session_state = SessionState()

        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

        session_state._set_widget_metadata(
            create_metadata("old_set_trigger", "trigger_value")
        )
        session_state._set_widget_metadata(
            create_metadata("old_unset_trigger", "trigger_value")
        )
        session_state._set_widget_metadata(
            create_metadata("missing_in_new", "int_value")
        )
        session_state._set_widget_metadata(
            create_metadata("shape changing trigger", "trigger_value")
        )

        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
        session_state._set_widget_metadata(
            create_metadata("new_set_trigger", "trigger_value")
        )
        session_state._set_widget_metadata(create_metadata("added_in_new", "int_value"))
        session_state._set_widget_metadata(
            create_metadata("shape_changing_trigger", "int_value")
        )

        session_state.set_widgets_from_proto(
            coalesce_widget_states(old_states, new_states)
        )

        self.assertIsNone(session_state.get("old_unset_trigger"))
        self.assertIsNone(session_state.get("missing_in_new"))

        self.assertEqual(True, session_state.get("old_set_trigger"))
        self.assertEqual(True, session_state.get("new_set_trigger"))
        self.assertEqual(456, session_state.get("added_in_new"))

        # Widgets that were triggers before, but no longer are, will *not*
        # be coalesced
        self.assertEqual(3, session_state.get("shape_changing_trigger"))
Esempio n. 2
0
    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))
Esempio n. 3
0
    def enqueue(self, request: ScriptRequest, data: Any = None) -> 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))
                return

            if request == ScriptRequest.RERUN:
                # RERUN requests are special - if there's an existing rerun
                # request in the queue, we try to coalesce this one into it
                # to avoid having redundant RERUNS.
                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,
                            ),
                        )
                        return

                    if data.widget_states is not None:
                        # 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,
                            ),
                        )
                        return

                    # `old_data.widget_states is not None and data.widget_states is None` -
                    # this new request is entirely redundant and can be dropped.
                    return

            # Base case: add the request to the end of the queue.
            self._queue.append((request, data))