Skip to content

Add interactive target and port selection to sync.py and port listing to detect_boards.py#333

Open
Copilot wants to merge 4 commits intomainfrom
copilot/add-list-pico-ports-feature
Open

Add interactive target and port selection to sync.py and port listing to detect_boards.py#333
Copilot wants to merge 4 commits intomainfrom
copilot/add-list-pico-ports-feature

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

Description

Quality-of-life improvements for the dev workflow, similar in spirit to #278:

  • detect_boards.py list — runs list_pico_ports() and prints one port per line. Default behavior (no args) unchanged.
  • Interactive hardware target selection in sync.py — when no system argument is provided (e.g. just python dev/sync.py), discovers available hardware targets from src/ and prompts the user to select one interactively.
  • Interactive port selection in sync.py — when no port is specified, lists detected Pico ports and prompts for selection. Auto-selects if only one port is connected. Falls through to flash.py autodetect if no ports are found.
  • Reusable interactive_select(label, options) — minimal shared function used by both target and port selection. Auto-selects single options, handles cancel/invalid input gracefully.
  • OSError handlinglist_pico_ports() now catches OSError (e.g. mpremote not installed) and returns an empty list instead of raising an unhandled traceback.
# List connected Pico ports
./dev/detect_boards.py list

# Fully interactive (no args) — prompts for target then port
python dev/sync.py
# Available targets:
#   1) data_east
#   2) em
#   3) sys11
#   4) whitestar
#   5) wpc
# Select a target [1]: 3
# Available ports:
#   1) /dev/ttyACM0
#   2) /dev/ttyACM1
# Select a port [1]:

# Interactive port selection only (target specified, no port)
python dev/sync.py sys11
# Available ports:
#   1) /dev/ttyACM0
#   2) /dev/ttyACM1
# Select a port [1]:

Related Issues

Motivation and Context

Specifying a port manually is faster than auto (which queries board type for every port), but requires knowing the port name. Running with no args previously defaulted to dev which isn't a valid hardware target. Now, running sync.py with no arguments gives a fully guided interactive experience — pick your target, pick your port, and go.

Testing

  • Verified detect_boards.py default (no-arg) behavior preserved
  • Verified list subcommand prints ports
  • Verified sync.py interactive target selection: discovers targets from src/, handles single target (auto-select), multiple targets (prompt), no targets (error)
  • Verified sync.py interactive port selection: single port (auto-select), multiple ports (prompt), no ports (falls through to flash.py autodetect)
  • Verified invalid input, EOF, and Ctrl+C are handled gracefully for both menus
  • Verified explicit system/port args still work as before (e.g. python dev/sync.py sys11 /dev/ttyACM0)

Screenshots (if applicable)

Types of Changes

  • Bug fix (non-breaking change to resolve an issue)
  • New feature (non-breaking change to add functionality)
  • Breaking change (alters existing functionality)
  • Documentation update required

Checklist

  • My code follows the project's style guidelines.
  • I have updated documentation as needed.
  • I have read the CONTRIBUTING.md document.
  • I have added or updated tests.
  • All new and existing tests pass.

Additional Notes

Backward-compatible: all existing imports from detect_boards and explicit sync.py argument patterns (e.g. sync.py sys11 /dev/ttyACM0, sync.py auto) continue to work identically. The only behavioral change is that running sync.py with no arguments now prompts interactively instead of defaulting to the dev target.

…sync.py

- detect_boards.py: when run as `./dev/detect_boards.py list`, calls
  list_pico_ports() and prints each port on its own line. Default
  behavior (no args) is preserved.
- sync.py: when a target system is specified but no port is given
  (and not 'auto'), detects connected ports and lets the user
  interactively select one. Auto-selects if only one port is found.

Agent-Logs-Url: https://github.com/warped-pinball/vector/sessions/70888ab8-6f09-44ed-97c2-723f949eb5c0

Co-authored-by: mullinmax <14000345+mullinmax@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 5, 2026

Developer build links:
Sys11

https://raw.githubusercontent.com/warped-pinball/vector/pr-update-artifacts/pr-artifacts/pr-333/sys11-update.json

Sys11 (Tiny)

https://raw.githubusercontent.com/warped-pinball/vector/pr-update-artifacts/pr-artifacts/pr-333/sys11-tiny-update.json

WPC

https://raw.githubusercontent.com/warped-pinball/vector/pr-update-artifacts/pr-artifacts/pr-333/wpc-update.json

EM

https://raw.githubusercontent.com/warped-pinball/vector/pr-update-artifacts/pr-artifacts/pr-333/em-update.json

WhiteStar

https://raw.githubusercontent.com/warped-pinball/vector/pr-update-artifacts/pr-artifacts/pr-333/whitestar-update.json

DataEast

https://raw.githubusercontent.com/warped-pinball/vector/pr-update-artifacts/pr-artifacts/pr-333/data-east-update.json

@mullinmax mullinmax marked this pull request as ready for review April 6, 2026 01:20
Copilot AI review requested due to automatic review settings April 6, 2026 01:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the developer flashing workflow by adding a simple “list ports” mode to detect_boards.py and introducing interactive serial-port selection in sync.py when no port is provided, reducing the need to manually discover /dev/tty* names.

Changes:

  • Add dev/detect_boards.py list to print detected Pico serial ports (one per line).
  • Update dev/sync.py to auto-select the only detected port or prompt the user to choose among multiple detected ports when port is omitted.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
dev/sync.py Adds port autodetection + interactive selection when no port argument is provided.
dev/detect_boards.py Adds a list CLI mode to print ports returned by list_pico_ports().

Comment thread dev/sync.py Outdated
Comment on lines +67 to +73
if not ports:
print("No boards detected.")
return 1
if len(ports) == 1:
port = ports[0]
print(f"Using detected port: {port}")
else:
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When port is omitted, this now hard-depends on list_pico_ports()/mpremote devs and aborts with "No boards detected." if it returns an empty list. That’s a behavioral change from the previous flow (which let dev/flash.py run its own autodetect via mpremote connect list) and can become a false-negative on environments where mpremote devs isn’t supported or fails transiently. Consider only prompting when list_pico_ports() returns >1, and otherwise fall back to passing port=None through to flash_single() so flash.py’s autodetect/error messaging remains the source of truth.

Suggested change
if not ports:
print("No boards detected.")
return 1
if len(ports) == 1:
port = ports[0]
print(f"Using detected port: {port}")
else:
if len(ports) == 1:
port = ports[0]
print(f"Using detected port: {port}")
elif len(ports) > 1:

Copilot uses AI. Check for mistakes.
Comment thread dev/sync.py
rc = flash_single(args.system, args.port, args.write_config)
port = args.port
if port is None:
ports = list_pico_ports()
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

list_pico_ports() uses subprocess.run(["mpremote", ...]) and doesn’t catch FileNotFoundError/OSError when mpremote isn’t installed or isn’t on PATH. With this new code path, that can surface as an unhandled traceback instead of a clean CLI error. Wrap the list_pico_ports() call in a try/except (or update list_pico_ports() to handle OSError) and print a clear message + non-zero exit.

Suggested change
ports = list_pico_ports()
try:
ports = list_pico_ports()
except OSError as exc:
print(f"Unable to detect Pico ports. Ensure mpremote is installed and available on PATH. ({exc})")
return 1

Copilot uses AI. Check for mistakes.
@mullinmax
Copy link
Copy Markdown
Contributor

@copilot if the user doesn't specify a target hardware (and does not use "auto") also list the target hardware options and allow the user to interactively select them the way we do for ports. Make the interactive menu functionality into a reuseable function that's minimal.

- Extract interactive_select(label, options) as a reusable menu function
- Add list_hardware_targets() to discover targets from src/ directory
- When no system arg is given, prompt user to select a hardware target
- When no port arg is given, prompt user to select from detected ports
  (falls through to flash.py autodetect if no ports found)
- Handle OSError in list_pico_ports() for missing mpremote

Agent-Logs-Url: https://github.com/warped-pinball/vector/sessions/2c1e83f8-c05f-4331-9376-3901ba80bd53

Co-authored-by: mullinmax <14000345+mullinmax@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 6, 2026

@copilot if the user doesn't specify a target hardware (and does not use "auto") also list the target hardware options and allow the user to interactively select them the way we do for...

Done in 321cf6a. When no system is specified, sync.py now discovers hardware targets from src/ and prompts with the same interactive menu used for ports.

Both menus use a shared interactive_select(label, options) function that auto-selects when there's only one option and handles invalid input/cancel gracefully.

Example flow with no args:

$ python dev/sync.py
Available targets:
  1) data_east
  2) em
  3) sys11
  4) whitestar
  5) wpc
Select a target [1]:

Copilot AI changed the title Add port listing to detect_boards.py and interactive port selection to sync.py Add interactive target and port selection to sync.py and port listing to detect_boards.py Apr 6, 2026
Copilot AI requested a review from mullinmax April 6, 2026 01:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants