class_docstr: Thread-safe wrapper around SessionState.
  
  When AppSession gets a re-run request, it can interrupt its existing
  ScriptRunner and spin up a new ScriptRunner to handle the request.
  When this happens, the existing ScriptRunner will continue executing
  its script until it reaches a yield point - but during this time, it
  must not mutate its SessionState.
class_docstr_tok: ["Thread-safe","wrapper","around","SessionState",".","When","AppSession","gets","a","re-run","request",",","it","can","interrupt","its","existing","ScriptRunner","and","spin","up","a","new","ScriptRunner","to","handle","the","request",".","When","this","happens",",","the","existing","ScriptRunner","will","continue","executing","its","script","until","it","reaches","a","yield","point","-","but","during","this","time",",","it","must","not","mutate","its","SessionState","."]
code: def on_script_will_rerun(
      self, latest_widget_states: WidgetStatesProto
  ) -> None:
      self._yield_callback()
      with self._lock:
          # TODO: rewrite this to copy the callbacks list into a local
          #  variable so that we don't need to hold our lock for the
          #  duration. (This will also allow us to downgrade our RLock
          #  to a Lock.)
          self._state.on_script_will_rerun(latest_widget_states)
  
imports: import threading
  from contextlib import contextmanager
  from typing import Any, Callable, Dict, Iterator, List, Optional, Set
  from streamlit.proto.WidgetStates_pb2 import WidgetState
  from streamlit.proto.WidgetStates_pb2 import WidgetStates
  from streamlit.runtime.state.common import RegisterWidgetResult, T, WidgetMetadata
  from streamlit.runtime.state.query_params import QueryParams
  from streamlit.runtime.state.session_state import SessionState
label_desc: Use image node_id 3 for calling the SafeSessionState obj's underlying member method code with example usage: obj.on_script_will_rerun(latest_widget_states) without return types