Refactor test cases for improved readability and consistency
- Updated test_dns.py to enhance mock function definitions and improve spacing for better readability. - Modified test_filters.py to streamline assertions and ensure consistent formatting across test cases. - Cleaned up test_import_export.py by organizing imports and ensuring consistent formatting in CSV and JSON tests. - Improved test_main.py by refining mock setups and ensuring consistent error handling in assertions.
This commit is contained in:
parent
0710d10fac
commit
7872991e0b
42 changed files with 2376 additions and 2735 deletions
346
README.md
346
README.md
|
|
@ -1,277 +1,115 @@
|
|||
# hosts - /etc/hosts Manager
|
||||
# hosts
|
||||
|
||||
A modern Python TUI (Text User Interface) application for managing your system's `/etc/hosts` file with ease and safety.
|
||||
A keyboard-first terminal application for inspecting and editing `/etc/hosts`
|
||||
on macOS and Linux.
|
||||
|
||||
## Overview
|
||||
> [!WARNING]
|
||||
> `hosts` is alpha software. It can replace a system file using `sudo`, and
|
||||
> several recovery and persistence workflows still have known limitations.
|
||||
> Read the [user guide](docs/user-guide.md) before entering Privileged Mode.
|
||||
|
||||
The `hosts` application provides a powerful, user-friendly terminal interface for viewing, editing, and managing your `/etc/hosts` file. It eliminates the need for manual text editing while providing advanced features like DNS resolution, entry validation, and comprehensive backup capabilities.
|
||||

|
||||
|
||||
## Features
|
||||
## What it does
|
||||
|
||||
### 🔍 **Read-Only Mode (Default)**
|
||||
- **Two-pane interface**: List view with detailed entry information
|
||||
- **Smart parsing**: Handles all real-world hosts file formats
|
||||
- **Sorting capabilities**: Sort by IP address or hostname
|
||||
- **Filtering options**: Hide/show system default entries
|
||||
- **Search functionality**: Find entries by hostname, IP, or comment
|
||||
- **Configuration management**: Persistent settings with modal interface
|
||||
- **Live reload**: Automatically refresh when hosts file changes
|
||||
- Browses, searches, and sorts active and inactive Host Entries.
|
||||
- Hides or shows protected localhost and broadcasthost Default Entries.
|
||||
- Adds, edits, deletes, activates, deactivates, and reorders Host Entries.
|
||||
- Creates DNS Entries and manually refreshes their resolved IP addresses.
|
||||
- Gates every `/etc/hosts` mutation behind an explicit Privileged Mode.
|
||||
- Creates a timestamped Pre-edit Backup before Privileged Mode begins.
|
||||
- Supports undo and redo during the current Privileged Mode session.
|
||||
|
||||
### ✏️ **Edit Mode (Permission-Protected)**
|
||||
- **Safe editing**: Automatic backups before any modifications
|
||||
- **Entry management**: Add, delete, and modify host entries
|
||||
- **Activation control**: Toggle entries active/inactive
|
||||
- **Reordering**: Move entries up/down with keyboard shortcuts
|
||||
- **Undo/Redo system**: Full operation history with Ctrl+Z/Ctrl+Y
|
||||
- **Atomic operations**: Safe file writing with rollback capability
|
||||
- **Permission management**: Secure sudo handling for system file access
|
||||
The application starts in Read-only Mode. Default Entries cannot be edited,
|
||||
deleted, activated, deactivated, or moved.
|
||||
|
||||
### 🛡️ **Safety & Reliability**
|
||||
- **Automatic backups**: Timestamped backups before modifications
|
||||
- **Change detection**: Track modifications with save confirmation
|
||||
- **Input validation**: Comprehensive IP and hostname validation
|
||||
- **Error handling**: Graceful error recovery with user feedback
|
||||
- **File integrity**: Preserve comments and formatting
|
||||
## Requirements
|
||||
|
||||
## Installation
|
||||
- macOS or Linux with `/etc/hosts` and `sudo`
|
||||
- Python 3.13 or newer
|
||||
- [uv](https://docs.astral.sh/uv/)
|
||||
|
||||
### Prerequisites
|
||||
- Python 3.13 or higher
|
||||
- [uv](https://docs.astral.sh/uv/) package manager
|
||||
The project is designed for macOS and Linux, but does not yet publish a tested
|
||||
platform matrix.
|
||||
|
||||
## Run
|
||||
|
||||
The normal user entry point runs the current revision from the canonical
|
||||
Forgejo repository:
|
||||
|
||||
### Run with uv
|
||||
```bash
|
||||
uvx git+https://git.s1q.dev/phg/hosts.git
|
||||
```
|
||||
|
||||
### Setup alias
|
||||
> [!CAUTION]
|
||||
> This command follows the repository's default branch because the project does
|
||||
> not yet publish versioned releases. Review the current project state and known
|
||||
> limitations before granting sudo access.
|
||||
|
||||
Press `Ctrl+E` to enter Privileged Mode. The application uses an existing sudo
|
||||
authorization or asks for your password, then creates a Pre-edit Backup before
|
||||
enabling changes.
|
||||
|
||||
Start with the [user guide](docs/user-guide.md) for the complete workflow,
|
||||
including persistence behavior and manual recovery.
|
||||
|
||||
## Essential keys
|
||||
|
||||
| Key | Action |
|
||||
| --- | --- |
|
||||
| `Up` / `Down` | Select a Host Entry |
|
||||
| `Ctrl+E` | Enter or leave Privileged Mode |
|
||||
| `n` | Add a Host Entry |
|
||||
| `e` | Open the selected Host Entry in the Entry Editor |
|
||||
| `d` | Delete the selected Host Entry |
|
||||
| `Space` | Activate or deactivate the selected Host Entry |
|
||||
| `Ctrl+S` | Save the current in-memory state |
|
||||
| `?` | Show help |
|
||||
| `q` or `Ctrl+C` | Quit |
|
||||
|
||||
Mutating keys work only in Privileged Mode. See the
|
||||
[complete key reference](docs/user-guide.md#key-reference) for navigation,
|
||||
sorting, DNS refresh, movement, undo, and redo.
|
||||
|
||||
## Safety and known limitations
|
||||
|
||||
- Most successful mutations save immediately, but undo and redo currently
|
||||
change only the in-memory state until another save occurs.
|
||||
- Reloading discards unsaved in-memory state.
|
||||
- Sorting currently reorders the in-memory model; a later save can write that
|
||||
order to `/etc/hosts`. Treat sorting as unsafe before another mutation.
|
||||
- A failed save can leave the interface changed while `/etc/hosts` remains
|
||||
unchanged.
|
||||
- Pre-edit Backups are not listed or restored by the TUI and have no retention
|
||||
management. Manual recovery is documented in the user guide.
|
||||
- Leaving Privileged Mode currently invalidates the user's cached sudo
|
||||
timestamp. This is [tracked for removal](https://git.s1q.dev/phg/hosts/issues/4).
|
||||
- Serialization preserves Host Entries and comments semantically, but
|
||||
normalizes spacing, comment placement, and blank lines. It is not a
|
||||
byte-for-byte round trip.
|
||||
|
||||
Read [Persistence and recovery](docs/user-guide.md#persistence-and-recovery)
|
||||
before making system-file changes.
|
||||
|
||||
## Develop and contribute
|
||||
|
||||
Clone the repository for development:
|
||||
|
||||
```bash
|
||||
# Install uv if not already installed
|
||||
echo "alias hosts=\"uvx git+https://git.s1q.dev/phg/hosts.git\"" >> ~/.zshrc
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
```bash
|
||||
# Launch the application
|
||||
uvx git+https://git.s1q.dev/phg/hosts.git
|
||||
|
||||
# Or if you've setup the alias
|
||||
hosts
|
||||
```
|
||||
|
||||
### Interface Overview
|
||||
|
||||

|
||||
|
||||
### Keyboard Shortcuts
|
||||
|
||||
#### Navigation
|
||||
- `↑/↓`: Navigate entries
|
||||
- `Home/End`: Go to first/last entry
|
||||
- `Page Up/Down`: Navigate by page
|
||||
|
||||
#### View Operations
|
||||
- `Ctrl+e`: Toggle between Read-only and Edit mode
|
||||
- `Ctrl+r`: Reload hosts file
|
||||
- `i`: Sort by IP address
|
||||
- `h`: Sort by hostname
|
||||
- `c`: Open configuration modal
|
||||
- `q` or `Ctrl+C`: Quit application
|
||||
|
||||
#### Edit Mode (requires sudo)
|
||||
- `e`: Toggle Entry edit mode
|
||||
- `Space`: Toggle entry active/inactive
|
||||
- `Shift+↑/↓`: Move entry up/down
|
||||
- `n`: Add new entry
|
||||
- `d`: Delete selected entry
|
||||
- `r`: Update the current select DNS based Entry
|
||||
- `Shift+r`: Update all DNS based Entries
|
||||
- `Ctrl+z`: Undo last operation
|
||||
- `Ctrl+y`: Redo operation
|
||||
- `Ctrl+s`: Save changes
|
||||
|
||||
## Configuration
|
||||
|
||||
The application stores its configuration in `~/.config/hosts-manager/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"show_default_entries": true,
|
||||
"default_sort_column": "ip",
|
||||
"default_sort_reverse": false,
|
||||
"backup_directory": "~/.config/hosts-manager/backups"
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Options
|
||||
- **show_default_entries**: Show/hide system default entries (localhost, etc.)
|
||||
- **default_sort_column**: Default sorting column ("ip" or "hostname")
|
||||
- **default_sort_reverse**: Default sort direction
|
||||
- **backup_directory**: Location for automatic backups
|
||||
|
||||
## Architecture
|
||||
|
||||
The application follows a clean, layered architecture:
|
||||
|
||||
```
|
||||
src/hosts/
|
||||
├── main.py # Application entry point
|
||||
├── core/ # Business logic layer
|
||||
│ ├── models.py # Data models (HostEntry, HostsFile)
|
||||
│ ├── parser.py # File parsing and writing
|
||||
│ ├── manager.py # Edit operations and permissions
|
||||
│ ├── config.py # Configuration management
|
||||
│ ├── dns.py # DNS resolution (planned)
|
||||
│ ├── commands.py # Command pattern for undo/redo
|
||||
│ ├── filters.py # Entry filtering and search
|
||||
│ └── import_export.py # Data import/export utilities
|
||||
└── tui/ # User interface layer
|
||||
├── app.py # Main TUI application
|
||||
├── styles.py # Visual styling
|
||||
├── keybindings.py # Keyboard shortcuts
|
||||
└── *.py # Modal dialogs and components
|
||||
```
|
||||
|
||||
### Key Components
|
||||
|
||||
- **HostEntry**: Immutable data class representing a single hosts entry
|
||||
- **HostsFile**: Container managing collections of entries with operations
|
||||
- **HostsParser**: File I/O operations with atomic writing and backup
|
||||
- **HostsManager**: Edit mode operations with permission management
|
||||
- **HostsManagerApp**: Main TUI application with Textual framework
|
||||
|
||||
## Development
|
||||
|
||||
### Setup Development Environment
|
||||
```bash
|
||||
# Clone and enter directory
|
||||
git clone https://github.com/yourusername/hosts.git
|
||||
git clone https://git.s1q.dev/phg/hosts.git
|
||||
cd hosts
|
||||
|
||||
# Install development dependencies
|
||||
uv sync
|
||||
|
||||
# Run tests
|
||||
uv run pytest
|
||||
|
||||
# Run linting
|
||||
uv run ruff check
|
||||
uv run ruff format
|
||||
uv run hosts
|
||||
```
|
||||
|
||||
### Testing
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for code boundaries, safety contracts,
|
||||
tests, linting, and documentation expectations. Domain language lives in
|
||||
[CONTEXT.md](CONTEXT.md), and consequential design decisions live in
|
||||
[`docs/adr/`](docs/adr/).
|
||||
|
||||
The project maintains comprehensive test coverage with 150+ tests:
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
uv run pytest
|
||||
|
||||
# Run specific test modules
|
||||
uv run pytest tests/test_models.py
|
||||
uv run pytest tests/test_parser.py
|
||||
|
||||
# Run with coverage
|
||||
uv run pytest --cov=src/hosts
|
||||
```
|
||||
|
||||
### Test Coverage
|
||||
- **Models**: Data validation and serialization (27 tests)
|
||||
- **Parser**: File operations and parsing (15 tests)
|
||||
- **Manager**: Edit operations and permissions (38 tests)
|
||||
- **Configuration**: Settings persistence (22 tests)
|
||||
- **TUI Components**: User interface (28 tests)
|
||||
- **Commands**: Undo/redo system (43 tests)
|
||||
- **Integration**: End-to-end workflows (additional tests)
|
||||
|
||||
### Code Quality
|
||||
|
||||
The project uses `ruff` for linting and formatting:
|
||||
|
||||
```bash
|
||||
# Check code quality
|
||||
uv run ruff check
|
||||
|
||||
# Format code
|
||||
uv run ruff format
|
||||
|
||||
# Fix auto-fixable issues
|
||||
uv run ruff check --fix
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Sudo handling**: Secure elevation only when entering edit mode
|
||||
- **File validation**: Comprehensive input validation and sanitization
|
||||
- **Atomic operations**: Safe file writing to prevent corruption
|
||||
- **Backup system**: Automatic backups before any modifications
|
||||
- **Permission boundaries**: Clear separation between read and edit operations
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Permission denied when entering edit mode:**
|
||||
```bash
|
||||
# Ensure you can run sudo
|
||||
sudo -v
|
||||
|
||||
# Check file permissions
|
||||
ls -la /etc/hosts
|
||||
```
|
||||
|
||||
**Configuration not saving:**
|
||||
```bash
|
||||
# Ensure config directory exists
|
||||
mkdir -p ~/.config/hosts-manager
|
||||
|
||||
# Check directory permissions
|
||||
ls -la ~/.config/
|
||||
```
|
||||
|
||||
**Application won't start:**
|
||||
```bash
|
||||
# Check Python version
|
||||
python3 --version
|
||||
|
||||
# Verify uv installation
|
||||
uv --version
|
||||
|
||||
# Install dependencies
|
||||
uv sync
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions! Please see our development setup above.
|
||||
|
||||
### Contribution Guidelines
|
||||
|
||||
1. **Fork the repository** and create a feature branch
|
||||
2. **Write tests** for new functionality
|
||||
3. **Ensure all tests pass** with `uv run pytest`
|
||||
4. **Follow code style** with `uv run ruff check`
|
||||
5. **Submit a pull request** with clear description
|
||||
|
||||
### Future Enhancements
|
||||
|
||||
- **DNS Resolution**: Automatic hostname-to-IP resolution
|
||||
- **Import/Export**: Support for different file formats
|
||||
- **Advanced Filtering**: Complex search and filter capabilities
|
||||
- **Performance Optimization**: Large file handling improvements
|
||||
Report bugs and request features in the
|
||||
[Forgejo issue tracker](https://git.s1q.dev/phg/hosts/issues).
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||
|
||||
## Support
|
||||
|
||||
- **Issues**: Report bugs and feature requests on GitHub Issues
|
||||
- **Documentation**: See the [project wiki](https://github.com/yourusername/hosts/wiki)
|
||||
- **Discussions**: Join community discussions on GitHub Discussions
|
||||
|
||||
---
|
||||
|
||||
**Note**: This application modifies system files. Always ensure you have proper backups and understand the implications of hosts file changes. The application includes safety features, but system administration knowledge is recommended.
|
||||
Licensed under the [MIT License](./LICENSE).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue