Skip to content

force explicit install of venv in .platformio folder #241

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

Merged
merged 1 commit into from
Aug 2, 2025
Merged

Conversation

Jason2866
Copy link

@Jason2866 Jason2866 commented Aug 2, 2025

Description:

to avoid pioarduino tools install issues (especially with Windows)

Checklist:

  • The pull request is done against the latest develop branch
  • Only relevant files were touched
  • Only one feature/fix was added per PR, more changes are allowed when changing boards.json
  • I accept the CLA

Summary by CodeRabbit

  • New Features

    • Introduced automatic creation and management of a dedicated Python virtual environment for handling Python dependencies within the PlatformIO core directory.
  • Improvements

    • Enhanced compatibility and reliability of Python environment setup, especially on Windows systems.
    • Improved detection and usage of installed Python packages by updating environment paths.
  • Other

    • Minor formatting and platform compatibility updates.

Copy link

coderabbitai bot commented Aug 2, 2025

Walkthrough

This update introduces a dedicated Python virtual environment ("penv") within the PlatformIO core directory to manage dependencies. It adds functions to set up and use this environment, updates global Python executable handling, modifies Windows path logic, and adjusts Python path setup to ensure correct interpreter and package resolution.

Changes

Cohort / File(s) Change Summary
Virtual Environment Setup and Management
builder/main.py
Introduced setup_pipenv_in_package() to create and manage a dedicated "penv" virtual environment; updated global PYTHON_EXE assignment; modified environment PATH and sys.path to ensure correct interpreter and package handling.
Python Path and Executable Resolution
builder/main.py
Updated setup_python_paths() to use subprocess for site-packages discovery and always add Python executable directory; refactored _get_executable_path() to use IS_WINDOWS and adjust Windows executable path logic.
Platform Checks and Formatting
builder/main.py
Replaced platform checks with IS_WINDOWS flag; performed minor formatting cleanup such as removing extra blank lines.
Dependency Installation Sequence
builder/main.py
Split installation sequence to install Python dependencies using the new virtual environment, followed by esptool installation.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MainScript
    participant VirtualEnv
    participant SystemEnv

    User->>MainScript: Start build process
    MainScript->>VirtualEnv: setup_pipenv_in_package()
    VirtualEnv-->>MainScript: Ensure "penv" exists, pip available
    MainScript->>SystemEnv: Update PATH and sys.path
    MainScript->>MainScript: Update PYTHON_EXE to penv Python
    MainScript->>MainScript: setup_python_paths()
    MainScript->>MainScript: Install Python dependencies (with penv Python)
    MainScript->>MainScript: Install esptool (with penv Python)
    MainScript-->>User: Continue build process
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

  • Fix windows python path issue #218: Modifies builder/main.py for improved Python environment and path handling, directly related to Python executable and site-packages management.
  • Full uv path #227: Builds upon and alters global PYTHON_EXE usage and _get_executable_path, showing direct continuation of environment setup logic.
  • call esptool with full path #226: Involves changes to executable path resolution, particularly for esptool, overlapping with modifications in this PR.

Poem

In the warren, a penv now grows,
Where Python dependencies neatly repose.
Paths are aligned, executables found,
Windows and Unix, all safe and sound.
With each hop and install, the build leaps ahead—
A rabbit’s delight in the virtual env bed! 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch win_test

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Jason2866
Copy link
Author

@coderabbitai full review

Copy link

coderabbitai bot commented Aug 2, 2025

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a 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 (2)
builder/main.py (2)

69-89: Consider adding more robust error handling for venv creation.

While the assertion checks for pip existence, the venv creation itself could fail for various reasons (permissions, disk space, corrupted Python installation). Consider wrapping the venv creation in a try-except block to provide more informative error messages.

 def setup_pipenv_in_package():
     """
     Checks if 'penv' folder exists in platformio dir and creates virtual environment if not.
     """
     if not os.path.exists(penv_dir):
-        env.Execute(
-            env.VerboseAction(
-                '"$PYTHONEXE" -m venv --clear "%s"' % penv_dir,
-                "Creating a new virtual environment for Python dependencies",
+        try:
+            env.Execute(
+                env.VerboseAction(
+                    '"$PYTHONEXE" -m venv --clear "%s"' % penv_dir,
+                    "Creating a new virtual environment for Python dependencies",
+                )
             )
-        )
+        except Exception as e:
+            sys.stderr.write(f"Error: Failed to create virtual environment at {penv_dir}: {e}\n")
+            env.Exit(1)
 
         assert os.path.isfile(
             pip_path
         ), "Error: Failed to create a proper virtual environment. Missing the `pip` binary!"

103-121: Consider using the Python interpreter to determine site-packages path.

While the current directory scanning approach works, it could be more robust to ask the Python interpreter directly for its site-packages location, similar to what's done in setup_python_paths().

-    if IS_WINDOWS:
-        penv_site_packages = os.path.join(penv_dir, "Lib", "site-packages")
-    else:
-        # Find the actual site-packages directory in the venv
-        penv_lib_dir = os.path.join(penv_dir, "lib")
-        if os.path.isdir(penv_lib_dir):
-            for python_dir in os.listdir(penv_lib_dir):
-                if python_dir.startswith("python"):
-                    penv_site_packages = os.path.join(penv_lib_dir, python_dir, "site-packages")
-                    break
-            else:
-                penv_site_packages = None
-        else:
-            penv_site_packages = None
+    # Get site-packages directly from the Python interpreter
+    try:
+        result = subprocess.run(
+            [PYTHON_EXE, "-c", "import site; print(site.getsitepackages()[0])"],
+            capture_output=True,
+            text=True,
+            timeout=5
+        )
+        if result.returncode == 0:
+            penv_site_packages = result.stdout.strip()
+        else:
+            penv_site_packages = None
+    except Exception:
+        penv_site_packages = None
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d14f77 and f704a61.

📒 Files selected for processing (1)
  • builder/main.py (6 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
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: in the esp32 platform builder, the subprocess call to get site-packages directory in setup_python_pa...
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.

Applied to files:

  • builder/main.py
📚 Learning: in platform.py, the `tool-esp_install` package intentionally transitions from mandatory to optional ...
Learnt from: Jason2866
PR: pioarduino/platform-espressif32#237
File: platform.py:200-201
Timestamp: 2025-07-29T11:35:26.182Z
Learning: In platform.py, the `tool-esp_install` package intentionally transitions from mandatory to optional status after successful installation. Initially it's needed and mandatory for installation, but becomes optional once installed since it's no longer required for subsequent operations. Setting `self.packages[tl_install_name]["optional"] = True` after version verification is the intended design pattern.

Applied to files:

  • builder/main.py
🔇 Additional comments (8)
builder/main.py (8)

37-37: Good use of centralized platform detection.

Using IS_WINDOWS from platformio.compat instead of direct platform checks improves maintainability and consistency.


60-68: Proper cross-platform path handling for virtual environment.

The code correctly constructs platform-specific paths for the virtual environment and pip executable.


94-99: Correct PATH manipulation for virtual environment.

The code properly updates the PATH environment variable to ensure subprocess calls use the virtual environment's Python interpreter, with appropriate duplicate checking.


100-102: Good verification of Python executable existence.

The assertion with a clear error message helps catch configuration issues early.


149-149: Minor formatting cleanup.


286-286: Consistent use of IS_WINDOWS constant.


424-428: Clear installation sequence with helpful comments.

The installation order (dependencies first, then esptool) is logical and the comments improve code clarity.


183-184: Ignore Scripts Directory Concern

The updated _get_executable_path no longer hard-codes “Scripts” for Windows; instead it uses

python_dir = os.path.dirname(python_exe)

Since in a standard Windows venv python_exe lives under the Scripts folder, executables are still found there. This dynamic lookup is actually more robust and does not break existing environments. No changes are needed.

Likely an incorrect or invalid review comment.

@Jason2866 Jason2866 merged commit 5d37b07 into develop Aug 2, 2025
68 checks passed
@Jason2866 Jason2866 deleted the win_test branch August 3, 2025 10:21
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.

1 participant