SessionContext Frozen Dataclass

Maintains persistent state across shell executions β€” cwd, environment, and encoding.

πŸ” Overview

SessionContext is an immutable dataclass designed to hold the execution context for a shell or REPL environment across multiple command invocations. It preserves the current working directory, a dictionary of environment variables, and the active character encoding. Because the class is frozen (frozen=True), instances are hashable and thread‑safe, encouraging explicit state transitions via replacement or factory methods.

🎯 Primary responsibility: Encapsulate shell session state to ensure consistent behavior across sequential commands, preventing global variable side effects.

πŸ“¦ Class Definition

@dataclass(frozen=True)
class SessionContext:
    """Maintains persistent state across Shell executions."""
    
    cwd: Path = field(default_factory=Path.cwd)
    env: Dict[str, str] = field(default_factory=dict)
    encoding: str = "utf-8"

The frozen decorator guarantees immutability after construction. All fields are read‑only, making SessionContext ideal for functional updates or storing in caches.

ParameterTypeDescription
cwdPathCurrent working directory for shell commands. Defaults to the system's current working directory via Path.cwd().
envDict[str, str]Environment variables as key-value pairs. Initially an empty dictionary.
encodingstrCharacter encoding used for I/O operations (e.g., subprocess or file handling). Defaults to "utf-8".

✨ Immutability & Default Factories

field(default_factory=Path.cwd) ensures that each new instance computes a fresh cwd value at runtime, rather than sharing a single path reference. Similarly, env uses default_factory=dict to create independent environment dictionaries. Because the dataclass is frozen, you cannot mutate cwd or env after creation β€” any change produces a new instance.

πŸ“‹ Attributes & Field Behavior

The three primary attributes define the persistent session contract. Below you'll find deeper insight into each field:

cwd : Path

Current Working Directory – any relative paths executed in the shell will resolve relative to this directory. The default value is obtained via Path.cwd() at instantiation time, meaning each SessionContext captures the actual process working directory on creation. Frozen state guarantees that the working directory cannot be changed without creating a new context.

Path object Immutable

env : Dict[str, str]

Environment Variables Dictionary – stores key-value string pairs that represent shell environment variables. This dictionary is independent per instance (default factory ensures unique dict). For typical shell usage, this may include PATH, HOME, or custom variables. Because the context is frozen, the dictionary is also read‑only; to update environment variables you must create a new context (e.g., using replace or by constructing a fresh instance).

Dict[str, str] – mutable default factory but frozen wrapper prevents direct mutation

encoding : str

Character Encoding – defines the text encoding for standard streams, file I/O, and subprocess communication. The default is "utf-8", the modern standard. Changing the encoding allows compatibility with legacy systems or different locales.

Literal string – recommended values: 'utf-8', 'latin-1', 'cp1252'

πŸ“Œ Field Summary

FieldTypeDefaultImmutability
cwdPathPath.cwd() (dynamic)Frozen β†’ read-only
envDict[str, str]{} (new dict per instance)Frozen β†’ read-only
encodingstr"utf-8"Frozen β†’ read-only

βš™οΈ Usage Examples

Typical patterns for constructing and β€œupdating” a SessionContext in a persistent shell environment. Since the class is frozen, modifications produce new instances β€” this aligns with functional state management.

πŸ“Œ Basic instantiation

from pathlib import Path
from dataclasses import dataclass, field
from typing import Dict

# Assuming SessionContext definition from above
initial_context = SessionContext()
print(initial_context.cwd)      # /current/working/directory
print(initial_context.env)      # {}
print(initial_context.encoding) # utf-8

πŸ“Œ Custom session with specific working directory & env

custom_env = {"EDITOR": "vim", "LANG": "en_US.UTF-8"}
project_context = SessionContext(
    cwd=Path("/home/user/projects/myapp"),
    env=custom_env,
    encoding="utf-8"
)
# Access fields
print(project_context.env["EDITOR"])  # vim

πŸ“Œ Updating context (immutable approach)

Because frozen=True disables direct assignment, use dataclasses.replace or construct new contexts:

from dataclasses import replace

# create new context with changed cwd
old_ctx = SessionContext(cwd=Path("/initial/path"))
new_ctx = replace(old_ctx, cwd=Path("/new/workspace"))

print(old_ctx.cwd)  # /initial/path
print(new_ctx.cwd)  # /new/workspace

# To update environment variables, merge and create a fresh instance
updated_env = {**old_ctx.env, "NEW_VAR": "value"}
refreshed_ctx = replace(old_ctx, env=updated_env)

πŸ“Œ Shell REPL state machine pattern

class ShellExecutor:
    def __init__(self, context: SessionContext):
        self._context = context

    def run_command(self, cmd: str) -> str:
        # use self._context.cwd, self._context.env, self._context.encoding
        # simulate execution ...
        return f"Executed '{cmd}' in {self._context.cwd}"

    def change_directory(self, new_path: Path) -> 'ShellExecutor':
        new_ctx = replace(self._context, cwd=new_path)
        return ShellExecutor(new_ctx)

# usage:
shell = ShellExecutor(SessionContext())
shell = shell.change_directory(Path("/var/log"))

🧠 Behavior & Design Notes

πŸ”’ Immutability Guarantees: The @dataclass(frozen=True) decorator makes the class hashable and prevents accidental mutation. However, note that the env dictionary itself is a mutable container; the frozen dataclass only prevents reassigning env attribute. To preserve deep immutability, avoid mutating the dictionary after creation β€” instead always replace the entire env via a new instance.

πŸ“Œ Advanced considerations

Environment variable fallback: While the env dictionary is empty by default, in a real shell you may want to pre‑populate it with os.environ.copy(). The design intentionally leaves this decision to the caller, making the context lightweight.

Encoding validation: The encoding attribute is a simple string; consumers should validate against Python's codecs.lookup() if needed. The class does not perform runtime checks to keep overhead minimal.

πŸ”„ Relationship with Shell Executor

SessionContext is meant to be used as an immutable state carrier for a shell loop or command processor. Instead of mutating global state, each command can receive the current context and optionally return a new context for the next iteration. This reduces bugs and makes history/replay possible.

πŸ“– API Reference Summary

Class: SessionContext (frozen dataclass)
Module: shell.context (assumed)
Since: core shell abstraction

@dataclass(frozen=True) ensures the shell session state is predictable. For any modifications, the consumer must produce a new instance β€” enabling clean rollback and snapshot capabilities.

See also: dataclasses.replace utility to create modified copies without boilerplate.