mpfaffenberger / mpfaffenberger/code_puppy

tools/common.py: get_user_approval sync/async are 150-line copy-pastes that have already diverged (async feedback prompt missing suspended_key_listener; sync arrow_select missing html escaping)

Open
#437 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
814
Forks
278
Avg merge
2d 5h
Merged PRs (30d)
76

Description

Files:

  • code_puppy/tools/common.py - get_user_approval() / _get_user_approval_impl() (~lines 1095-1290) vs get_user_approval_async() / _get_user_approval_async_impl() (~lines 1295-1480)
  • code_puppy/tools/common.py - arrow_select() (~line 998) vs arrow_select_async() (~line 870)

Severity: Medium (DRY / divergence already happening)

The sync and async approval flows are ~150-line near-verbatim copies of each other: identical panel construction, identical spinner pause/resume, identical feedback prompt, identical finally-block console resets. Same story for the two arrow selectors.

They have already diverged in subtle ways:

  1. The sync impl wraps the feedback Prompt.ask in suspended_key_listener(); the async impl does not (line ~1437) - so in the async path the background key listener can still eat keystrokes typed into the feedback prompt, exactly the bug the sync path fixed.
  2. arrow_select_async html-escapes message/choices and supports preview_callback; arrow_select does neither, so markup-looking characters in choices will break only the sync selector.

Also Zen-of-Python nits in both copies:

  • except (ImportError, Exception): pass (4 occurrences) - Exception already subsumes ImportError; this is just a disguised except Exception: pass.
  • time.sleep(0.3) / asyncio.sleep(0.3) "Let spinners fully stop" magic delays.

Suggested fix: implement the flow once async, and make the sync wrapper drive it (asyncio.run when no loop is running - which is the only situation the sync variant is valid in anyway, per its own RuntimeError guard). Extract panel construction + result rendering into shared helpers so the remaining sync/async difference is just the two sleep/arrow_select calls. Apply the suspended_key_listener fix to the async feedback prompt now, regardless.

Filed by Zen Reviewer B (code-puppy-60635a)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read code_puppy/tools/common.py, starting with arrow_select_async(), arrow_select(), and the sync and async get_user_approval implementations. Compare their shared panel, feedback, spinner, and reset behavior; done means the duplicated flow is consolidated, the async feedback prompt suspends the key listener, and both selectors retain the async escaping and preview behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.