6.1 KiB
6.1 KiB
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
@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
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
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
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
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
- Initialize TUI: Create Textual app instance
- Load hosts file: Parse
/etc/hosts
in read-only mode - Build UI: Populate left pane with entries
- Enter main loop: Handle user input and events
Edit Mode Activation
- User triggers edit mode: Keyboard shortcut or menu
- Request sudo: Prompt for password if needed
- Validate permissions: Ensure write access to
/etc/hosts
- Update UI state: Enable edit operations
- Maintain permissions: Keep sudo active until exit
Entry Modification
- User action: Toggle, reorder, or edit entry
- Create command: Instantiate appropriate command object
- Validate operation: Check if change is valid
- Execute command: Apply change to in-memory state
- Update UI: Refresh display to show changes
- Track dirty state: Mark file as needing save
File Persistence
- User saves: Explicit save command or auto-save
- Validate entire file: Ensure no syntax errors
- Create backup: Optional backup of original file
- Write atomically: Use temporary file + rename
- Verify write: Confirm file was written correctly
DNS Resolution Flow
- User requests resolution: For entry with DNS name
- Resolve hostname: Use socket.gethostbyname()
- Compare IPs: Current IP vs resolved IP
- Present choice: Show user both options
- Update entry: Apply user's choice
- 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