From 58ba72500a9dbc5a944e2c046c681cd727fc94cc Mon Sep 17 00:00:00 2001 From: shaggy Date: Sun, 19 Oct 2025 20:03:00 -0500 Subject: [PATCH 1/9] add the ability to change the target file in the --stay-connected menu --- pybricksdev/cli/__init__.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pybricksdev/cli/__init__.py b/pybricksdev/cli/__init__.py index a499bd3..6e07e16 100644 --- a/pybricksdev/cli/__init__.py +++ b/pybricksdev/cli/__init__.py @@ -262,6 +262,7 @@ async def reconnect_hub(): return hub response_options = [ + "Change Target File", "Recompile and Run", "Recompile and Download", "Exit", @@ -292,8 +293,18 @@ async def reconnect_hub(): ) with _get_script_path(args.file) as script_path: if response == response_options[0]: - await hub.run(script_path, wait=True) + args.file = os.path.abspath( + await hub.race_disconnect( + hub.race_power_button_press( + questionary.path( + "What file would you like to use?" + ).ask_async() + ) + ) + ) elif response == response_options[1]: + await hub.run(script_path, wait=True) + elif response == response_options[2]: await hub.download(script_path) else: return From 98a6659859393cc5f16689cbec71a3c395a3dec1 Mon Sep 17 00:00:00 2001 From: shaggy Date: Mon, 20 Oct 2025 14:35:52 -0500 Subject: [PATCH 2/9] fix to open the file properly as a stream as _get_script_path expects --- pybricksdev/cli/__init__.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pybricksdev/cli/__init__.py b/pybricksdev/cli/__init__.py index 6e07e16..23f1d3f 100644 --- a/pybricksdev/cli/__init__.py +++ b/pybricksdev/cli/__init__.py @@ -284,21 +284,23 @@ async def reconnect_hub(): "Would you like to re-compile your code?", response_options, default=( - response_options[0] + response_options[1] if args.start - else response_options[1] + else response_options[2] ), ).ask_async() ) ) with _get_script_path(args.file) as script_path: if response == response_options[0]: - args.file = os.path.abspath( - await hub.race_disconnect( - hub.race_power_button_press( - questionary.path( - "What file would you like to use?" - ).ask_async() + args.file = open( + os.path.abspath( + await hub.race_disconnect( + hub.race_power_button_press( + questionary.path( + "What file would you like to use?" + ).ask_async() + ) ) ) ) From 1eb8056871dfa213de86f386f27eb03c1c55e4ab Mon Sep 17 00:00:00 2001 From: shaggy Date: Mon, 20 Oct 2025 16:15:45 -0500 Subject: [PATCH 3/9] display the current file in the re-compile menu --- pybricksdev/cli/__init__.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/pybricksdev/cli/__init__.py b/pybricksdev/cli/__init__.py index 23f1d3f..8a9f7a1 100644 --- a/pybricksdev/cli/__init__.py +++ b/pybricksdev/cli/__init__.py @@ -281,7 +281,7 @@ async def reconnect_hub(): response = await hub.race_disconnect( hub.race_power_button_press( questionary.select( - "Would you like to re-compile your code?", + f"Would you like to re-compile {os.path.basename(args.file.name)}?", response_options, default=( response_options[1] @@ -294,13 +294,11 @@ async def reconnect_hub(): with _get_script_path(args.file) as script_path: if response == response_options[0]: args.file = open( - os.path.abspath( - await hub.race_disconnect( - hub.race_power_button_press( - questionary.path( - "What file would you like to use?" - ).ask_async() - ) + await hub.race_disconnect( + hub.race_power_button_press( + questionary.path( + "What file would you like to use?" + ).ask_async() ) ) ) From 8e89cfbeeb1f09399164d62b5d459cd1e6c67871 Mon Sep 17 00:00:00 2001 From: shaggy Date: Mon, 20 Oct 2025 16:42:26 -0500 Subject: [PATCH 4/9] close the old file prior to opening a new one --- pybricksdev/cli/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pybricksdev/cli/__init__.py b/pybricksdev/cli/__init__.py index 8a9f7a1..b32ec82 100644 --- a/pybricksdev/cli/__init__.py +++ b/pybricksdev/cli/__init__.py @@ -293,6 +293,7 @@ async def reconnect_hub(): ) with _get_script_path(args.file) as script_path: if response == response_options[0]: + args.file.close() args.file = open( await hub.race_disconnect( hub.race_power_button_press( From b735de6f516f1e88f1bfdf79adca086135862a49 Mon Sep 17 00:00:00 2001 From: shaggy Date: Mon, 20 Oct 2025 19:29:59 -0500 Subject: [PATCH 5/9] send the new file to the hub upon change --- pybricksdev/cli/__init__.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/pybricksdev/cli/__init__.py b/pybricksdev/cli/__init__.py index b32ec82..b390210 100644 --- a/pybricksdev/cli/__init__.py +++ b/pybricksdev/cli/__init__.py @@ -291,22 +291,28 @@ async def reconnect_hub(): ).ask_async() ) ) - with _get_script_path(args.file) as script_path: - if response == response_options[0]: - args.file.close() - args.file = open( - await hub.race_disconnect( - hub.race_power_button_press( - questionary.path( - "What file would you like to use?" - ).ask_async() - ) + + if response == response_options[0]: + args.file.close() + args.file = open( + await hub.race_disconnect( + hub.race_power_button_press( + questionary.path( + "What file would you like to use?" + ).ask_async() ) ) + ) + + with _get_script_path(args.file) as script_path: + # send the new target file to the hub + if ( + response == response_options[0] + or response == response_options[2] + ): + await hub.download(script_path) elif response == response_options[1]: await hub.run(script_path, wait=True) - elif response == response_options[2]: - await hub.download(script_path) else: return @@ -326,6 +332,9 @@ async def reconnect_hub(): await asyncio.sleep(0.3) hub = await reconnect_hub() + except FileNotFoundError: + print("Your file is invalid.") + finally: await hub.disconnect() From ce2447aa462509f030da6835fdb6fc4d59442a2d Mon Sep 17 00:00:00 2001 From: shaggy Date: Mon, 20 Oct 2025 19:44:01 -0500 Subject: [PATCH 6/9] add a changelog entry --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20886d0..df04f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- Added the `Change Target File` option to the `--stay-connected` menu. + ([pybricksdev#123]) + +[pybricksdev#123]: https://github.com/pybricks/pybricksdev/pull/123 + ## [2.1.1] - 2025-09-13 ### Fixed From c2c72fc25158393cd86d888e326787f7dc5db33e Mon Sep 17 00:00:00 2001 From: shaggy Date: Thu, 23 Oct 2025 13:20:13 -0500 Subject: [PATCH 7/9] implement some suggested changes --- pybricksdev/cli/__init__.py | 67 +++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/pybricksdev/cli/__init__.py b/pybricksdev/cli/__init__.py index b390210..4e31f15 100644 --- a/pybricksdev/cli/__init__.py +++ b/pybricksdev/cli/__init__.py @@ -10,6 +10,7 @@ import os import sys from abc import ABC, abstractmethod +from enum import IntEnum from os import PathLike, path from tempfile import NamedTemporaryFile from typing import ContextManager, TextIO @@ -239,6 +240,12 @@ def is_pybricks_usb(dev): if not args.stay_connected: return + class ResponseOptions(IntEnum): + RECOMPILE_RUN = 0 + RECOMPILE_DOWNLOAD = 1 + CHANGE_TARGET_FILE = 2 + EXIT = 3 + async def reconnect_hub(): if not await questionary.confirm( "\nThe hub has been disconnected. Would you like to re-connect?" @@ -262,9 +269,9 @@ async def reconnect_hub(): return hub response_options = [ - "Change Target File", "Recompile and Run", "Recompile and Download", + "Change Target File", "Exit", ] while True: @@ -284,37 +291,50 @@ async def reconnect_hub(): f"Would you like to re-compile {os.path.basename(args.file.name)}?", response_options, default=( - response_options[1] + response_options[ResponseOptions.RECOMPILE_RUN] if args.start - else response_options[2] + else response_options[ + ResponseOptions.RECOMPILE_DOWNLOAD + ] ), ).ask_async() ) ) - if response == response_options[0]: + if response == response_options[ResponseOptions.RECOMPILE_RUN]: + with _get_script_path(args.file) as script_path: + await hub.run(script_path, wait=True) + + elif ( + response == response_options[ResponseOptions.RECOMPILE_DOWNLOAD] + ): + with _get_script_path(args.file) as script_path: + await hub.download(script_path) + + elif ( + response == response_options[ResponseOptions.CHANGE_TARGET_FILE] + ): args.file.close() - args.file = open( - await hub.race_disconnect( - hub.race_power_button_press( - questionary.path( - "What file would you like to use?" - ).ask_async() + while True: + try: + args.file = open( + await hub.race_disconnect( + hub.race_power_button_press( + questionary.path( + "What file would you like to use?" + ).ask_async() + ) + ) ) - ) - ) - - with _get_script_path(args.file) as script_path: + break + except FileNotFoundError: + print("The file was not found. Please try again.") # send the new target file to the hub - if ( - response == response_options[0] - or response == response_options[2] - ): + with _get_script_path(args.file) as script_path: await hub.download(script_path) - elif response == response_options[1]: - await hub.run(script_path, wait=True) - else: - return + + else: + return except HubPowerButtonPressedError: # This means the user pressed the button on the hub to re-start the @@ -332,9 +352,6 @@ async def reconnect_hub(): await asyncio.sleep(0.3) hub = await reconnect_hub() - except FileNotFoundError: - print("Your file is invalid.") - finally: await hub.disconnect() From 92b0d22b533f199ba44035f40b7f4c4a9f104e4e Mon Sep 17 00:00:00 2001 From: shaggy Date: Thu, 23 Oct 2025 14:37:58 -0500 Subject: [PATCH 8/9] replace the bulky if-else block with a match statement --- pybricksdev/cli/__init__.py | 62 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/pybricksdev/cli/__init__.py b/pybricksdev/cli/__init__.py index 4e31f15..e9751b2 100644 --- a/pybricksdev/cli/__init__.py +++ b/pybricksdev/cli/__init__.py @@ -301,40 +301,38 @@ async def reconnect_hub(): ) ) - if response == response_options[ResponseOptions.RECOMPILE_RUN]: - with _get_script_path(args.file) as script_path: - await hub.run(script_path, wait=True) - - elif ( - response == response_options[ResponseOptions.RECOMPILE_DOWNLOAD] - ): - with _get_script_path(args.file) as script_path: - await hub.download(script_path) - - elif ( - response == response_options[ResponseOptions.CHANGE_TARGET_FILE] - ): - args.file.close() - while True: - try: - args.file = open( - await hub.race_disconnect( - hub.race_power_button_press( - questionary.path( - "What file would you like to use?" - ).ask_async() + match response_options.index(response): + + case ResponseOptions.RECOMPILE_RUN: + with _get_script_path(args.file) as script_path: + await hub.run(script_path, wait=True) + + case ResponseOptions.RECOMPILE_DOWNLOAD: + with _get_script_path(args.file) as script_path: + await hub.download(script_path) + + case ResponseOptions.CHANGE_TARGET_FILE: + args.file.close() + while True: + try: + args.file = open( + await hub.race_disconnect( + hub.race_power_button_press( + questionary.path( + "What file would you like to use?" + ).ask_async() + ) ) ) - ) - break - except FileNotFoundError: - print("The file was not found. Please try again.") - # send the new target file to the hub - with _get_script_path(args.file) as script_path: - await hub.download(script_path) - - else: - return + break + except FileNotFoundError: + print("The file was not found. Please try again.") + # send the new target file to the hub + with _get_script_path(args.file) as script_path: + await hub.download(script_path) + + case _: + return except HubPowerButtonPressedError: # This means the user pressed the button on the hub to re-start the From e72b050b5b73e127744763c9052772f417123275 Mon Sep 17 00:00:00 2001 From: shaggy Date: Thu, 23 Oct 2025 19:11:09 -0500 Subject: [PATCH 9/9] fix comment alignment --- pybricksdev/cli/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pybricksdev/cli/__init__.py b/pybricksdev/cli/__init__.py index e9751b2..0abe13b 100644 --- a/pybricksdev/cli/__init__.py +++ b/pybricksdev/cli/__init__.py @@ -327,7 +327,7 @@ async def reconnect_hub(): break except FileNotFoundError: print("The file was not found. Please try again.") - # send the new target file to the hub + # send the new target file to the hub with _get_script_path(args.file) as script_path: await hub.download(script_path)