def test_add_rows_rerun(self): rq = ForwardMsgQueue() self.assertTrue(rq.is_empty()) rq.enqueue(NEW_SESSION_MSG) # Simulate rerun for i in range(2): TEXT_DELTA_MSG1.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0) rq.enqueue(TEXT_DELTA_MSG1) DF_DELTA_MSG.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 1) rq.enqueue(DF_DELTA_MSG) ADD_ROWS_MSG.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 1) rq.enqueue(ADD_ROWS_MSG) queue = rq.flush() self.assertEqual(len(queue), 3) self.assertEqual(make_delta_path(RootContainer.MAIN, (), 0), queue[1].metadata.delta_path) self.assertEqual(queue[1].delta.new_element.text.body, "text1") self.assertEqual(make_delta_path(RootContainer.MAIN, (), 1), queue[2].metadata.delta_path) col0 = queue[2].delta.new_element.data_frame.data.cols[0].int64s.data col1 = queue[2].delta.new_element.data_frame.data.cols[1].int64s.data self.assertEqual(col0, [0, 1, 2, 3, 4, 5]) self.assertEqual(col1, [10, 11, 12, 13, 14, 15])
def test_simple_add_rows(self): rq = ReportQueue() self.assertTrue(rq.is_empty()) rq.enqueue(NEW_REPORT_MSG) TEXT_DELTA_MSG1.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0 ) rq.enqueue(TEXT_DELTA_MSG1) DF_DELTA_MSG.metadata.delta_path[:] = make_delta_path(RootContainer.MAIN, (), 1) rq.enqueue(DF_DELTA_MSG) ADD_ROWS_MSG.metadata.delta_path[:] = make_delta_path(RootContainer.MAIN, (), 1) rq.enqueue(ADD_ROWS_MSG) queue = rq.flush() self.assertEqual(len(queue), 3) self.assertTrue(queue[0].new_report.config.sharing_enabled) self.assertEqual( make_delta_path(RootContainer.MAIN, (), 0), queue[1].metadata.delta_path ) self.assertEqual(queue[1].delta.new_element.text.body, "text1") self.assertEqual( make_delta_path(RootContainer.MAIN, (), 1), queue[2].metadata.delta_path ) col0 = queue[2].delta.new_element.data_frame.data.cols[0].int64s.data col1 = queue[2].delta.new_element.data_frame.data.cols[1].int64s.data self.assertEqual(col0, [0, 1, 2, 3, 4, 5]) self.assertEqual(col1, [10, 11, 12, 13, 14, 15])
def assert_deltas(container: int, path: Tuple[int, ...], idx: int): # Text delta self.assertEqual(make_delta_path(container, path, 0), queue[idx].metadata.delta_path) self.assertEqual("text1", queue[idx].delta.new_element.text.body) # Dataframe delta self.assertEqual(make_delta_path(container, path, 1), queue[idx + 1].metadata.delta_path) col0 = queue[ idx + 1].delta.new_element.data_frame.data.cols[0].int64s.data col1 = queue[ idx + 1].delta.new_element.data_frame.data.cols[1].int64s.data self.assertEqual([0, 1, 2], col0) self.assertEqual([10, 11, 12], col1) # add_rows delta self.assertEqual(make_delta_path(container, path, 1), queue[idx + 2].metadata.delta_path) ar_col0 = queue[idx + 2].delta.add_rows.data.data.cols[0].int64s.data ar_col1 = queue[idx + 2].delta.add_rows.data.data.cols[1].int64s.data self.assertEqual([3, 4, 5], ar_col0) self.assertEqual([13, 14, 15], ar_col1)
def test_enqueue_three(self): rq = ReportQueue() self.assertTrue(rq.is_empty()) rq.enqueue(NEW_REPORT_MSG) TEXT_DELTA_MSG1.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0 ) rq.enqueue(TEXT_DELTA_MSG1) TEXT_DELTA_MSG2.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 1 ) rq.enqueue(TEXT_DELTA_MSG2) queue = rq.flush() self.assertEqual(len(queue), 3) self.assertTrue(queue[0].new_report.config.sharing_enabled) self.assertEqual( make_delta_path(RootContainer.MAIN, (), 0), queue[1].metadata.delta_path ) self.assertEqual(queue[1].delta.new_element.text.body, "text1") self.assertEqual( make_delta_path(RootContainer.MAIN, (), 1), queue[2].metadata.delta_path ) self.assertEqual(queue[2].delta.new_element.text.body, "text2")
def assert_deltas(container: RootContainer, path: Tuple[int, ...], idx: int): self.assertEqual( make_delta_path(container, path, 0), queue[idx].metadata.delta_path ) self.assertEqual("text1", queue[idx].delta.new_element.text.body) self.assertEqual( make_delta_path(container, path, 1), queue[idx + 1].metadata.delta_path ) col0 = queue[idx + 1].delta.new_element.data_frame.data.cols[0].int64s.data col1 = queue[idx + 1].delta.new_element.data_frame.data.cols[1].int64s.data self.assertEqual([0, 1, 2, 3, 4, 5], col0) self.assertEqual([10, 11, 12, 13, 14, 15], col1)
def enqueue_deltas(container: RootContainer, path: Tuple[int, ...]): # We deep-copy the protos because we mutate each one # multiple times. msg = copy.deepcopy(TEXT_DELTA_MSG1) msg.metadata.delta_path[:] = make_delta_path(container, path, 0) rq.enqueue(msg) msg = copy.deepcopy(DF_DELTA_MSG) msg.metadata.delta_path[:] = make_delta_path(container, path, 1) rq.enqueue(msg) msg = copy.deepcopy(ADD_ROWS_MSG) msg.metadata.delta_path[:] = make_delta_path(container, path, 1) rq.enqueue(msg)
def test_enqueue_two(self): rq = ForwardMsgQueue() self.assertTrue(rq.is_empty()) rq.enqueue(NEW_SESSION_MSG) TEXT_DELTA_MSG1.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0) rq.enqueue(TEXT_DELTA_MSG1) queue = rq.flush() self.assertEqual(len(queue), 2) self.assertEqual(make_delta_path(RootContainer.MAIN, (), 0), queue[1].metadata.delta_path) self.assertEqual(queue[1].delta.new_element.text.body, "text1")
def test_nested_with(self): with st.beta_container(): with st.beta_container(): st.markdown("Level 2 with") msg = self.get_message_from_queue() self.assertEqual( make_delta_path(RootContainer.MAIN, (0, 0), 0), msg.metadata.delta_path, ) st.markdown("Level 1 with") msg = self.get_message_from_queue() self.assertEqual( make_delta_path(RootContainer.MAIN, (0, ), 1), msg.metadata.delta_path, )
def test_enqueue_two(self): rq = ReportQueue() self.assertTrue(rq.is_empty()) rq.enqueue(INIT_MSG) TEXT_DELTA_MSG1.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0) rq.enqueue(TEXT_DELTA_MSG1) queue = rq.flush() self.assertEqual(len(queue), 2) self.assertTrue(queue[0].initialize.config.sharing_enabled) self.assertEqual(make_delta_path(RootContainer.MAIN, (), 0), queue[1].metadata.delta_path) self.assertEqual(queue[1].delta.new_element.text.body, "text1")
def test_container_paths(self): level3 = st.beta_container().beta_container().beta_container() level3.markdown("hi") level3.markdown("bye") msg = self.get_message_from_queue() self.assertEqual(make_delta_path(RootContainer.MAIN, (0, 0, 0), 1), msg.metadata.delta_path)
def test_with(self): # Same as test_container_paths, but using `with` syntax level3 = st.beta_container().beta_container().beta_container() with level3: st.markdown("hi") st.markdown("bye") msg = self.get_message_from_queue() self.assertEqual(make_delta_path(RootContainer.MAIN, (0, 0, 0), 1), msg.metadata.delta_path) # Now we're out of the `with` block, commands should use the main dg st.markdown("outside") msg = self.get_message_from_queue() self.assertEqual(make_delta_path(RootContainer.MAIN, (), 1), msg.metadata.delta_path)
def test_dont_replace_block(self, other_msg: ForwardMsg): """add_block deltas should never be replaced/composed because they can have dependent deltas later in the queue.""" rq = ReportQueue() self.assertTrue(rq.is_empty()) ADD_BLOCK_MSG.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0) other_msg.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0) # Delta messages should not replace `add_block` deltas with the # same delta_path. rq.enqueue(ADD_BLOCK_MSG) rq.enqueue(other_msg) queue = rq.flush() self.assertEqual(len(queue), 2) self.assertEqual(queue[0], ADD_BLOCK_MSG) self.assertEqual(queue[1], other_msg)
def test_replace_element(self): """Enqueuing an element with the same delta_path as another element already in the queue should replace the original element. """ rq = ForwardMsgQueue() self.assertTrue(rq.is_empty()) rq.enqueue(NEW_SESSION_MSG) TEXT_DELTA_MSG1.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0) rq.enqueue(TEXT_DELTA_MSG1) TEXT_DELTA_MSG2.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0) rq.enqueue(TEXT_DELTA_MSG2) queue = rq.flush() self.assertEqual(2, len(queue)) self.assertEqual(make_delta_path(RootContainer.MAIN, (), 0), queue[1].metadata.delta_path) self.assertEqual("text2", queue[1].delta.new_element.text.body)
def test_enqueue_three(self): """Enqueue 3 ForwardMsgs.""" rq = ForwardMsgQueue() self.assertTrue(rq.is_empty()) rq.enqueue(NEW_SESSION_MSG) TEXT_DELTA_MSG1.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0) rq.enqueue(TEXT_DELTA_MSG1) TEXT_DELTA_MSG2.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 1) rq.enqueue(TEXT_DELTA_MSG2) queue = rq.flush() self.assertEqual(3, len(queue)) self.assertEqual(make_delta_path(RootContainer.MAIN, (), 0), queue[1].metadata.delta_path) self.assertEqual("text1", queue[1].delta.new_element.text.body) self.assertEqual(make_delta_path(RootContainer.MAIN, (), 1), queue[2].metadata.delta_path) self.assertEqual("text2", queue[2].delta.new_element.text.body)
def test_add_rows_rerun(self): rq = ForwardMsgQueue() self.assertTrue(rq.is_empty()) rq.enqueue(NEW_SESSION_MSG) # Simulate rerun for i in range(2): TEXT_DELTA_MSG1.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0) rq.enqueue(TEXT_DELTA_MSG1) DF_DELTA_MSG.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 1) rq.enqueue(DF_DELTA_MSG) ADD_ROWS_MSG.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 1) rq.enqueue(ADD_ROWS_MSG) queue = rq.flush() self.assertEqual(5, len(queue)) # Text delta self.assertEqual(make_delta_path(RootContainer.MAIN, (), 0), queue[1].metadata.delta_path) self.assertEqual("text1", queue[1].delta.new_element.text.body) # Dataframe delta self.assertEqual(make_delta_path(RootContainer.MAIN, (), 1), queue[2].metadata.delta_path) col0 = queue[2].delta.new_element.data_frame.data.cols[0].int64s.data col1 = queue[2].delta.new_element.data_frame.data.cols[1].int64s.data self.assertEqual([0, 1, 2], col0) self.assertEqual([10, 11, 12], col1) # First add_rows delta self.assertEqual(make_delta_path(RootContainer.MAIN, (), 1), queue[3].metadata.delta_path) ar_col0 = queue[3].delta.add_rows.data.data.cols[0].int64s.data ar_col1 = queue[3].delta.add_rows.data.data.cols[1].int64s.data self.assertEqual([3, 4, 5], ar_col0) self.assertEqual([13, 14, 15], ar_col1) # Second add_rows delta self.assertEqual(make_delta_path(RootContainer.MAIN, (), 1), queue[4].metadata.delta_path) ar_col0 = queue[4].delta.add_rows.data.data.cols[0].int64s.data ar_col1 = queue[4].delta.add_rows.data.data.cols[1].int64s.data self.assertEqual([3, 4, 5], ar_col0) self.assertEqual([13, 14, 15], ar_col1)
def test_enqueue_same_id(self): cursor = LockedCursor(root_container=RootContainer.MAIN, index=123) dg = DeltaGenerator(root_container=RootContainer.MAIN, cursor=cursor) self.assertEqual(123, dg._cursor.index) test_data = "some test data" text_proto = TextProto() text_proto.body = test_data new_dg = dg._enqueue("text", text_proto) self.assertEqual(dg._cursor, new_dg._cursor) msg = self.get_message_from_queue() # The last element in delta_path is the delta's index in its container. self.assertEqual(make_delta_path(RootContainer.MAIN, (), 123), msg.metadata.delta_path) self.assertEqual(msg.delta.new_element.text.body, test_data)
def test_simple_add_rows(self): """'add_rows' messages should behave as expected.""" rq = ForwardMsgQueue() self.assertTrue(rq.is_empty()) rq.enqueue(NEW_SESSION_MSG) TEXT_DELTA_MSG1.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 0) rq.enqueue(TEXT_DELTA_MSG1) DF_DELTA_MSG.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 1) rq.enqueue(DF_DELTA_MSG) ADD_ROWS_MSG.metadata.delta_path[:] = make_delta_path( RootContainer.MAIN, (), 1) rq.enqueue(ADD_ROWS_MSG) queue = rq.flush() self.assertEqual(4, len(queue)) # Text delta self.assertEqual(make_delta_path(RootContainer.MAIN, (), 0), queue[1].metadata.delta_path) self.assertEqual("text1", queue[1].delta.new_element.text.body) # Dataframe delta self.assertEqual(make_delta_path(RootContainer.MAIN, (), 1), queue[2].metadata.delta_path) df_col0 = queue[2].delta.new_element.data_frame.data.cols[ 0].int64s.data df_col1 = queue[2].delta.new_element.data_frame.data.cols[ 1].int64s.data self.assertEqual([0, 1, 2], df_col0) self.assertEqual([10, 11, 12], df_col1) # AddRows delta self.assertEqual(make_delta_path(RootContainer.MAIN, (), 1), queue[3].metadata.delta_path) ar_col0 = queue[3].delta.add_rows.data.data.cols[0].int64s.data ar_col1 = queue[3].delta.add_rows.data.data.cols[1].int64s.data self.assertEqual([3, 4, 5], ar_col0) self.assertEqual([13, 14, 15], ar_col1)
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
from streamlit import RootContainer from streamlit.cursor import make_delta_path from streamlit.report_queue import ReportQueue from streamlit.elements import 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_REPORT_MSG = ForwardMsg() NEW_REPORT_MSG.new_report.config.sharing_enabled = True NEW_REPORT_MSG.new_report.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) DF_DELTA_MSG = ForwardMsg() data_frame.marshall_data_frame( {"col1": [0, 1, 2], "col2": [10, 11, 12]}, DF_DELTA_MSG.delta.new_element.data_frame ) DF_DELTA_MSG.metadata.delta_path[:] = make_delta_path(RootContainer.MAIN, (), 0) ADD_ROWS_MSG = ForwardMsg() data_frame.marshall_data_frame( {"col1": [3, 4, 5], "col2": [13, 14, 15]}, ADD_ROWS_MSG.delta.add_rows.data )
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.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) def _enqueue(report, msg): msg = copy.deepcopy(msg) msg.metadata.delta_path[-1] = len(list(report._master_queue))