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
253
docs/user-guide.md
Normal file
253
docs/user-guide.md
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
# User guide
|
||||
|
||||
`hosts` is a keyboard-first terminal application for inspecting and editing the
|
||||
system Hosts File. It starts in Read-only Mode and requires explicit sudo
|
||||
authorization before it can change `/etc/hosts`.
|
||||
|
||||
> [!WARNING]
|
||||
> `hosts` is alpha software. Read [Persistence and recovery](#persistence-and-recovery)
|
||||
> before entering Privileged Mode. In particular, undo, redo, sorting, and save
|
||||
> failures can currently leave the interface and `/etc/hosts` out of sync.
|
||||
|
||||
## Before you begin
|
||||
|
||||
You need macOS or Linux, Python 3.13 or newer, `sudo`, and
|
||||
[uv](https://docs.astral.sh/uv/). The normal user entry point runs the current
|
||||
revision from the project's default branch:
|
||||
|
||||
```bash
|
||||
uvx git+https://git.s1q.dev/phg/hosts.git
|
||||
```
|
||||
|
||||
The project does not yet publish versioned releases. The `uvx` command can
|
||||
therefore run newer code on a later invocation.
|
||||
|
||||
## Inspect the Hosts File safely
|
||||
|
||||
The application opens in Read-only Mode. In this mode you can:
|
||||
|
||||
- select a Host Entry and inspect all of its hostnames, comment, state, and DNS
|
||||
details;
|
||||
- search by hostname, IP address, or comment;
|
||||
- sort by IP address or Canonical Hostname;
|
||||
- show or hide Default Entries from the configuration screen; and
|
||||
- reload `/etc/hosts` from disk.
|
||||
|
||||
The footer shows `Read-only` while system-file mutations are blocked. Press `?`
|
||||
for in-application help.
|
||||
|
||||
### A warning about sorting
|
||||
|
||||
Sorting is intended as a view operation, but currently reorders the in-memory
|
||||
Hosts File. If you later enter Privileged Mode and save or perform an auto-saved
|
||||
mutation, that sorted order can be written to `/etc/hosts`. Reload with `Ctrl+R`
|
||||
before entering Privileged Mode if you sorted only for inspection.
|
||||
|
||||
## Enter Privileged Mode
|
||||
|
||||
Press `Ctrl+E`. The application first checks for existing sudo authorization.
|
||||
If authorization is not already available, it asks for your password. Before
|
||||
enabling mutations it verifies write access and creates a Pre-edit Backup.
|
||||
|
||||
If authorization, permission validation, or backup creation fails, the
|
||||
application remains in Read-only Mode.
|
||||
|
||||
The footer shows `Edit` while Privileged Mode is active. This label refers to
|
||||
Privileged Mode; it is separate from the Entry Editor used to change one Host
|
||||
Entry.
|
||||
|
||||
## Change a Host Entry
|
||||
|
||||
In Privileged Mode:
|
||||
|
||||
- Press `n` to add a Host Entry.
|
||||
- Select a non-default Host Entry and press `e` to open the Entry Editor.
|
||||
- Press `d` and confirm to delete the selected Host Entry.
|
||||
- Press `Space` to activate or deactivate the selected Host Entry.
|
||||
- Press `Shift+Up` or `Shift+Down` to change its file order.
|
||||
|
||||
A Host Entry requires a valid IPv4 or IPv6 address, at least one valid hostname,
|
||||
and may include a comment. The first hostname is its Canonical Hostname; any
|
||||
additional hostnames are Aliases.
|
||||
|
||||
Default Entries represent protected baseline localhost or broadcasthost
|
||||
mappings. They cannot be changed, deleted, activated, deactivated, or moved.
|
||||
|
||||
Most successful mutations are saved to `/etc/hosts` immediately. Read the
|
||||
status message after every action. A message that reports a save failure means
|
||||
the interface may have changed while the system file did not.
|
||||
|
||||
## Use a DNS Entry
|
||||
|
||||
Choose the DNS Name Entry type when adding or editing an entry, then provide:
|
||||
|
||||
- the DNS name whose address should be resolved; and
|
||||
- one or more local hostnames that should map to that address.
|
||||
|
||||
The application resolves the DNS name in the background. A successful result
|
||||
replaces the entry's stored IP address, records DNS metadata in the serialized
|
||||
comment, activates a newly created DNS Entry, and saves the Hosts File. DNS
|
||||
refresh is manual rather than continuous:
|
||||
|
||||
- Press `r` to refresh the selected DNS Entry.
|
||||
- Press `Shift+R` to refresh all DNS Entries.
|
||||
|
||||
Both actions require Privileged Mode because a successful result changes
|
||||
`/etc/hosts`. A failed lookup reports the failure and keeps the previously
|
||||
stored mapping.
|
||||
|
||||
## Verify what is on disk
|
||||
|
||||
The details shown by the application normally match the last successful save,
|
||||
except for the known persistence cases below. To discard in-memory state and
|
||||
read `/etc/hosts` again, press `Ctrl+R`.
|
||||
|
||||
You can also inspect the file from another terminal:
|
||||
|
||||
```bash
|
||||
sed -n '1,240p' /etc/hosts
|
||||
```
|
||||
|
||||
Remember that saving is normalized rather than byte-preserving. The serializer
|
||||
aligns fields, groups comments, removes original blank-line placement, and adds
|
||||
a management header while retaining the modeled Host Entries and comments.
|
||||
|
||||
## Persistence and recovery
|
||||
|
||||
### What saves immediately
|
||||
|
||||
Adding, editing, deleting, moving, activating, deactivating, and successfully
|
||||
refreshing DNS Entries normally save immediately. `Ctrl+S` explicitly saves the
|
||||
entire current in-memory Hosts File.
|
||||
|
||||
### What does not save immediately
|
||||
|
||||
Undo and redo currently update the in-memory state without saving it. After
|
||||
`Ctrl+Z` or `Ctrl+Y`, use `Ctrl+S` if you want `/etc/hosts` to match the display.
|
||||
Reloading or quitting discards that unsaved in-memory result. Leaving
|
||||
Privileged Mode does not save it: the result remains displayed, but its
|
||||
undo/redo history is cleared and `/etc/hosts` still differs from the display.
|
||||
|
||||
A save failure can also leave the interface changed while the file on disk is
|
||||
unchanged. Reload with `Ctrl+R` to return the interface to the on-disk state
|
||||
before attempting another change.
|
||||
|
||||
### Locate a Pre-edit Backup
|
||||
|
||||
Entering Privileged Mode creates one timestamped Pre-edit Backup below the
|
||||
operating system's temporary directory. The application does not currently show
|
||||
this path. Ask Python for the directory used on your system:
|
||||
|
||||
```bash
|
||||
python3 -c 'import tempfile; print(tempfile.gettempdir() + "/hosts-manager-backups")'
|
||||
```
|
||||
|
||||
List the directory printed by that command. Backup files are named
|
||||
`hosts.backup.<timestamp>`:
|
||||
|
||||
```bash
|
||||
ls -lt /path/printed/by/the/previous/command
|
||||
```
|
||||
|
||||
The application does not remove old Pre-edit Backups, apply retention rules, or
|
||||
record which file belongs to a later session. Do not choose a backup solely
|
||||
because it is the newest; inspect its timestamp and contents first.
|
||||
|
||||
### Restore manually
|
||||
|
||||
Restoration is not available through the TUI. To restore manually:
|
||||
|
||||
1. Leave the application or return it to Read-only Mode.
|
||||
2. Locate and inspect the intended Pre-edit Backup.
|
||||
3. Copy that explicit file over `/etc/hosts` with sudo.
|
||||
4. Relaunch the application or press `Ctrl+R` to verify the restored contents.
|
||||
|
||||
For example, after replacing the placeholder with the exact file you inspected:
|
||||
|
||||
```bash
|
||||
sudo cp /exact/path/to/hosts.backup.TIMESTAMP /etc/hosts
|
||||
```
|
||||
|
||||
This replaces the current Hosts File. Never paste a guessed path or automate
|
||||
selection of the newest backup without inspecting it.
|
||||
|
||||
## Leave Privileged Mode
|
||||
|
||||
Press `Ctrl+E` again. The application clears its undo/redo history and forgets
|
||||
which Pre-edit Backup belongs to the session. The backup file remains in the
|
||||
temporary directory.
|
||||
|
||||
Leaving Privileged Mode currently runs `sudo -k`, which invalidates your cached
|
||||
sudo timestamp for other terminal sessions as well. This behavior is
|
||||
[tracked for removal](https://git.s1q.dev/phg/hosts/issues/4).
|
||||
|
||||
## Configuration
|
||||
|
||||
Press `c` to open configuration. The supported screen controls whether Default
|
||||
Entries are visible; they are hidden by default. The setting is stored at
|
||||
`~/.config/hosts-manager/config.json`.
|
||||
|
||||
Other values may exist in that file but are internal until their behavior is
|
||||
reachable through the TUI. Editing them manually is not a supported workflow.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Privileged Mode asks for a password
|
||||
|
||||
This is expected when no cached sudo authorization is available. Canceling the
|
||||
password prompt leaves the application in Read-only Mode.
|
||||
|
||||
### Privileged Mode cannot be enabled
|
||||
|
||||
The application requires all three safety gates: valid sudo authorization,
|
||||
write access to `/etc/hosts`, and successful creation of a Pre-edit Backup. A
|
||||
failure in any gate leaves mutations disabled. Read the status message for the
|
||||
specific failure.
|
||||
|
||||
### The display differs from `/etc/hosts`
|
||||
|
||||
This can occur after undo, redo, a failed save, or sorting followed by other
|
||||
actions. Press `Ctrl+R` to discard in-memory state and reload the file. If an
|
||||
unwanted change reached disk, follow the manual restoration procedure above.
|
||||
|
||||
### DNS resolution fails
|
||||
|
||||
DNS resolution uses the operating system resolver and a per-query timeout. A
|
||||
failure can result from an invalid DNS name, resolver failure, timeout, or no
|
||||
address being returned. The application reports the failure rather than
|
||||
continually retrying it.
|
||||
|
||||
## Key reference
|
||||
|
||||
### General
|
||||
|
||||
| Key | Action |
|
||||
| --- | --- |
|
||||
| `Up` / `Down` | Select a Host Entry |
|
||||
| `Home` / `End` | Select the first or last visible Host Entry |
|
||||
| `Page Up` / `Page Down` | Move by one page |
|
||||
| `i` | Sort by IP address |
|
||||
| `h` | Sort by Canonical Hostname |
|
||||
| `Ctrl+R` | Reload `/etc/hosts` |
|
||||
| `c` | Open configuration |
|
||||
| `?` | Show help |
|
||||
| `q` or `Ctrl+C` | Quit |
|
||||
| `Ctrl+E` | Enter or leave Privileged Mode |
|
||||
|
||||
### Privileged Mode
|
||||
|
||||
| Key | Action |
|
||||
| --- | --- |
|
||||
| `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 |
|
||||
| `Shift+Up` / `Shift+Down` | Move the selected Host Entry |
|
||||
| `r` | Refresh the selected DNS Entry |
|
||||
| `Shift+R` | Refresh all DNS Entries |
|
||||
| `Ctrl+Z` / `Ctrl+Y` | Undo or redo in memory |
|
||||
| `Ctrl+S` | Save the current in-memory state |
|
||||
|
||||
Within the Entry Editor, use `Tab` and `Shift+Tab` to move between fields and
|
||||
`Escape` to leave the form. If values changed, the application asks whether to
|
||||
save, discard, or continue editing.
|
||||
Loading…
Add table
Add a link
Reference in a new issue