docstr: Create a new session (or connect to an existing one) and return its unique ID.
  
  Parameters
  ----------
  client
      A concrete SessionClient implementation for communicating with
      the session's client.
  user_info
      A dict that contains information about the session's user. For now,
      it only (optionally) contains the user's email address.
  
      {
          "email": "example@example.com"
      }
  existing_session_id
      The ID of an existing session to reconnect to. If one is not provided, a new
      session is created. Note that whether the Runtime's SessionManager supports
      reconnecting to an existing session depends on the SessionManager that this
      runtime is configured with.
  session_id_override
      The ID to assign to a new session being created with this method. Setting
      this can be useful when the service that a Streamlit Runtime is running in
      wants to tie the lifecycle of a Streamlit session to some other session-like
      object that it manages. Only one of existing_session_id and
      session_id_override should be set.
  
  Returns
  -------
  str
      The session's unique string ID.
  
  Notes
  -----
  Threading: UNSAFE. Must be called on the eventloop thread.
code: def connect_session(
      self,
      client: SessionClient,
      user_info: Dict[str, Optional[str]],
      existing_session_id: Optional[str] = None,
      session_id_override: Optional[str] = None,
  ) -> str:
      """Create a new session (or connect to an existing one) and return its unique ID.
  
      Parameters
      ----------
      client
          A concrete SessionClient implementation for communicating with
          the session's client.
      user_info
          A dict that contains information about the session's user. For now,
          it only (optionally) contains the user's email address.
  
          {
              "email": "example@example.com"
          }
      existing_session_id
          The ID of an existing session to reconnect to. If one is not provided, a new
          session is created. Note that whether the Runtime's SessionManager supports
          reconnecting to an existing session depends on the SessionManager that this
          runtime is configured with.
      session_id_override
          The ID to assign to a new session being created with this method. Setting
          this can be useful when the service that a Streamlit Runtime is running in
          wants to tie the lifecycle of a Streamlit session to some other session-like
          object that it manages. Only one of existing_session_id and
          session_id_override should be set.
  
      Returns
      -------
      str
          The session's unique string ID.
  
      Notes
      -----
      Threading: UNSAFE. Must be called on the eventloop thread.
      """
      assert not (
          existing_session_id and session_id_override
      ), "Only one of existing_session_id and session_id_override should be set!"
  
      if self._state in (RuntimeState.STOPPING, RuntimeState.STOPPED):
          raise RuntimeStoppedError(
              f"Can't connect_session (state={self._state})"
          )
  
      session_id = self._session_mgr.connect_session(
          client=client,
          script_data=ScriptData(
              self._main_script_path, self._is_hello
          ),
          user_info=user_info,
          existing_session_id=existing_session_id,
          session_id_override=session_id_override,
      )
      self._set_state(RuntimeState.ONE_OR_MORE_SESSIONS_CONNECTED)
      self._get_async_objs().has_connection.set()
  
      return session_id
  
imports: from __future__ import annotations
  import asyncio
  import time
  import traceback
  from dataclasses import dataclass, field
  from enum import Enum
  from typing import TYPE_CHECKING, Awaitable, Dict, NamedTuple, Optional, Tuple, Type
  from typing_extensions import Final
  from streamlit import config
  from streamlit.logger import get_logger
  from streamlit.proto.BackMsg_pb2 import BackMsg
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
  from streamlit.runtime.app_session import AppSession
  from streamlit.runtime.caching import get_data_cache_stats_provider, get_resource_cache_stats_provider
  from streamlit.runtime.caching.storage.local_disk_cache_storage import LocalDiskCacheStorageManager
  from streamlit.runtime.forward_msg_cache import ForwardMsgCache, create_reference_msg, populate_hash_if_needed
  from streamlit.runtime.legacy_caching.caching import _mem_caches
  from streamlit.runtime.media_file_manager import MediaFileManager
  from streamlit.runtime.media_file_storage import MediaFileStorage
  from streamlit.runtime.memory_session_storage import MemorySessionStorage
  from streamlit.runtime.runtime_util import is_cacheable_msg
  from streamlit.runtime.script_data import ScriptData
  from streamlit.runtime.scriptrunner.script_cache import ScriptCache
  from streamlit.runtime.session_manager import ActiveSessionInfo, SessionClient, SessionClientDisconnectedError, SessionManager, SessionStorage
  from streamlit.runtime.state import SCRIPT_RUN_WITHOUT_ERRORS_KEY, SessionStateStatProvider
  from streamlit.runtime.stats import StatsManager
  from streamlit.runtime.uploaded_file_manager import UploadedFileManager
  from streamlit.runtime.websocket_session_manager import WebsocketSessionManager
  from streamlit.watcher import LocalSourcesWatcher
label_desc: Use image node_id 14 for calling the Runtime obj's underlying member method code with example usage: obj.connect_session(client, user_info, existing_session_id, session_id_override) and returns: session_id