-
Notifications
You must be signed in to change notification settings - Fork 61
Remove use of pip in espidf.py to create the venv #265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughSwitches ESP-IDF venv and dependency handling to use the penv "uv" executable via penv_setup.get_executable_path; adds PLATFORMIO_DIR constant; locates LIB_SOURCE via platform.get_dir(); changes venv location to PLATFORMIO_DIR/penv/.espidf-{version} and verifies venv by resolving its Python executable. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Build as Build System
participant ESP as builder/frameworks/espidf.py
participant Platform as Platform API
participant Penv as penv_setup
participant UV as uv CLI
Build->>ESP: trigger ESP-IDF setup
ESP->>Platform: platform.get_dir()
Platform-->>ESP: platform dir (for LIB_SOURCE)
ESP->>ESP: set PLATFORMIO_DIR, penv_dir, venv_dir
ESP->>Penv: get_executable_path(penv_dir, "uv")
Penv-->>ESP: uv_exe path
ESP->>UV: uv_exe venv --clear --quiet --python "<py>" "<venv_dir>"
UV-->>ESP: exit status
ESP->>Penv: get_executable_path(venv_dir, "python")
Penv-->>ESP: python_in_venv (found / not found)
alt python found
ESP-->>Build: venv verified
else
ESP-->>Build: venv verification failed
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
builder/frameworks/espidf.py (1)
1609-1642
: Harden venv creation & unifyuv
resolution across ESP-IDF builderI’ve confirmed two distinct ways of locating the
uv
executable inbuilder/frameworks/espidf.py
:
- In
install_python_deps()
(around line 1490),UV_EXE
is built fromenv.subst("$PYTHONEXE") + os.path.dirname()
- In
_create_venv()
(lines 1614–1642),uv_path
comes fromget_executable_path(penv_dir, "uv")
To avoid silent failures and ensure consistent behavior:
In
_create_venv()
:
- Immediately verify
uv_path
exists before invoking it.- Replace the
assert
on the Python executable with an explicitenv.Exit(1)
and stderr message.def _create_venv(venv_dir): penv_setup_path = os.path.join(platform.get_dir(), "builder") sys.path.insert(0, penv_setup_path) from penv_setup import get_executable_path penv_dir = os.path.join(PLATFORMIO_DIR, "penv") uv_path = get_executable_path(penv_dir, "uv")
if not uv_path or not os.path.isfile(uv_path):
sys.stderr.write(
"Error: 'uv' executable not found in PlatformIO penv. "
"Ensure penv_setup has installed uv or reinstall the platform.\n"
)
env.Exit(1) if os.path.isdir(venv_dir): … env.Execute( env.VerboseAction( '"%s" venv --clear --quiet "%s"' % (uv_path, venv_dir), "Creating a new virtual environment for IDF Python dependencies using uv", ) ) python_path = get_executable_path(venv_dir, "python")
assert os.path.isfile(python_path), \
"Error: Failed to create a proper virtual environment. Missing the Python executable!"
if not python_path or not os.path.isfile(python_path):
sys.stderr.write(
"Error: Failed to create a proper virtual environment "
"(Python executable missing).\n"
)
env.Exit(1)
In
install_python_deps()
:
- Replace the custom
UV_EXE
derivation with the sameget_executable_path()
approach.- Import
get_executable_path
frompenv_setup
and point it at the sharedpenv
directory.def install_python_deps():
PYTHON_EXE = env.subst("$PYTHONEXE")
UV_EXE = os.path.join(
os.path.dirname(PYTHON_EXE),
"uv" + (".exe" if IS_WINDOWS else "")
)
from penv_setup import get_executable_path
PYTHON_EXE = env.subst("$PYTHONEXE")
penv_dir = os.path.join(PLATFORMIO_DIR, "penv")
UV_EXE = get_executable_path(penv_dir, "uv") def _get_installed_uv_packages(python_exe_path): …
By unifying both call sites on
get_executable_path()
you eliminate path drift, and by adding explicit existence checks plus consistent error exits you prevent opaque failures in CI or user environments.
🧹 Nitpick comments (2)
builder/frameworks/espidf.py (2)
85-85
: Use PLATFORMIO_DIR consistently throughout the fileGood addition. For consistency and to avoid duplicate env lookups, reuse PLATFORMIO_DIR (introduced here) when computing the IDF venv path in get_idf_venv_dir() instead of calling env.subst("$PROJECT_CORE_DIR") again.
Proposed change outside this range (for get_idf_venv_dir):
def get_idf_venv_dir(): idf_version = get_framework_version() return os.path.join(PLATFORMIO_DIR, "penv", f".espidf-{idf_version}")
1491-1523
: Drop “uv” from the IDF venv dependenciesThe PyPI “uv” package isn’t needed inside the IDF virtual environment—
uv
is a standalone CLI and is provided alongside thepython
executable rather than installed viapip
in the target venv. You can remove it from thedeps
dict without impacting functionality.• In builder/frameworks/espidf.py (around lines 1513–1516), update the
deps
block:deps = { - "uv": ">=0.1.0", # not needed inside the IDF venv "urllib3": "<2", "cryptography": "~=44.0.0", "pyparsing": ">=3.1.0,<4", "idf-component-manager": "~=2.2", "esp-idf-kconfig": "~=2.5.0" }
• To confirm no other
uv
entries remain in thedeps
list, run:rg -nP "^[ \t]*['\"]uv['\"][ \t]*:" builder/frameworks/espidf.py
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
builder/frameworks/espidf.py
(4 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#263
File: platform.py:80-84
Timestamp: 2025-08-20T14:13:13.842Z
Learning: For the pioarduino/platform-espressif32 project, Jason2866 prefers to always override IDF_TOOLS_PATH environment variable with PlatformIO's core directory, rather than respecting any existing user-defined IDF_TOOLS_PATH values. This ensures consistent ESP32 tool management within PlatformIO.
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#246
File: builder/main.py:0-0
Timestamp: 2025-08-05T11:47:41.756Z
Learning: In the ESP32 platform builder, subprocess calls correctly use the virtual environment Python by explicitly passing PYTHON_EXE (which is set to the venv python path) as the first argument in the command array, rather than relying on environment variable propagation. The env=os.environ parameter only affects environment variables, not the executable path itself.
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:265-275
Timestamp: 2025-08-10T16:59:15.533Z
Learning: In the ESP32 platform builder's penv_setup.py, the esptool_repo_path used in subprocess calls comes from PlatformIO's internal package management system (platform.get_package_dir()) which is a trusted source. Command injection concerns are not applicable here since this is build infrastructure code with controlled inputs, not user-facing code accepting arbitrary input.
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#225
File: builder/main.py:99-108
Timestamp: 2025-07-13T20:03:29.695Z
Learning: In the ESP32 platform builder, the subprocess call to get site-packages directory in setup_python_paths() function is intentionally left without error handling because if this basic Python operation fails, it indicates a fundamental system issue that would cause the entire build process to fail anyway.
📚 Learning: 2025-08-20T14:13:13.842Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#263
File: platform.py:80-84
Timestamp: 2025-08-20T14:13:13.842Z
Learning: For the pioarduino/platform-espressif32 project, Jason2866 prefers to always override IDF_TOOLS_PATH environment variable with PlatformIO's core directory, rather than respecting any existing user-defined IDF_TOOLS_PATH values. This ensures consistent ESP32 tool management within PlatformIO.
Applied to files:
builder/frameworks/espidf.py
📚 Learning: 2025-08-10T19:12:17.988Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:19-19
Timestamp: 2025-08-10T19:12:17.988Z
Learning: In PlatformIO ESP32 platform builds, `semantic_version` is a dependency provided by PlatformIO itself and is guaranteed to be available when the build scripts run. The module is already imported at the top level in existing files like `builder/frameworks/espidf.py`, so lazy-loading it is unnecessary.
Applied to files:
builder/frameworks/espidf.py
📚 Learning: 2025-08-10T19:13:25.599Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:26-40
Timestamp: 2025-08-10T19:13:25.599Z
Learning: In the pioarduino/platform-espressif32 repository's builder/penv_setup.py file, semantic_version is imported but intentionally not listed in python_deps because it's a transitive dependency of platformio-core (version 2.10.*). When platformio is installed from the GitHub URL, semantic_version is automatically installed as one of its dependencies.
Applied to files:
builder/frameworks/espidf.py
📚 Learning: 2025-08-10T16:59:15.533Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:265-275
Timestamp: 2025-08-10T16:59:15.533Z
Learning: In the ESP32 platform builder's penv_setup.py, the esptool_repo_path used in subprocess calls comes from PlatformIO's internal package management system (platform.get_package_dir()) which is a trusted source. Command injection concerns are not applicable here since this is build infrastructure code with controlled inputs, not user-facing code accepting arbitrary input.
Applied to files:
builder/frameworks/espidf.py
📚 Learning: 2025-08-05T11:47:41.756Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#246
File: builder/main.py:0-0
Timestamp: 2025-08-05T11:47:41.756Z
Learning: In the ESP32 platform builder, subprocess calls correctly use the virtual environment Python by explicitly passing PYTHON_EXE (which is set to the venv python path) as the first argument in the command array, rather than relying on environment variable propagation. The env=os.environ parameter only affects environment variables, not the executable path itself.
Applied to files:
builder/frameworks/espidf.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: build (macos-15, examples/espidf-ulp-lp)
- GitHub Check: build (macos-15, examples/espidf-storage-sdcard)
- GitHub Check: build (windows-latest, examples/espidf-storage-sdcard)
- GitHub Check: build (macos-15, examples/arduino-NimBLE-ext_client)
- GitHub Check: build (macos-15, examples/arduino-rmt-blink)
- GitHub Check: build (macos-15, examples/tasmota)
- GitHub Check: build (windows-latest, examples/espidf-peripherals-usb)
- GitHub Check: build (windows-latest, examples/espidf-coap-server)
- GitHub Check: build (windows-latest, examples/espidf-blink)
- GitHub Check: build (windows-latest, examples/espidf-http-request)
- GitHub Check: build (windows-latest, examples/espidf-exceptions)
- GitHub Check: build (windows-latest, examples/arduino-zigbee-switch)
- GitHub Check: build (windows-latest, examples/arduino-blink)
- GitHub Check: build (ubuntu-latest, examples/espidf-arduino-blink)
- GitHub Check: build (windows-latest, examples/arduino-rmt-blink)
- GitHub Check: build (ubuntu-latest, examples/espidf-blink)
- GitHub Check: build (ubuntu-latest, examples/espidf-arduino-matter-light)
- GitHub Check: build (ubuntu-latest, examples/tasmota)
- GitHub Check: build (ubuntu-latest, examples/arduino-wifiscan)
- GitHub Check: build (ubuntu-latest, examples/arduino-blink)
🔇 Additional comments (1)
builder/frameworks/espidf.py (1)
351-366
: LIB_SOURCE resolution via platform.get_dir() looks correctSwitching to platform.get_dir() for builder/build_lib resolves the path deterministically from the platform package root and decouples it from ProjectConfig. The flow that reshapes the environment for Arduino-only builds remains intact.
Refactor Python dependency installation to use a virtual environment and update UV executable path retrieval.
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (5)
builder/frameworks/espidf.py (5)
85-85
: Rename PLATFORMIO_DIR to PIO_CORE_DIR to avoid confusion with PlatformIO’s own “PLATFORMIO_DIR” conceptThis variable actually holds $PROJECT_CORE_DIR (PlatformIO core dir). Naming it PLATFORMIO_DIR is easy to conflate with PlatformIO’s “home” dir in docs and other code. Rename for clarity and update references.
Apply these focused diffs:
-PLATFORMIO_DIR = env.subst("$PROJECT_CORE_DIR") +PIO_CORE_DIR = env.subst("$PROJECT_CORE_DIR")- penv_dir = os.path.join(PLATFORMIO_DIR, "penv") + penv_dir = os.path.join(PIO_CORE_DIR, "penv")- return os.path.join(PLATFORMIO_DIR, "penv", f".espidf-{idf_version}") + return os.path.join(PIO_CORE_DIR, "penv", f".espidf-{idf_version}")- penv_dir = os.path.join(PLATFORMIO_DIR, "penv") + penv_dir = os.path.join(PIO_CORE_DIR, "penv")Also applies to: 1495-1495, 1568-1568, 1615-1615
1491-1496
: Centralize uv resolution; avoid duplicating sys.path mutationsYou resolve uv here and again in _create_venv by pushing builder/ onto sys.path and importing penv_setup each time. Centralizing this avoids path pollution and repetition. Also guarantees a single place to tweak bootstrap logic later.
Apply this minimal diff in-place:
- penv_setup_path = os.path.join(platform.get_dir(), "builder") - sys.path.insert(0, penv_setup_path) - from penv_setup import get_executable_path - - penv_dir = os.path.join(PLATFORMIO_DIR, "penv") - UV_EXE = get_executable_path(penv_dir, "uv") + UV_EXE = _get_uv_exe()And add this helper once (outside this hunk), which safely avoids duplicate sys.path entries:
def _get_uv_exe(): penv_setup_path = os.path.join(platform.get_dir(), "builder") if penv_setup_path not in sys.path: sys.path.insert(0, penv_setup_path) from penv_setup import get_executable_path penv_dir = os.path.join(PIO_CORE_DIR if 'PIO_CORE_DIR' in globals() else PLATFORMIO_DIR, "penv") return get_executable_path(penv_dir, "uv")
1610-1617
: Use the centralized uv resolver and prefer explicit error handling over assert for venv verification
- Reuse the _get_uv_exe() helper here.
- Replace assert with a proper error path; asserts can be stripped with -O and don’t print stderr context in SCons.
Apply this diff:
- penv_setup_path = os.path.join(platform.get_dir(), "builder") - sys.path.insert(0, penv_setup_path) - - from penv_setup import get_executable_path - - penv_dir = os.path.join(PLATFORMIO_DIR, "penv") - uv_path = get_executable_path(penv_dir, "uv") + uv_path = _get_uv_exe()- env.Execute( + env.Execute( env.VerboseAction( '"%s" venv --clear --quiet --python "%s" "%s"' % (uv_path, env.subst("$PYTHONEXE"), venv_dir), "Creating a new virtual environment for IDF Python dependencies using uv", ) )- python_path = get_executable_path(venv_dir, "python") - - assert os.path.isfile( - python_path - ), "Error: Failed to create a proper virtual environment. Missing the Python executable!" + python_path = get_executable_path(venv_dir, "python") + if not os.path.isfile(python_path): + sys.stderr.write("Error: Failed to create a proper IDF virtual environment; Python not found at %s\n" % python_path) + env.Exit(1)Also applies to: 1630-1634, 1637-1643
1497-1512
: Compatibility of uv pip list JSON parsing is acceptable; guard for future format deviationParsing name/version from uv pip list --format=json is fine. You already catch JSONDecodeError/OSError. Optional: log UV_EXE version when the parse fails to make debugging easier if uv changes output format.
1568-1568
: New venv location under core penv is fine; add optional detection/cleanup for legacy venvsThe change to install IDF’s Python virtualenv under
$PROJECT_CORE_DIR/penv/.espidf‐<version>
is safe and will be recreated on first use. As a small quality-of-life improvement, you can add a one-time check for legacy venvs (which were previously created directly under the core dir) and log a hint so users can delete them and reclaim disk space.Here’s an example you could drop into your
penv_setup
logic:import os, glob, logging core_dir = PLATFORMIO_DIR # env.subst("$PROJECT_CORE_DIR") # Find any “.espidf-…” dirs not under the new penv folder legacy = [ d for d in glob.glob(os.path.join(core_dir, ".espidf-*")) if not d.startswith(os.path.join(core_dir, "penv")) ] if legacy: logging.info( "Found legacy IDF venv(s): %s; consider removing them to reclaim disk space", legacy )Or from the shell (adjust
CORE_DIR
as needed for your setup):#!/usr/bin/env bash # Replace with your actual core dir if not ~/.platformio CORE_DIR="${PLATFORMIO_DIR:-$(platformio settings get project_core_dir)}" # List any hidden .espidf-* dirs outside of penv/ fd -HI '^\.espidf-' "$CORE_DIR" -t d \ ! -path "$CORE_DIR/penv/*" \ -x echo {}This will accurately locate any leftover
.espidf-*
venvs outside the newpenv
directory so users can clean them up.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
builder/frameworks/espidf.py
(6 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#263
File: platform.py:80-84
Timestamp: 2025-08-20T14:13:13.842Z
Learning: For the pioarduino/platform-espressif32 project, Jason2866 prefers to always override IDF_TOOLS_PATH environment variable with PlatformIO's core directory, rather than respecting any existing user-defined IDF_TOOLS_PATH values. This ensures consistent ESP32 tool management within PlatformIO.
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#246
File: builder/main.py:0-0
Timestamp: 2025-08-05T11:47:41.756Z
Learning: In the ESP32 platform builder, subprocess calls correctly use the virtual environment Python by explicitly passing PYTHON_EXE (which is set to the venv python path) as the first argument in the command array, rather than relying on environment variable propagation. The env=os.environ parameter only affects environment variables, not the executable path itself.
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:265-275
Timestamp: 2025-08-10T16:59:15.533Z
Learning: In the ESP32 platform builder's penv_setup.py, the esptool_repo_path used in subprocess calls comes from PlatformIO's internal package management system (platform.get_package_dir()) which is a trusted source. Command injection concerns are not applicable here since this is build infrastructure code with controlled inputs, not user-facing code accepting arbitrary input.
📚 Learning: 2025-08-20T14:13:13.842Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#263
File: platform.py:80-84
Timestamp: 2025-08-20T14:13:13.842Z
Learning: For the pioarduino/platform-espressif32 project, Jason2866 prefers to always override IDF_TOOLS_PATH environment variable with PlatformIO's core directory, rather than respecting any existing user-defined IDF_TOOLS_PATH values. This ensures consistent ESP32 tool management within PlatformIO.
Applied to files:
builder/frameworks/espidf.py
📚 Learning: 2025-08-10T19:12:17.988Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:19-19
Timestamp: 2025-08-10T19:12:17.988Z
Learning: In PlatformIO ESP32 platform builds, `semantic_version` is a dependency provided by PlatformIO itself and is guaranteed to be available when the build scripts run. The module is already imported at the top level in existing files like `builder/frameworks/espidf.py`, so lazy-loading it is unnecessary.
Applied to files:
builder/frameworks/espidf.py
📚 Learning: 2025-08-10T19:13:25.599Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:26-40
Timestamp: 2025-08-10T19:13:25.599Z
Learning: In the pioarduino/platform-espressif32 repository's builder/penv_setup.py file, semantic_version is imported but intentionally not listed in python_deps because it's a transitive dependency of platformio-core (version 2.10.*). When platformio is installed from the GitHub URL, semantic_version is automatically installed as one of its dependencies.
Applied to files:
builder/frameworks/espidf.py
📚 Learning: 2025-08-10T16:59:15.533Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:265-275
Timestamp: 2025-08-10T16:59:15.533Z
Learning: In the ESP32 platform builder's penv_setup.py, the esptool_repo_path used in subprocess calls comes from PlatformIO's internal package management system (platform.get_package_dir()) which is a trusted source. Command injection concerns are not applicable here since this is build infrastructure code with controlled inputs, not user-facing code accepting arbitrary input.
Applied to files:
builder/frameworks/espidf.py
📚 Learning: 2025-08-05T11:47:41.756Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#246
File: builder/main.py:0-0
Timestamp: 2025-08-05T11:47:41.756Z
Learning: In the ESP32 platform builder, subprocess calls correctly use the virtual environment Python by explicitly passing PYTHON_EXE (which is set to the venv python path) as the first argument in the command array, rather than relying on environment variable propagation. The env=os.environ parameter only affects environment variables, not the executable path itself.
Applied to files:
builder/frameworks/espidf.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
- GitHub Check: build (windows-latest, examples/espidf-peripherals-usb)
- GitHub Check: build (windows-latest, examples/espidf-blink)
- GitHub Check: build (windows-latest, examples/espidf-coap-server)
- GitHub Check: build (windows-latest, examples/arduino-zigbee-switch)
- GitHub Check: build (windows-latest, examples/arduino-usb-keyboard)
- GitHub Check: build (ubuntu-latest, examples/espidf-ulp-riscv)
- GitHub Check: build (windows-latest, examples/arduino-blink)
- GitHub Check: build (ubuntu-latest, examples/espidf-hello-world)
- GitHub Check: build (ubuntu-latest, examples/espidf-ulp)
- GitHub Check: build (ubuntu-latest, examples/espidf-ulp-lp)
- GitHub Check: build (ubuntu-latest, examples/arduino-blink)
- GitHub Check: build (ubuntu-latest, examples/espidf-arduino-blink)
- GitHub Check: build (ubuntu-latest, examples/espidf-arduino-matter-light)
🔇 Additional comments (3)
builder/frameworks/espidf.py (3)
353-365
: LIB_SOURCE via platform.get_dir() is a good moveSwitching to platform.get_dir() to resolve builder/build_lib removes reliance on ProjectConfig and is more robust. The copy-tree guard looks sane.
1541-1551
: Nice: installing missing packages only; quotes/constraints look correctSelective install using uv pip --python and quoting each "pkg{spec}" looks good and OS-safe. This aligns with the repo’s pattern of executing Python via explicit paths (per past learnings).
1552-1559
: Windows-only windows-curses install via uv is correctGood conditional and reuse of uv pip to keep all installs within the IDF venv.
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
builder/frameworks/espidf.py (4)
24-60
: Dynamic import of penv_setup: add defensive checks to fail fast if the module file/spec/loader is missingGood call switching to importlib and centralizing get_executable_path. Add explicit checks so failures surface with actionable messages instead of AttributeError later.
_penv_setup_file = os.path.join(platform.get_dir(), "builder", "penv_setup.py") -_spec = importlib.util.spec_from_file_location("penv_setup", _penv_setup_file) -_penv_setup = importlib.util.module_from_spec(_spec) -_spec.loader.exec_module(_penv_setup) # type: ignore[attr-defined] -get_executable_path = _penv_setup.get_executable_path +if not os.path.isfile(_penv_setup_file): + sys.stderr.write(f"Error: Missing penv_setup.py at {_penv_setup_file}\n") + env.Exit(1) +_spec = importlib.util.spec_from_file_location("penv_setup", _penv_setup_file) +if _spec is None or _spec.loader is None: + sys.stderr.write("Error: Failed to load spec for penv_setup module\n") + env.Exit(1) +_penv_setup = importlib.util.module_from_spec(_spec) +_spec.loader.exec_module(_penv_setup) # type: ignore[attr-defined] +get_executable_path = _penv_setup.get_executable_path
1498-1500
: Fail fast if uv executable is not resolvableSince subsequent steps rely on uv, surface a clear error early rather than failing deeper in subprocess calls.
-def _get_uv_exe(): - return get_executable_path(os.path.join(PLATFORMIO_DIR, "penv"), "uv") +def _get_uv_exe(): + uv_path = get_executable_path(os.path.join(PLATFORMIO_DIR, "penv"), "uv") + if not uv_path or not os.path.isfile(uv_path): + sys.stderr.write( + "Error: 'uv' executable not found in PlatformIO penv. " + "Ensure builder/penv_setup.py installed it correctly.\n" + ) + env.Exit(1) + return uv_path
1503-1568
: Normalize package-name keys to avoid case-sensitivity mismatchesuv pip list can return names with varying case. Normalize to lower-case once to make membership checks robust (especially for windows-curses).
- for p in packages: - result[p["name"]] = pepver_to_semver(p["version"]) + for p in packages: + result[p["name"].lower()] = pepver_to_semver(p["version"])
1618-1645
: Venv creation and verification: prefer explicit error handling over assertAsserts can be stripped with Python -O. Use an explicit check and env.Exit to guarantee the error is raised. Also, the user-facing message already mentions uv; good clarity.
- # Verify that the venv was created successfully by checking for Python executable - python_path = get_executable_path(venv_dir, "python") - - assert os.path.isfile( - python_path - ), "Error: Failed to create a proper virtual environment. Missing the Python executable!" + # Verify that the venv was created successfully by checking for Python executable + python_path = get_executable_path(venv_dir, "python") + if not python_path or not os.path.isfile(python_path): + sys.stderr.write( + "Error: Failed to create a proper virtual environment. " + "Missing the Python executable!\n" + ) + env.Exit(1)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
builder/frameworks/espidf.py
(8 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#263
File: platform.py:80-84
Timestamp: 2025-08-20T14:13:13.842Z
Learning: For the pioarduino/platform-espressif32 project, Jason2866 prefers to always override IDF_TOOLS_PATH environment variable with PlatformIO's core directory, rather than respecting any existing user-defined IDF_TOOLS_PATH values. This ensures consistent ESP32 tool management within PlatformIO.
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#246
File: builder/main.py:0-0
Timestamp: 2025-08-05T11:47:41.756Z
Learning: In the ESP32 platform builder, subprocess calls correctly use the virtual environment Python by explicitly passing PYTHON_EXE (which is set to the venv python path) as the first argument in the command array, rather than relying on environment variable propagation. The env=os.environ parameter only affects environment variables, not the executable path itself.
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:265-275
Timestamp: 2025-08-10T16:59:15.533Z
Learning: In the ESP32 platform builder's penv_setup.py, the esptool_repo_path used in subprocess calls comes from PlatformIO's internal package management system (platform.get_package_dir()) which is a trusted source. Command injection concerns are not applicable here since this is build infrastructure code with controlled inputs, not user-facing code accepting arbitrary input.
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:26-40
Timestamp: 2025-08-10T19:13:25.599Z
Learning: In the pioarduino/platform-espressif32 repository's builder/penv_setup.py file, semantic_version is imported but intentionally not listed in python_deps because it's a transitive dependency of platformio-core (version 2.10.*). When platformio is installed from the GitHub URL, semantic_version is automatically installed as one of its dependencies.
📚 Learning: 2025-08-10T19:13:25.599Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#255
File: builder/penv_setup.py:26-40
Timestamp: 2025-08-10T19:13:25.599Z
Learning: In the pioarduino/platform-espressif32 repository's builder/penv_setup.py file, semantic_version is imported but intentionally not listed in python_deps because it's a transitive dependency of platformio-core (version 2.10.*). When platformio is installed from the GitHub URL, semantic_version is automatically installed as one of its dependencies.
Applied to files:
builder/frameworks/espidf.py
📚 Learning: 2025-08-20T14:13:13.842Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#263
File: platform.py:80-84
Timestamp: 2025-08-20T14:13:13.842Z
Learning: For the pioarduino/platform-espressif32 project, Jason2866 prefers to always override IDF_TOOLS_PATH environment variable with PlatformIO's core directory, rather than respecting any existing user-defined IDF_TOOLS_PATH values. This ensures consistent ESP32 tool management within PlatformIO.
Applied to files:
builder/frameworks/espidf.py
📚 Learning: 2025-08-05T11:47:41.756Z
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#246
File: builder/main.py:0-0
Timestamp: 2025-08-05T11:47:41.756Z
Learning: In the ESP32 platform builder, subprocess calls correctly use the virtual environment Python by explicitly passing PYTHON_EXE (which is set to the venv python path) as the first argument in the command array, rather than relying on environment variable propagation. The env=os.environ parameter only affects environment variables, not the executable path itself.
Applied to files:
builder/frameworks/espidf.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
- GitHub Check: build (macos-15, examples/espidf-peripherals-uart)
- GitHub Check: build (macos-15, examples/arduino-blink)
- GitHub Check: build (macos-15, examples/arduino-wifiscan)
- GitHub Check: build (windows-latest, examples/arduino-usb-keyboard)
- GitHub Check: build (macos-15, examples/espidf-arduino-C6-ULP-blink)
- GitHub Check: build (macos-15, examples/espidf-coap-server)
- GitHub Check: build (windows-latest, examples/espidf-coap-server)
- GitHub Check: build (windows-latest, examples/espidf-http-request)
- GitHub Check: build (windows-latest, examples/espidf-blink)
- GitHub Check: build (windows-latest, examples/espidf-arduino-blink)
- GitHub Check: build (windows-latest, examples/espidf-arduino-littlefs)
- GitHub Check: build (windows-latest, examples/tasmota)
- GitHub Check: build (windows-latest, examples/arduino-wifiscan)
- GitHub Check: build (windows-latest, examples/arduino-blink)
🔇 Additional comments (5)
builder/frameworks/espidf.py (5)
92-92
: PLATFORMIO_DIR constant: LGTMCentralizing the core dir via env.subst("$PROJECT_CORE_DIR") improves readability and reuse downstream.
1575-1577
: Venv location under PLATFORMIO_DIR/penv/.espidf-{version}: LGTMKeeps IDF envs co-located with PlatformIO penv. Matches prior conventions and avoids user-global pollution.
1503-1519
: uv-based deps install: approach looks solid
- Single-shot install per batch is efficient.
- Constraints for urllib3/cryptography/pyparsing/idf-component-manager/esp-idf-kconfig are explicit and reproducible.
- Windows-specific windows-curses handled.
No blockers from me here.
Also applies to: 1550-1567
513-528
: IDF_TOOLS_PATH sanitization aligns with prior preferenceUnsetting IDF_TOOLS_PATH in the IDF env avoids leakage of user overrides, matching the project preference captured in prior PRs.
361-374
: Verified:builder/build_lib
directory exists; LIB_SOURCE resolution is correctConfirmed that
builder/build_lib/
is present under the platform root, so the switch toplatform.get_dir()
for locatingbuild_lib
is valid and robust against varying install layouts.env.Replace uses this path appropriately—no further changes needed.
Checklist:
Summary by CodeRabbit
Refactor
Bug Fixes
Chores