Repository: streamlit/streamlit

Issue:
st_in_cache_warning test is not working
# Summary

st_in_cache_warning.py is not working as expected . The three different cached functions that should do a st.write() are not doing anything.

# Steps to reproduce

1. run `streamlit run e2e/scripts/st_in_cache_warning.py`
2. see

## Expected behavior:

We should see two different paragraphs and one button.

## Actual behavior:

I'm only seeing the message:
```
    If this is failing locally, it could be because you have a browser with
    Streamlit open. Close it and the test should pass.
```

## Is this a regression?

That is, did this use to work the way you expected in the past?
yes

# Additional information

https://4870-204086862-gh.circle-artifacts.com/0/frontend/cypress/videos/st_in_cache_warning.spec.ts.mp4


Discussion:

Resolving patch:
diff --git a/e2e/scripts/st_reuse_label.py b/e2e/scripts/st_reuse_label.py
--- a/e2e/scripts/st_reuse_label.py
+++ b/e2e/scripts/st_reuse_label.py
@@ -21,7 +21,7 @@
 if hasattr(st, "test_run_count"):
     st.test_run_count += 1
 else:
-    st.test_run_count = -1 if st.get_option("server.headless") else -2
+    st.test_run_count = 0 if st.get_option("server.headless") else -1
 
 if st.test_run_count < 1:
     w1 = st.slider("label", 0, 100, 25, 1)
diff --git a/lib/streamlit/ReportSession.py b/lib/streamlit/ReportSession.py
--- a/lib/streamlit/ReportSession.py
+++ b/lib/streamlit/ReportSession.py
@@ -45,6 +45,10 @@
 
 LOGGER = get_logger(__name__)
 
+# ID used to mark the script execution context that starts up before the first
+# browser connects.
+PREHEATED_ID = "PREHEATED_ID"
+
 
 class ReportSessionState(Enum):
     REPORT_NOT_RUNNING = "REPORT_NOT_RUNNING"
@@ -63,11 +67,16 @@ class ReportSession(object):
     A ReportSession is attached to each thread involved in running its Report.
     """
 
-    def __init__(self, ioloop, script_path, command_line, uploaded_file_manager):
+    def __init__(
+        self, is_preheat, ioloop, script_path, command_line, uploaded_file_manager
+    ):
         """Initialize the ReportSession.
 
         Parameters
         ----------
+        is_preheat : bool
+            True if this is the "preheated" session.
+
         ioloop : tornado.ioloop.IOLoop
             The Tornado IOLoop that we're running within.
 
@@ -82,7 +91,10 @@ def __init__(self, ioloop, script_path, command_line, uploaded_file_manager):
 
         """
         # Each ReportSession has a unique string ID.
-        self.id = str(uuid.uuid4())
+        if is_preheat:
+            self.id = PREHEATED_ID
+        else:
+            self.id = str(uuid.uuid4())
 
         self._ioloop = ioloop
         self._report = Report(script_path, command_line)
diff --git a/lib/streamlit/server/Server.py b/lib/streamlit/server/Server.py
--- a/lib/streamlit/server/Server.py
+++ b/lib/streamlit/server/Server.py
@@ -35,6 +35,7 @@
 from streamlit.ForwardMsgCache import ForwardMsgCache
 from streamlit.ForwardMsgCache import create_reference_msg
 from streamlit.ForwardMsgCache import populate_hash_if_needed
+from streamlit.ReportSession import PREHEATED_ID
 from streamlit.ReportSession import ReportSession
 from streamlit.UploadedFileManager import UploadedFileManager
 from streamlit.logger import get_logger
@@ -68,10 +69,6 @@
 }
 
 
-# Dictionary key used to mark the script execution context that starts
-# up before the first browser connects.
-PREHEATED_REPORT_SESSION = "PREHEATED_REPORT_SESSION"
-
 # When server.port is not available it will look for the next available port
 # up to MAX_PORT_SEARCH_RETRIES.
 MAX_PORT_SEARCH_RETRIES = 100
@@ -373,7 +370,8 @@ def _loop_coroutine(self, on_started=None):
                     session_infos = list(self._session_info_by_id.values())
 
                     for session_info in session_infos:
-                        if session_info.ws is PREHEATED_REPORT_SESSION:
+                        if session_info.ws is None:
+                            # Preheated.
                             continue
                         msg_list = session_info.session.flush_browser_queue()
                         for msg in msg_list:
@@ -488,7 +486,7 @@ def add_preheated_report_session(self):
         This is used to start running the user's script even before the first
         browser connects.
         """
-        session = self._create_report_session(PREHEATED_REPORT_SESSION)
+        session = self._create_report_session(ws=None)
         session.handle_rerun_script_request(is_preheat=True)
 
     def _create_report_session(self, ws):
@@ -496,8 +494,9 @@ def _create_report_session(self, ws):
 
         Parameters
         ----------
-        ws : _BrowserWebSocketHandler or PREHEATED_REPORT_SESSION
-            The newly-connected websocket handler.
+        ws : _BrowserWebSocketHandler or None
+            The newly-connected websocket handler or None if preheated
+            connection.
 
         Returns
         -------
@@ -505,14 +504,15 @@ def _create_report_session(self, ws):
             The newly-created ReportSession for this browser connection.
 
         """
-        if PREHEATED_REPORT_SESSION in self._session_info_by_id:
+        if PREHEATED_ID in self._session_info_by_id:
             assert len(self._session_info_by_id) == 1
             LOGGER.debug("Reusing preheated context for ws %s", ws)
-            session = self._session_info_by_id[PREHEATED_REPORT_SESSION].session
-            del self._session_info_by_id[PREHEATED_REPORT_SESSION]
+            session = self._session_info_by_id[PREHEATED_ID].session
+            del self._session_info_by_id[PREHEATED_ID]
         else:
             LOGGER.debug("Creating new context for ws %s", ws)
             session = ReportSession(
+                is_preheat=(ws is None),
                 ioloop=self._ioloop,
                 script_path=self._script_path,
                 command_line=self._command_line,
@@ -522,9 +522,10 @@ def _create_report_session(self, ws):
         assert session.id not in self._session_info_by_id, (
             "session.id '%s' registered multiple times!" % session.id
         )
+
         self._session_info_by_id[session.id] = SessionInfo(ws, session)
 
-        if ws is not PREHEATED_REPORT_SESSION:
+        if ws is not None:
             self._set_state(State.ONE_OR_MORE_BROWSERS_CONNECTED)
 
         return session


Test patch:
diff --git a/lib/tests/streamlit/ReportSession_test.py b/lib/tests/streamlit/ReportSession_test.py
--- a/lib/tests/streamlit/ReportSession_test.py
+++ b/lib/tests/streamlit/ReportSession_test.py
@@ -52,7 +52,7 @@ def get_option(name):
 
         patched_config.get_option.side_effect = get_option
 
-        rs = ReportSession(None, "", "", UploadedFileManager())
+        rs = ReportSession(False, None, "", "", UploadedFileManager())
         mock_script_runner = MagicMock()
         mock_script_runner._install_tracer = ScriptRunner._install_tracer
         rs._scriptrunner = mock_script_runner
@@ -88,7 +88,7 @@ def get_option(name):
 
         patched_config.get_option.side_effect = get_option
 
-        rs = ReportSession(None, "", "", UploadedFileManager())
+        rs = ReportSession(False, None, "", "", UploadedFileManager())
         mock_script_runner = MagicMock()
         rs._scriptrunner = mock_script_runner
 
@@ -108,7 +108,7 @@ def get_option(name):
     def test_shutdown(self, _1):
         """Test that ReportSession.shutdown behaves sanely."""
         file_mgr = MagicMock(spec=UploadedFileManager)
-        rs = ReportSession(None, "", "", file_mgr)
+        rs = ReportSession(False, None, "", "", file_mgr)
 
         rs.shutdown()
         self.assertEquals(ReportSessionState.SHUTDOWN_REQUESTED, rs._state)
@@ -123,8 +123,8 @@ def test_shutdown(self, _1):
     def test_unique_id(self, _1):
         """Each ReportSession should have a unique ID"""
         file_mgr = MagicMock(spec=UploadedFileManager)
-        rs1 = ReportSession(None, "", "", file_mgr)
-        rs2 = ReportSession(None, "", "", file_mgr)
+        rs1 = ReportSession(False, None, "", "", file_mgr)
+        rs2 = ReportSession(False, None, "", "", file_mgr)
         self.assertNotEquals(rs1.id, rs2.id)
 
 
@@ -144,7 +144,9 @@ class ReportSessionSerializationTest(tornado.testing.AsyncTestCase):
     def test_handle_save_request(self, _1):
         """Test that handle_save_request serializes files correctly."""
         # Create a ReportSession with some mocked bits
-        rs = ReportSession(self.io_loop, "mock_report.py", "", UploadedFileManager())
+        rs = ReportSession(
+            False, self.io_loop, "mock_report.py", "", UploadedFileManager()
+        )
         rs._report.report_id = "TestReportID"
 
         orig_ctx = get_report_ctx()