class_docstr: SessionManagers are responsible for encapsulating all session lifecycle behavior
  that the Streamlit Runtime may care about.
  
  A SessionManager must define the following required methods:
    * __init__
    * connect_session
    * close_session
    * get_session_info
    * list_sessions
  
  SessionManager implementations may also choose to define the notions of active and
  inactive sessions. The precise definitions of active/inactive are left to the
  concrete implementation. SessionManagers that wish to differentiate between active
  and inactive sessions should have the required methods listed above operate on *all*
  sessions. Additionally, they should define the following methods for working with
  active sessions:
    * disconnect_session
    * get_active_session_info
    * is_active_session
    * list_active_sessions
  
  When active session-related methods are left undefined, their default
  implementations are the naturally corresponding required methods.
  
  The Runtime, unless there's a good reason to do otherwise, should generally work
  with the active-session versions of a SessionManager's methods. There isn't currently
  a need for us to be able to operate on inactive sessions stored in SessionStorage
  outside of the SessionManager itself. However, it's highly likely that we'll
  eventually have to do so, which is why the abstractions allow for this now.
  
  Notes
  -----
  Threading: All SessionManager methods are *not* threadsafe -- they must be called
  from the runtime's eventloop thread.
docstr: Create a new session or connect to an existing one.
  
  Parameters
  ----------
  client
      A concrete SessionClient implementation for communicating with
      the session's client.
  script_data
      Contains parameters related to running a script.
  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 a SessionManager supports reconnecting
      to an existing session is left up to the concrete SessionManager
      implementation. Those that do not support reconnection should simply ignore
      this argument.
  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.
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:
      """Create a new session or connect to an existing one.
  
      Parameters
      ----------
      client
          A concrete SessionClient implementation for communicating with
          the session's client.
      script_data
          Contains parameters related to running a script.
      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 a SessionManager supports reconnecting
          to an existing session is left up to the concrete SessionManager
          implementation. Those that do not support reconnection should simply ignore
          this argument.
      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.
      """
      raise NotImplementedError
  
imports: from abc import abstractmethod
  from dataclasses import dataclass
  from typing import Callable, Dict, List, Optional, cast
  from typing_extensions import Protocol
  from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
  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.uploaded_file_manager import UploadedFileManager
label_desc: Use image node_id 2 for calling the SessionManager obj's underlying member method code with example usage: obj.connect_session(client, script_data, user_info, existing_session_id, session_id_override) without return types