From 5a7b1c411ee8c5c572c49740bba04de0721d7146 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 11 May 2026 16:00:42 -0500 Subject: [PATCH] [cli] DRY up --prebuilt-dir helpers Two small simplifications surfaced by re-reading the diff with a 'is this DRY?' lens: - Extract _missing_prebuilt_flash_tool(): the _ensure_platform_packages_for_prebuilt_upload helper had two near-identical 'if platform check; if finder() is not None return 0; tool_label = ...' blocks. Lift the platform->(tool_name) selection into a tiny helper so the early-return is one line and the install body is no longer interleaved with the platform dispatch. - Collapse the two near-duplicate 'firmware not found' return points in upload_using_picotool. Both branches just selected an error message and returned 1; reorder so the message selection happens first and there's a single 'return 1'. No behavior change; pure refactor. 587 unit tests pass. Issue: esphome/device-builder#572 --- esphome/__main__.py | 75 +++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 84e55294d6..8851682511 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -1032,26 +1032,25 @@ def upload_using_picotool(config: ConfigType) -> int: # picotool's "load" target accepts .uf2 / .bin / .elf, so fall back to # CORE.firmware_bin (which resolves to the prebuilt firmware.uf2 when set) # when no ELF is available. - firmware_file: Path elf_path = Path(idedata.firmware_elf_path) if elf_path.is_file(): - firmware_file = elf_path + firmware_file: Path = elf_path elif CORE.prebuilt_dir is not None and CORE.firmware_bin.is_file(): firmware_file = CORE.firmware_bin - elif CORE.prebuilt_dir is not None: - _LOGGER.error( - "No firmware found for picotool: neither %s (from idedata) nor " - "%s (prebuilt) exists.", - elf_path, - CORE.firmware_bin, - ) - return 1 else: - _LOGGER.error( - "Firmware ELF file not found at %s. " - "Make sure the project has been compiled first.", - elf_path, - ) + if CORE.prebuilt_dir is not None: + _LOGGER.error( + "No firmware found for picotool: neither %s (from idedata) " + "nor %s (prebuilt) exists.", + elf_path, + CORE.firmware_bin, + ) + else: + _LOGGER.error( + "Firmware ELF file not found at %s. " + "Make sure the project has been compiled first.", + elf_path, + ) return 1 picotool = get_picotool_path(idedata.cc_path) @@ -1210,41 +1209,43 @@ def check_permissions(port: str): ) +def _missing_prebuilt_flash_tool() -> str | None: + """Return the name of the platform-specific flash tool that's expected + but not yet on disk, or None if no install step is needed. + + ESP* paths use bundled esptool / smpclient. Libretiny + RP2040 paths + use ltchiptool / picotool, which ship inside the PlatformIO platform + package and aren't pip-installable on their own. + """ + if CORE.is_libretiny and get_ltchiptool_path() is None: + return "ltchiptool" + if CORE.target_platform == PLATFORM_RP2040 and _find_picotool() is None: + return "picotool" + return None + + def _ensure_platform_packages_for_prebuilt_upload(config: ConfigType) -> int: """Make sure the per-platform flash tool is available before a ``--prebuilt-dir`` upload dispatches. - The libretiny + RP2040 prebuilt-dir paths use ``ltchiptool`` and - ``picotool`` respectively. Both binaries live inside the PlatformIO - platform package, not in esphome's Python deps. On a host that has - never compiled the target platform locally (the dashboard's - transparent-install scenario), they won't be on disk yet. - - Mirror what ``esphome compile`` would do up to the platform-install - step (codegen + write platformio.ini), then run ``pio pkg install`` - instead of ``pio run`` so the platform is downloaded without paying - for an actual compile. After this returns, the flash-tool lookups - (``get_ltchiptool_path``, ``_find_picotool``) succeed and the upload - helper takes over. + On a host that has never compiled the target platform locally (the + dashboard's transparent-install scenario), the flash tool isn't on + disk yet. Mirror what ``esphome compile`` would do up to the + platform-install step (codegen + write platformio.ini), then run + ``pio run -t idedata`` so the platform is downloaded without paying + for an actual compile. Returns 0 if no install was needed or the install succeeded; non-zero on failure so the upload bails out with a clear status. """ - if CORE.is_libretiny: - if get_ltchiptool_path() is not None: - return 0 - tool_label = "ltchiptool" - elif CORE.target_platform == PLATFORM_RP2040: - if _find_picotool() is not None: - return 0 - tool_label = "picotool" - else: + tool_name = _missing_prebuilt_flash_tool() + if tool_name is None: return 0 _LOGGER.info( "%s not found on this host; configuring the PlatformIO %s " "platform so the upload can flash the prebuilt firmware...", - tool_label, + tool_name, CORE.target_platform, ) rc = write_cpp(config)