The reviewer asked for a known-good interactive-menu library instead of
the custom termios/select key reader; arrow keys had failed in their
terminal. The TTY path now delegates to questionary.select (pointer ">",
bold highlight via pointer/selected styles), keeping choice values mapped
to list indices. Cancellable menus graft an eager Escape binding onto the
prompt's own key-binding registry so Esc backs out while Ctrl-C still
aborts fixed menus and backs out of cancellable ones. The non-TTY
numbered fallback is untouched, and hand-rolled internals
(_arrow_menu/_read_keypress/_option_line/_draw_menu_rows) are gone.
sys.stdin.read(1) on the buffered TextIOWrapper pulls the whole escape
sequence into its Python-level buffer, so the follow-up select() sees an
empty fd and every arrow/Home/End press degrades to bare Esc; the unread
'[B' tail then leaks into the next keypress. Read raw bytes via os.read()
and select() on the file descriptor instead, keeping the same key tokens
and classifications. Add pty-driven regression tests over a real cbreak
terminal covering CSI sequences, single-byte keys, bare Esc, and tail-leak.
wizard: when stdin and stdout are both TTYs, menus render inline and
are driven by keys: up/down/j/k/Home/End move the bold '>' highlight,
Enter accepts, Esc/Ctrl-C/q back out of cancellable menus while Ctrl-C
on fixed menus still aborts. Rows redraw with erase+CR across the
option block only and clear before returning so prompts stay aligned.
Non-TTY stdio keeps the original numbered prompt verbatim.
report: each configured source shows a transient "# Generating
report: pulling <name> data..." line that is erased on completion,
only when stdout is a TTY; piped output remains exactly the report.
tests: cover the numbered fallback, row rendering, status suppression
and show+clear parity; reformat stray test files to satisfy ruff.
Address review of PR #1 (Valentin): replace the linear config walk-through
and single-section schema.
- weekly-activity config becomes a menu loop: Current sources (masked) ->
Add a new source (pick kind, repeatable) / Remove a source / Exit; the
file is written only when something changed
- new versioned config layout (version = 2): [[kind.accounts]] arrays so
several accounts or instances per provider coexist; optional display
labels; strict unknown-key/type validation kept (errors carry account
position, e.g. [github.accounts[1]])
- legacy v1 files (no version key, one section per source) migrate
transparently in memory on load; saving from the wizard persists v2;
the file itself is never rewritten by load_config
- non-anonymous Launchpad accounts now authenticate at config time:
constructing LaunchpadSource runs launchpadlib's browser OAuth and the
token lands in the system keyring before any report; an explicit
credentials_file stays supported as an additive opt-out
- report aggregates every configured account in stable order with failure
isolation intact; headings add the account label when it disambiguates
(source_label shared between aggregate and wizard)
- GitHub accounts gain optional token_env resolved lazily against the
environment before falling back to GITHUB_TOKEN / `gh auth token`
New `bts` subcommand backed by python-debianbts (bugs.debian.org SOAP):
- Identify by email address: get_bugs(submitter=...) for bugs filed,
get_bugs(owner=...) for bugs owned
- Filed filtered on creation date, owned on log_modified; status
lookups capped at 500 bugs per collect
- Per-query failures degrade to warnings like other sources