# System Patterns: hosts ## System Architecture ### Layered Architecture ``` ┌─────────────────────────────────────┐ │ TUI Layer │ ← User Interface (Textual) ├─────────────────────────────────────┤ │ Manager Layer │ ← Orchestration & Operations ├─────────────────────────────────────┤ │ Core Layer │ ← Business Logic ├─────────────────────────────────────┤ │ System Layer │ ← File I/O & DNS └─────────────────────────────────────┘ ``` ### Component Relationships #### TUI Layer (`src/hosts/tui/`) - **views.py**: Main application views and widgets - **Responsibilities**: User interaction, display logic, event handling - **Dependencies**: Manager layer for operations #### Manager Layer (`src/hosts/core/manager.py`) - **Responsibilities**: Coordinate operations, maintain application state - **Dependencies**: Core models, parser, DNS resolver - **Patterns**: Command pattern for operations, Observer for state changes #### Core Layer (`src/hosts/core/`) - **models.py**: Data structures (Entry, Comment, HostsFile) - **parser.py**: Hosts file parsing and serialization - **dns.py**: DNS resolution and IP comparison - **Responsibilities**: Pure business logic, no I/O dependencies #### System Layer - **File I/O**: Direct `/etc/hosts` file operations - **DNS Resolution**: Network calls for hostname resolution - **Permission Management**: Sudo privilege handling ## Key Technical Decisions ### Data Model Design ```python @dataclass class HostEntry: ip_address: str hostnames: list[str] comment: str | None = None is_active: bool = True dns_name: str | None = None # For CNAME-like functionality @dataclass class HostsFile: entries: list[HostEntry] header_comments: list[str] footer_comments: list[str] ``` ### State Management - **Immutable operations**: All modifications return new state - **Validation pipeline**: Every change goes through validation - **Undo/Redo capability**: Maintain operation history - **Dirty state tracking**: Know when changes need saving ### Permission Model ```python class PermissionManager: def __init__(self): self.edit_mode = False self.sudo_acquired = False def enter_edit_mode(self) -> bool: # Request sudo permissions # Set edit_mode = True only if successful def exit_edit_mode(self): # Release sudo permissions # Set edit_mode = False ``` ## Design Patterns in Use ### Command Pattern ```python class Command(ABC): @abstractmethod def execute(self) -> HostsFile: pass @abstractmethod def undo(self) -> HostsFile: pass class ToggleEntryCommand(Command): def __init__(self, entry_index: int): self.entry_index = entry_index def execute(self, hosts_file: HostsFile) -> HostsFile: # Toggle entry active state def undo(self, hosts_file: HostsFile) -> HostsFile: # Reverse the toggle ``` ### Observer Pattern ```python class HostsManager: def __init__(self): self.observers: list[Observer] = [] self.state: HostsFile = HostsFile() def notify_observers(self, event: StateChangeEvent): for observer in self.observers: observer.on_state_change(event) ``` ### Factory Pattern ```python class ParserFactory: @staticmethod def create_parser(file_path: str) -> HostsParser: # Return appropriate parser based on file format return StandardHostsParser(file_path) ``` ## Critical Implementation Paths ### Application Startup 1. **Initialize TUI**: Create Textual app instance 2. **Load hosts file**: Parse `/etc/hosts` in read-only mode 3. **Build UI**: Populate left pane with entries 4. **Enter main loop**: Handle user input and events ### Edit Mode Activation 1. **User triggers edit mode**: Keyboard shortcut or menu 2. **Request sudo**: Prompt for password if needed 3. **Validate permissions**: Ensure write access to `/etc/hosts` 4. **Update UI state**: Enable edit operations 5. **Maintain permissions**: Keep sudo active until exit ### Entry Modification 1. **User action**: Toggle, reorder, or edit entry 2. **Create command**: Instantiate appropriate command object 3. **Validate operation**: Check if change is valid 4. **Execute command**: Apply change to in-memory state 5. **Update UI**: Refresh display to show changes 6. **Track dirty state**: Mark file as needing save ### File Persistence 1. **User saves**: Explicit save command or auto-save 2. **Validate entire file**: Ensure no syntax errors 3. **Create backup**: Optional backup of original file 4. **Write atomically**: Use temporary file + rename 5. **Verify write**: Confirm file was written correctly ### DNS Resolution Flow 1. **User requests resolution**: For entry with DNS name 2. **Resolve hostname**: Use socket.gethostbyname() 3. **Compare IPs**: Current IP vs resolved IP 4. **Present choice**: Show user both options 5. **Update entry**: Apply user's choice 6. **Mark dirty**: Flag file for saving ## Error Handling Patterns ### Graceful Degradation - **Permission denied**: Fall back to read-only mode - **DNS resolution failure**: Show error but continue - **File corruption**: Load what's possible, warn user - **Network unavailable**: Disable DNS features ### User Feedback - **Status bar**: Show current mode and operation status - **Modal dialogs**: For errors requiring user attention - **Inline validation**: Real-time feedback on input - **Progress indicators**: For long-running operations ### Recovery Mechanisms - **Undo operations**: Allow reverting recent changes - **File restoration**: Restore from backup if available - **Safe mode**: Minimal functionality if errors occur - **Graceful exit**: Always attempt to save valid changes