Beispiel #1
0
 def progress(percent):
     progress_msg = ForwardMsg()
     progress_msg.upload_report_progress = percent
     yield ws.write_message(serialize_forward_msg(progress_msg), binary=True)
Beispiel #2
0
def _create_dataframe_msg(df, id=1):
    msg = ForwardMsg()
    msg.metadata.delta_id = id
    msg.metadata.parent_block.container = BlockPath.SIDEBAR
    data_frame_proto.marshall_data_frame(df, msg.delta.new_element.data_frame)
    return msg
Beispiel #3
0
    def _on_scriptrunner_event(self, event, exception=None, client_state=None):
        """Called when our ScriptRunner emits an event.

        This is *not* called on the main thread.

        Parameters
        ----------
        event : ScriptRunnerEvent

        exception : BaseException | None
            An exception thrown during compilation. Set only for the
            SCRIPT_STOPPED_WITH_COMPILE_ERROR event.

        client_state : streamlit.proto.ClientState_pb2.ClientState | None
            The ScriptRunner's final ClientState. Set only for the
            SHUTDOWN event.

        """
        LOGGER.debug("OnScriptRunnerEvent: %s", event)

        prev_state = self._state

        if event == ScriptRunnerEvent.SCRIPT_STARTED:
            if self._state != ReportSessionState.SHUTDOWN_REQUESTED:
                self._state = ReportSessionState.REPORT_IS_RUNNING

            if config.get_option("server.liveSave"):
                # Enqueue into the IOLoop so it runs without blocking AND runs
                # on the main thread.
                self._ioloop.spawn_callback(self._save_running_report)

            self._clear_queue()
            self._maybe_enqueue_initialize_message()
            self._enqueue_new_report_message()

        elif (
            event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS
            or event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_COMPILE_ERROR
        ):

            if self._state != ReportSessionState.SHUTDOWN_REQUESTED:
                self._state = ReportSessionState.REPORT_NOT_RUNNING

            script_succeeded = event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS

            self._enqueue_report_finished_message(
                ForwardMsg.FINISHED_SUCCESSFULLY
                if script_succeeded
                else ForwardMsg.FINISHED_WITH_COMPILE_ERROR
            )

            if config.get_option("server.liveSave"):
                # Enqueue into the IOLoop so it runs without blocking AND runs
                # on the main thread.
                self._ioloop.spawn_callback(self._save_final_report_and_quit)

            if script_succeeded:
                # When a script completes successfully, we update our
                # LocalSourcesWatcher to account for any source code changes
                # that change which modules should be watched. (This is run on
                # the main thread, because LocalSourcesWatcher is not
                # thread safe.)
                self._ioloop.spawn_callback(
                    self._local_sources_watcher.update_watched_modules
                )
            else:
                # When a script fails to compile, we send along the exception.
                from streamlit.elements import exception_proto

                msg = ForwardMsg()
                exception_proto.marshall(
                    msg.session_event.script_compilation_exception, exception
                )
                self.enqueue(msg)

        elif event == ScriptRunnerEvent.SHUTDOWN:
            # When ScriptRunner shuts down, update our local reference to it,
            # and check to see if we need to spawn a new one. (This is run on
            # the main thread.)

            if self._state == ReportSessionState.SHUTDOWN_REQUESTED:
                # Only clear media files if the script is done running AND the
                # report session is actually shutting down.
                media_file_manager.clear_session_files(self.id)

            def on_shutdown():
                self._client_state = client_state
                self._scriptrunner = None
                # Because a new ScriptEvent could have been enqueued while the
                # scriptrunner was shutting down, we check to see if we should
                # create a new one. (Otherwise, a newly-enqueued ScriptEvent
                # won't be processed until another event is enqueued.)
                self._maybe_create_scriptrunner()

            self._ioloop.spawn_callback(on_shutdown)

        # Send a message if our run state changed
        report_was_running = prev_state == ReportSessionState.REPORT_IS_RUNNING
        report_is_running = self._state == ReportSessionState.REPORT_IS_RUNNING
        if report_is_running != report_was_running:
            self._enqueue_session_state_changed_message()
Beispiel #4
0
def _create_dataframe_msg(df, id=1) -> ForwardMsg:
    msg = ForwardMsg()
    msg.metadata.delta_path[:] = make_delta_path(RootContainer.SIDEBAR, (), id)
    data_frame.marshall_data_frame(df, msg.delta.new_element.data_frame)
    return msg
def _create_dataframe_msg(df, id=1):
    msg = ForwardMsg()
    msg.metadata.delta_path[:] = [RootContainer.SIDEBAR, id]
    data_frame_proto.marshall_data_frame(df, msg.delta.new_element.data_frame)
    return msg
Beispiel #6
0
    def _on_scriptrunner_event(
        self,
        sender: Optional[ScriptRunner],
        event: ScriptRunnerEvent,
        exception: Optional[BaseException] = None,
        client_state: Optional[ClientState] = None,
    ) -> None:
        """Called when our ScriptRunner emits an event.

        This is called from the sender ScriptRunner's script thread;
        it is *not* called on the main thread.

        Parameters
        ----------
        sender : ScriptRunner | None
            The ScriptRunner that emitted the event. This will be set to
            None when called from `handle_backmsg_exception`.

        event : ScriptRunnerEvent
            The event type.

        exception : BaseException | None
            An exception thrown during compilation. Set only for the
            SCRIPT_STOPPED_WITH_COMPILE_ERROR event.

        client_state : streamlit.proto.ClientState_pb2.ClientState | None
            The ScriptRunner's final ClientState. Set only for the
            SHUTDOWN event.

        """
        LOGGER.debug("OnScriptRunnerEvent: %s", event)

        prev_state = self._state

        if event == ScriptRunnerEvent.SCRIPT_STARTED:
            if self._state != AppSessionState.SHUTDOWN_REQUESTED:
                self._state = AppSessionState.APP_IS_RUNNING

            self._clear_queue()
            self._enqueue_new_session_message()

        elif (event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS
              or event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_COMPILE_ERROR):

            if self._state != AppSessionState.SHUTDOWN_REQUESTED:
                self._state = AppSessionState.APP_NOT_RUNNING

            script_succeeded = event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS

            self._enqueue_script_finished_message(
                ForwardMsg.FINISHED_SUCCESSFULLY if script_succeeded else
                ForwardMsg.FINISHED_WITH_COMPILE_ERROR)

            if script_succeeded:
                # When a script completes successfully, we update our
                # LocalSourcesWatcher to account for any source code changes
                # that change which modules should be watched. (This is run on
                # the main thread, because LocalSourcesWatcher is not
                # thread safe.)
                self._ioloop.spawn_callback(
                    self._local_sources_watcher.update_watched_modules)
            else:
                assert (
                    exception is not None
                ), "exception must be set for the SCRIPT_STOPPED_WITH_COMPILE_ERROR event"
                msg = ForwardMsg()
                exception_utils.marshall(
                    msg.session_event.script_compilation_exception, exception)
                self.enqueue(msg)

        elif event == ScriptRunnerEvent.SHUTDOWN:
            # When ScriptRunner shuts down, update our local reference to it,
            # and check to see if we need to spawn a new one. (This is run on
            # the main thread.)

            assert (
                client_state
                is not None), "client_state must be set for the SHUTDOWN event"

            if self._state == AppSessionState.SHUTDOWN_REQUESTED:
                # Only clear media files if the script is done running AND the
                # session is actually shutting down.
                in_memory_file_manager.clear_session_files(self.id)

            def on_shutdown():
                # We assert above that this is non-null
                self._client_state = cast(ClientState, client_state)

                self._scriptrunner = None
                # Because a new ScriptEvent could have been enqueued while the
                # scriptrunner was shutting down, we check to see if we should
                # create a new one. (Otherwise, a newly-enqueued ScriptEvent
                # won't be processed until another event is enqueued.)
                self._maybe_create_scriptrunner()

            self._ioloop.spawn_callback(on_shutdown)

        # Send a message if our run state changed
        app_was_running = prev_state == AppSessionState.APP_IS_RUNNING
        app_is_running = self._state == AppSessionState.APP_IS_RUNNING
        if app_is_running != app_was_running:
            self._enqueue_session_state_changed_message()
Beispiel #7
0
 def _enqueue_file_change_message(self) -> None:
     LOGGER.debug("Enqueuing script_changed message (id=%s)", self.id)
     msg = ForwardMsg()
     msg.session_event.script_changed_on_disk = True
     self.enqueue(msg)
Beispiel #8
0
def _create_script_finished_msg(status) -> ForwardMsg:
    msg = ForwardMsg()
    msg.script_finished = status
    return msg
Beispiel #9
0
 def _enqueue_session_state_changed_message(self):
     msg = ForwardMsg()
     msg.session_state_changed.run_on_save = self._run_on_save
     msg.session_state_changed.report_is_running = (
         self._state == ReportSessionState.REPORT_IS_RUNNING)
     self.enqueue(msg)
Beispiel #10
0
 def _create_exception_message(self, e: BaseException) -> ForwardMsg:
     """Create and return an Exception ForwardMsg."""
     msg = ForwardMsg()
     exception_utils.marshall(msg.delta.new_element.exception, e)
     return msg
Beispiel #11
0
import copy
import unittest
from typing import Tuple

from parameterized import parameterized

from streamlit import RootContainer
from streamlit.cursor import make_delta_path
from streamlit.forward_msg_queue import ForwardMsgQueue
from streamlit.elements import legacy_data_frame
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg

# For the messages below, we don't really care about their contents so much as
# their general type.

NEW_SESSION_MSG = ForwardMsg()
NEW_SESSION_MSG.new_session.config.allow_run_on_save = True

TEXT_DELTA_MSG1 = ForwardMsg()
TEXT_DELTA_MSG1.delta.new_element.text.body = "text1"
TEXT_DELTA_MSG1.metadata.delta_path[:] = make_delta_path(
    RootContainer.MAIN, (), 0)

TEXT_DELTA_MSG2 = ForwardMsg()
TEXT_DELTA_MSG2.delta.new_element.text.body = "text2"
TEXT_DELTA_MSG2.metadata.delta_path[:] = make_delta_path(
    RootContainer.MAIN, (), 0)

ADD_BLOCK_MSG = ForwardMsg()
ADD_BLOCK_MSG.metadata.delta_path[:] = make_delta_path(RootContainer.MAIN, (),
                                                       0)
Beispiel #12
0
 def _create_file_change_message(self) -> ForwardMsg:
     """Create and return a 'script_changed_on_disk' ForwardMsg."""
     msg = ForwardMsg()
     msg.session_event.script_changed_on_disk = True
     return msg
Beispiel #13
0
    def _handle_scriptrunner_event_on_main_thread(
        self,
        sender: Optional[ScriptRunner],
        event: ScriptRunnerEvent,
        forward_msg: Optional[ForwardMsg] = None,
        exception: Optional[BaseException] = None,
        client_state: Optional[ClientState] = None,
    ) -> None:
        """Handle a ScriptRunner event.

        This function must only be called on the main thread.

        Parameters
        ----------
        sender : ScriptRunner | None
            The ScriptRunner that emitted the event. (This may be set to
            None when called from `handle_backmsg_exception`, if no
            ScriptRunner was active when the backmsg exception was raised.)

        event : ScriptRunnerEvent
            The event type.

        forward_msg : ForwardMsg | None
            The ForwardMsg to send to the frontend. Set only for the
            ENQUEUE_FORWARD_MSG event.

        exception : BaseException | None
            An exception thrown during compilation. Set only for the
            SCRIPT_STOPPED_WITH_COMPILE_ERROR event.

        client_state : streamlit.proto.ClientState_pb2.ClientState | None
            The ScriptRunner's final ClientState. Set only for the
            SHUTDOWN event.

        """

        assert (threading.main_thread() == threading.current_thread()
                ), "This function must only be called on the main thread"

        if sender is not self._scriptrunner:
            # This event was sent by a non-current ScriptRunner; ignore it.
            # This can happen after sppinng up a new ScriptRunner (to handle a
            # rerun request, for example) while another ScriptRunner is still
            # shutting down. The shutting-down ScriptRunner may still
            # emit events.
            LOGGER.debug("Ignoring event from non-current ScriptRunner: %s",
                         event)
            return

        prev_state = self._state

        if event == ScriptRunnerEvent.SCRIPT_STARTED:
            if self._state != AppSessionState.SHUTDOWN_REQUESTED:
                self._state = AppSessionState.APP_IS_RUNNING

            self._clear_queue()
            self._enqueue_forward_msg(self._create_new_session_message())

        elif (event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS
              or event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_COMPILE_ERROR):

            if self._state != AppSessionState.SHUTDOWN_REQUESTED:
                self._state = AppSessionState.APP_NOT_RUNNING

            script_succeeded = event == ScriptRunnerEvent.SCRIPT_STOPPED_WITH_SUCCESS

            script_finished_msg = self._create_script_finished_message(
                ForwardMsg.FINISHED_SUCCESSFULLY if script_succeeded else
                ForwardMsg.FINISHED_WITH_COMPILE_ERROR)
            self._enqueue_forward_msg(script_finished_msg)

            if script_succeeded:
                # The script completed successfully: update our
                # LocalSourcesWatcher to account for any source code changes
                # that change which modules should be watched.
                self._local_sources_watcher.update_watched_modules()
            else:
                # The script didn't complete successfully: send the exception
                # to the frontend.
                assert (
                    exception is not None
                ), "exception must be set for the SCRIPT_STOPPED_WITH_COMPILE_ERROR event"
                msg = ForwardMsg()
                exception_utils.marshall(
                    msg.session_event.script_compilation_exception, exception)
                self._enqueue_forward_msg(msg)

        elif event == ScriptRunnerEvent.SHUTDOWN:
            assert (
                client_state
                is not None), "client_state must be set for the SHUTDOWN event"

            if self._state == AppSessionState.SHUTDOWN_REQUESTED:
                # Only clear media files if the script is done running AND the
                # session is actually shutting down.
                in_memory_file_manager.clear_session_files(self.id)

            self._client_state = client_state
            self._scriptrunner = None

        elif event == ScriptRunnerEvent.ENQUEUE_FORWARD_MSG:
            assert (
                forward_msg
                is not None), "null forward_msg in ENQUEUE_FORWARD_MSG event"
            self._enqueue_forward_msg(forward_msg)

        # Send a message if our run state changed
        app_was_running = prev_state == AppSessionState.APP_IS_RUNNING
        app_is_running = self._state == AppSessionState.APP_IS_RUNNING
        if app_is_running != app_was_running:
            self._enqueue_forward_msg(
                self._create_session_state_changed_message())
Beispiel #14
0
 def progress(percent):
     progress_msg = ForwardMsg()
     progress_msg.upload_report_progress = percent
     yield ws.write_message(progress_msg.SerializeToString(),
                            binary=True)
Beispiel #15
0
 def read_forward_msg(self, ws_client):
     """Parse the next message from a Websocket client into a ForwardMsg."""
     data = yield ws_client.read_message()
     message = ForwardMsg()
     message.ParseFromString(data)
     raise gen.Return(message)
Beispiel #16
0
"""Unit tests for session_data.py."""

from unittest.mock import patch
import copy
import unittest

from parameterized import parameterized

from streamlit import config, RootContainer
from streamlit.cursor import make_delta_path
from streamlit.session_data import get_url
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
from streamlit.proto.Empty_pb2 import Empty as EmptyProto
from tests import testutil

NEW_SESSION_MSG = ForwardMsg()
NEW_SESSION_MSG.metadata.delta_path[:] = make_delta_path(RootContainer.MAIN, (), 0)

TEXT_DELTA_MSG = ForwardMsg()
TEXT_DELTA_MSG.delta.new_element.text.body = "text1"
TEXT_DELTA_MSG.metadata.delta_path[:] = make_delta_path(RootContainer.MAIN, (), 0)

EMPTY_DELTA_MSG = ForwardMsg()
EMPTY_DELTA_MSG.delta.new_element.empty.CopyFrom(EmptyProto())
EMPTY_DELTA_MSG.metadata.delta_path[:] = make_delta_path(RootContainer.MAIN, (), 0)


def _enqueue(report, msg):
    msg = copy.deepcopy(msg)
    msg.metadata.delta_path[-1] = len(list(report._master_queue))
    report.enqueue(msg)
Beispiel #17
0
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit test of ReportQueue.py."""

import copy
import unittest

from streamlit.ReportQueue import ReportQueue
from streamlit.elements import data_frame_proto
from streamlit.proto.BlockPath_pb2 import BlockPath
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg

# For the messages below, we don't really care about their contents so much as
# their general type.

INIT_MSG = ForwardMsg()
INIT_MSG.initialize.config.sharing_enabled = True

TEXT_DELTA_MSG1 = ForwardMsg()
TEXT_DELTA_MSG1.delta.new_element.text.body = "text1"

TEXT_DELTA_MSG2 = ForwardMsg()
TEXT_DELTA_MSG2.delta.new_element.text.body = "text2"

DF_DELTA_MSG = ForwardMsg()
data_frame_proto.marshall_data_frame({
    "col1": [0, 1, 2],
    "col2": [10, 11, 12]
}, DF_DELTA_MSG.delta.new_element.data_frame)

ADD_ROWS_MSG = ForwardMsg()
Beispiel #18
0
from unittest.mock import patch
import copy
import unittest

from parameterized import parameterized

from streamlit import config, RootContainer
from streamlit.cursor import make_delta_path
from streamlit.report import Report
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
from streamlit.proto.StaticManifest_pb2 import StaticManifest
from streamlit.proto.Empty_pb2 import Empty as EmptyProto
from tests import testutil

NEW_REPORT_MSG = ForwardMsg()
NEW_REPORT_MSG.new_report.initialize.config.sharing_enabled = True
NEW_REPORT_MSG.metadata.delta_path[:] = make_delta_path(
    RootContainer.MAIN, (), 0)

TEXT_DELTA_MSG = ForwardMsg()
TEXT_DELTA_MSG.delta.new_element.text.body = "text1"
TEXT_DELTA_MSG.metadata.delta_path[:] = make_delta_path(
    RootContainer.MAIN, (), 0)

EMPTY_DELTA_MSG = ForwardMsg()
EMPTY_DELTA_MSG.delta.new_element.empty.CopyFrom(EmptyProto())
EMPTY_DELTA_MSG.metadata.delta_path[:] = make_delta_path(
    RootContainer.MAIN, (), 0)

Beispiel #19
0
 def _enqueue_session_state_changed_message(self) -> None:
     msg = ForwardMsg()
     msg.session_state_changed.run_on_save = self._run_on_save
     msg.session_state_changed.script_is_running = (
         self._state == AppSessionState.APP_IS_RUNNING)
     self.enqueue(msg)
Beispiel #20
0
"""Unit tests for report.py."""

from unittest.mock import patch
import copy
import unittest

from parameterized import parameterized

from streamlit import config, RootContainer
from streamlit.cursor import make_delta_path
from streamlit.report import Report
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
from streamlit.proto.StaticManifest_pb2 import StaticManifest
from tests import testutil

INIT_MSG = ForwardMsg()
INIT_MSG.initialize.config.sharing_enabled = True
INIT_MSG.metadata.delta_path[:] = make_delta_path(RootContainer.MAIN, (), 0)

TEXT_DELTA_MSG = ForwardMsg()
TEXT_DELTA_MSG.delta.new_element.text.body = "text1"
TEXT_DELTA_MSG.metadata.delta_path[:] = make_delta_path(
    RootContainer.MAIN, (), 0)

EMPTY_DELTA_MSG = ForwardMsg()
EMPTY_DELTA_MSG.delta.new_element.empty.unused = True
EMPTY_DELTA_MSG.metadata.delta_path[:] = make_delta_path(
    RootContainer.MAIN, (), 0)


def _enqueue(report, msg):
Beispiel #21
0
 def _enqueue_script_finished_message(
         self, status: "ForwardMsg.ScriptFinishedStatus.ValueType") -> None:
     """Enqueue a script_finished ForwardMsg."""
     msg = ForwardMsg()
     msg.script_finished = status
     self.enqueue(msg)
Beispiel #22
0
def _parse_msg(msg_string):
    """Parse a ForwardMsg from a string"""
    msg = ForwardMsg()
    msg.ParseFromString(msg_string)
    return msg
Beispiel #23
0
def _create_report_finished_msg(status) -> ForwardMsg:
    msg = ForwardMsg()
    msg.report_finished = status
    return msg
Beispiel #24
0
 def _enqueue_report_finished_message(self):
     msg = ForwardMsg()
     msg.report_finished = True
     self.enqueue(msg)