Refactor: extract shared muted-footnote/stack render helpers#40
Merged
Conversation
The `usage` and `audit` commands each re-derived the same Rich idiom: build a primary view, optionally tack on a dim "Hidden: N … Use --flag to show them." note, and wrap the result in a `Group` (or return it bare when there's nothing to stack). This duplicated the Group/None branching and the `Text(..., style="aai.muted")` construction across both files. Add two small helpers to `output.py`: - `muted(text)` — a dim secondary line (empty-state messages, footnotes). - `stack(*items)` — combine renderables top-to-bottom, dropping None; a lone survivor is returned bare so a single table isn't wrapped in a redundant Group. Rewrite both command renderers in terms of them. Output is byte-identical (snapshot and command tests unchanged); this only removes the repeated composition logic.
The `usage` and `audit` commands each wrapped `timeparse.parse_iso_utc` in their own private parse/format helpers — `_parse_usage_timestamp` + `_format_usage_day` (calendar day) in account.py, and `_parse_time` + `_format_time` (YYYY-MM-DD HH:MM:SS) in audit.py — to turn an ISO string into a display value with a stringify-fallback for unparseable input. Lift the two display formatters next to the parser they build on: - `timeparse.format_utc_day(value)` -> "YYYY-MM-DD" - `timeparse.format_utc_datetime(value)` -> "YYYY-MM-DD HH:MM:SS" Both fall back to the stringified input (or "") when the value isn't a parseable timestamp. The commands now call these directly; their local parse/format helpers are gone. (audit's `_parse_time` stripped tzinfo only to feed strftime, which ignores it — so formatting the UTC datetime directly is byte-identical.) Output is unchanged; tests for the formatters move to test_timeparse.py.
`keys create` (without --project) resolved the account's first project id through three sequential guards — empty project list, unparseable first entry, missing/invalid id — each raising the identical "no project to create a key in" APIError inline in the command body. Extract `_default_project_id(account_id, jwt)` to fold all three into one helper that raises the single canonical error once. The command body drops to a one-line `pid = project_id if ... else _default_project_id(...)`. Behavior and error message are unchanged; existing tests cover all three failure branches plus both success paths.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The
usageandauditcommands each re-derived the same Rich idiom:build a primary view, optionally tack on a dim "Hidden: N … Use --flag to
show them." note, and wrap the result in a
Group(or return it bare whenthere's nothing to stack). This duplicated the Group/None branching and the
Text(..., style="aai.muted")construction across both files.Add two small helpers to
output.py:muted(text)— a dim secondary line (empty-state messages, footnotes).stack(*items)— combine renderables top-to-bottom, dropping None; a lonesurvivor is returned bare so a single table isn't wrapped in a redundant
Group.
Rewrite both command renderers in terms of them. Output is byte-identical
(snapshot and command tests unchanged); this only removes the repeated
composition logic.