class_docstr: A SessionManager used to manage sessions with lifecycles tied to those of a
  browser tab's websocket connection.
  
  WebsocketSessionManagers differentiate between "active" and "inactive" sessions.
  Active sessions are those with a currently active websocket connection. Inactive
  sessions are sessions without. Eventual cleanup of inactive sessions is a detail left
  to the specific SessionStorage that a WebsocketSessionManager is instantiated with.
class_docstr_tok: ["A","SessionManager","used","to","manage","sessions","with","lifecycles","tied","to","those","of","a","browser","tab","'s","websocket","connection",".","WebsocketSessionManagers","differentiate","between","``","active","''","and","``","inactive","''","sessions",".","Active","sessions","are","those","with","a","currently","active","websocket","connection",".","Inactive","sessions","are","sessions","without",".","Eventual","cleanup","of","inactive","sessions","is","a","detail","left","to","the","specific","SessionStorage","that","a","WebsocketSessionManager","is","instantiated","with","."]
code: def connect_session(
      self,
      client: SessionClient,
      script_data: ScriptData,
      user_info: Dict[str, Optional[str]],
      existing_session_id: Optional[str] = None,
      session_id_override: Optional[str] = None,
  ) -> str:
      assert not (
          existing_session_id and session_id_override
      ), "Only one of existing_session_id and session_id_override should be truthy"
  
      if existing_session_id in self._active_session_info_by_id:
          LOGGER.warning(
              "Session with id %s is already connected! Connecting to a new session.",
              existing_session_id,
          )
  
      session_info = (
          existing_session_id
          and existing_session_id not in self._active_session_info_by_id
          and self._session_storage.get(existing_session_id)
      )
  
      if session_info:
          existing_session = session_info.session
          existing_session.register_file_watchers()
  
          self._active_session_info_by_id[
              existing_session.id
          ] = ActiveSessionInfo(
              client,
              existing_session,
              session_info.script_run_count,
          )
          self._session_storage.delete(existing_session.id)
  
          return existing_session.id
  
      session = AppSession(
          script_data=script_data,
          uploaded_file_manager=self._uploaded_file_mgr,
          script_cache=self._script_cache,
          message_enqueued_callback=self._message_enqueued_callback,
          local_sources_watcher=LocalSourcesWatcher(
              script_data.main_script_path
          ),
          user_info=user_info,
          session_id_override=session_id_override,
      )
  
      LOGGER.debug(
          "Created new session for client %s. Session ID: %s",
          id(client),
          session.id,
      )
  
      assert (
          session.id not in self._active_session_info_by_id
      ), f"session.id '{session.id}' registered multiple times!"
  
      self._active_session_info_by_id[session.id] = ActiveSessionInfo(
          client, session
      )
      return session.id
  
imports: from typing import Callable, Dict, List, Optional, cast
  from typing_extensions import Final
  from streamlit.logger import get_logger
  from streamlit.runtime.app_session import AppSession
  from streamlit.runtime.script_data import ScriptData
  from streamlit.runtime.scriptrunner.script_cache import ScriptCache
  from streamlit.runtime.session_manager import ActiveSessionInfo, SessionClient, SessionInfo, SessionManager, SessionStorage
  from streamlit.runtime.uploaded_file_manager import UploadedFileManager
  from streamlit.watcher import LocalSourcesWatcher
label_desc: Use image node_id 2 for calling the WebsocketSessionManager obj's underlying member method code with example usage: obj.connect_session(client, script_data, user_info, existing_session_id, session_id_override) and returns: session, existing_session