Module: lean_interact.sessioncache
This module implements the session cache classes responsible for storing and retrieving Lean proof states and environments.
Session cache is used internally by the AutoLeanServer class.
It enables efficient resumption of proofs and environments after server restarts, timeouts, and automated recover from crashes.
While by default AutoLeanServer instantiates a fresh PickleSessionCache instance, you can also use a custom one.
It can be useful to share a session cache between multiple AutoLeanServer instances, or to use a custom session cache implementation.
Examples:
    from lean_interact.sessioncache import PickleSessionCache
from lean_interact.server import AutoLeanServer
# Create a session cache
cache = PickleSessionCache(working_dir="./cache")
# Create a Lean server with the cache
server = AutoLeanServer(config=..., session_cache=cache)
            PickleSessionCache
PickleSessionCache(working_dir: str | PathLike)
            
              Bases: BaseSessionCache
        A session cache based on the local file storage and the REPL pickle feature.
                  
                    Source code in src/lean_interact/sessioncache.py
                    |  | def __init__(self, working_dir: str | PathLike):
    self._cache: dict[int, PickleSessionState] = {}
    self._state_counter = 0
    self._working_dir = Path(working_dir)
 | 
 
  
            add
add(
    lean_server: LeanServer,
    request: BaseREPLQuery,
    response: BaseREPLResponse,
    verbose: bool = False,
) -> int
            
              Source code in src/lean_interact/sessioncache.py
              |  | def add(
    self, lean_server: "LeanServer", request: BaseREPLQuery, response: BaseREPLResponse, verbose: bool = False
) -> int:
    self._state_counter -= 1
    process_id = os.getpid()  # use process id to avoid conflicts in multiprocessing
    hash_key = f"request_{type(request).__name__}_{id(request)}"
    pickle_file = (
        self._working_dir / "session_cache" / f"{hashlib.sha256(hash_key.encode()).hexdigest()}_{process_id}.olean"
    )
    pickle_file.parent.mkdir(parents=True, exist_ok=True)
    if isinstance(response, ProofStepResponse):
        repl_id = response.proof_state
        is_proof_state = True
        request = PickleProofState(proof_state=response.proof_state, pickle_to=str(pickle_file))
    elif isinstance(response, CommandResponse):
        repl_id = response.env
        is_proof_state = False
        request = PickleEnvironment(env=response.env, pickle_to=str(pickle_file))
    else:
        raise NotImplementedError(
            f"Cannot pickle the session state for unsupported request of type {type(request).__name__}."
        )
    # Use file lock when accessing the pickle file to prevent cache invalidation
    # from concurrent access
    with FileLock(f"{pickle_file}.lock", timeout=60):
        response_pickle = lean_server.run(request, verbose=verbose)
        if isinstance(response_pickle, LeanError):
            raise ValueError(
                f"Could not store the result in the session cache. The Lean server returned an error: {response_pickle.message}"
            )
        self._cache[self._state_counter] = PickleSessionState(
            session_id=self._state_counter,
            repl_id=repl_id,
            pickle_file=str(pickle_file),
            is_proof_state=is_proof_state,
        )
    return self._state_counter
 | 
 
     
 
            remove
remove(
    session_state_id: int, verbose: bool = False
) -> None
            
              Source code in src/lean_interact/sessioncache.py
              |  | def remove(self, session_state_id: int, verbose: bool = False) -> None:
    if (state_cache := self._cache.pop(session_state_id, None)) is not None:
        pickle_file = state_cache.pickle_file
        with FileLock(f"{pickle_file}.lock", timeout=60):
            if os.path.exists(pickle_file):
                os.remove(pickle_file)
 | 
 
     
 
            reload
reload(
    lean_server: LeanServer,
    timeout_per_state: int | float | None,
    verbose: bool = False,
) -> None
            
              Source code in src/lean_interact/sessioncache.py
              |  | def reload(self, lean_server: "LeanServer", timeout_per_state: int | float | None, verbose: bool = False) -> None:
    for state_data in self:
        # Use file lock when accessing the pickle file to prevent cache invalidation
        # from multiple concurrent processes
        with FileLock(
            f"{state_data.pickle_file}.lock", timeout=float(timeout_per_state) if timeout_per_state else -1
        ):
            if state_data.is_proof_state:
                cmd = UnpickleProofState(unpickle_proof_state_from=state_data.pickle_file, env=state_data.repl_id)
            else:
                cmd = UnpickleEnvironment(unpickle_env_from=state_data.pickle_file)
            result = lean_server.run(
                cmd,
                verbose=verbose,
                timeout=timeout_per_state,
            )
            if isinstance(result, LeanError):
                raise ValueError(
                    f"Could not reload the session cache. The Lean server returned an error: {result.message}"
                )
            elif isinstance(result, CommandResponse):
                state_data.repl_id = result.env
            elif isinstance(result, ProofStepResponse):
                state_data.repl_id = result.proof_state
            else:
                raise ValueError(
                    f"Could not reload the session cache. The Lean server returned an unexpected response: {result}"
                )
 | 
 
     
 
            is_empty
    
            
              Source code in src/lean_interact/sessioncache.py
              |  | def is_empty(self) -> bool:
    return len(self._cache) == 0
 | 
 
     
 
            clear
clear(verbose: bool = False) -> None
            
              Source code in src/lean_interact/sessioncache.py
              |  | def clear(self, verbose: bool = False) -> None:
    for state_data in list(self):
        self.remove(session_state_id=state_data.session_id, verbose=verbose)
    assert not self._cache, f"Cache is not empty after clearing: {self._cache}"
 | 
 
     
 
            keys
    
            
              Source code in src/lean_interact/sessioncache.py
              |  | def keys(self) -> list[int]:
    return list(self._cache.keys())
 | 
 
     
 
   
     
 
            SessionState
  
      dataclass
  
SessionState(
    session_id: int, repl_id: int, is_proof_state: bool
)
  
            session_id
  
      instance-attribute
  
    
    
 
            repl_id
  
      instance-attribute
  
    
    
 
            is_proof_state
  
      instance-attribute
  
    
    
 
   
     
 
            PickleSessionState
  
      dataclass
  
PickleSessionState(
    session_id: int,
    repl_id: int,
    is_proof_state: bool,
    pickle_file: str,
)
            
              Bases: SessionState
  
            pickle_file
  
      instance-attribute
  
    
    
 
            session_id
  
      instance-attribute
  
    
    
 
            repl_id
  
      instance-attribute
  
    
    
 
            is_proof_state
  
      instance-attribute