Skip to content
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

Zed Python doesn't detect multiple venvs in project #20402

Open
1 task done
KhazAkar opened this issue Nov 8, 2024 · 8 comments
Open
1 task done

Zed Python doesn't detect multiple venvs in project #20402

KhazAkar opened this issue Nov 8, 2024 · 8 comments
Labels
bug [core label] language An umbrella label for all programming languages syntax behaviors python Python programming language support

Comments

@KhazAkar
Copy link

KhazAkar commented Nov 8, 2024

Check for existing issues

  • Completed

Describe the bug / provide steps to reproduce it

I have monorepository with few sub-projects, each have their own venv. Currently it only sees venv in the root of monorepo, but doesn't detect venvs in subfolders.

Environment

Zed: v0.160.7 (Zed)
OS: Linux Wayland ubuntu 22.04
Memory: 15.2 GiB
Architecture: x86_64
GPU: Intel(R) UHD Graphics 620 (WHL GT2) || Intel open-source Mesa driver || Mesa 23.2.1-1ubuntu3.1~22.04.2

If applicable, add mockups / screenshots to help explain present your vision of the feature

No response

If applicable, attach your Zed.log file to this issue.

No response

@KhazAkar KhazAkar added admin read Pending admin review bug [core label] triage Maintainer needs to classify the issue labels Nov 8, 2024
@JosephTLyons JosephTLyons added python Python programming language support language An umbrella label for all programming languages syntax behaviors and removed triage Maintainer needs to classify the issue admin read Pending admin review labels Nov 10, 2024
@osiewicz
Copy link
Contributor

Yup, that's a current limitation; each project has multiple worktrees and each worktree has at most one associated venv. You can work around it by opening your monorepo with multiple worktrees.

I realize it's not ideal, but we're aware of that.

@KhazAkar
Copy link
Author

Okay, so this issue can stay as tracking of eventual progress towards fixing that limitation. As of now, I will try opening subdirs :)

@osiewicz
Copy link
Contributor

Right; one problem we've had with allowing arbitrary venvs in the project is that currently we only allow using a single language server per worktree (so same as single venv per worktree), so having multiple venvs in a single project seemed like a lot of work of unclear benefit. I'd love to learn about your use case more; does the limitation of language servers having one instance per worktree bother you anyhow?

@KhazAkar
Copy link
Author

Well, currently I work in monorepository, which contains few projects, quite coupled together, and they use Python, JS and C++. Some of those projects use python, but each with different version and libraries needed, so either we use poetry, or venv, depending on a project. More than 1 of them uses venv, most notably main directory (for tools and CI), and one of the projects inside one of the subfolders.
In this case, technically it bothers me, because I need, currently as limitation, to either open multiple zed instances, or use micromamba for environments and swap between them, depending on what part of monorepo I work currently on.

@andres-ortizl
Copy link

Hello !

I currently work in a monorepo as well, which contains several projects that are fairly independent but share some common code. These projects primarily use Python but are configured with different virtual environments (venv) or dependency managers (e.g., Poetry). This setup often requires switching between environments based on the file or project I'm working on.

The limitation I’ve found, specifically in Zed (and also in VS Code to some extent), is the inability to dynamically switch the active virtual environment based on the file or folder that’s currently focused. For example, in Python, I have to manually adjust the pyright configuration or switch environments when working on different parts of the monorepo. This is tedious when jumping between projects as part of my normal workflow.

In VS Code, this limitation is addressed with an extension like Python Envy, which dynamically adjusts the virtual environment based on the workspace or file being edited. I think adding a similar feature to Zed would be a game-changer for managing Python projects in a monorepo setup.

@osiewicz
Copy link
Contributor

osiewicz commented Dec 19, 2024

This is somewhat related to #22182 as we'd have to understand at which point in your worktree a given subproject starts.
Would either of you say that each subdirectory that you'd like to use distinct virtual environment for can be clearly "recognized" as a Python project? e.g. do these subdirectories have pyproject.toml files in them? Or do they meet any other criteria you think could be used to categorize them as roots of Python projects?

@KhazAkar
Copy link
Author

@osiewicz most of the time it's designated by having pyproject.toml file. One exception I know of are python azure functions, but for now we can stick with it

@andres-ortizl
Copy link

I found a partial workaround for dynamically updating the pyrightconfig.json file with the virtual environment path corresponding to the current project when switching between projects. Here’s how I solved it:

I created a small Python script that, combined with a Zed task, automates updating the pyrightconfig.json file based on the virtual environment (.venv) for the current file’s project (if a .venv exists).

How It Works :

  1. Zed Task Configuration:
    I added the following task to my Zed configuration, which calls the Python script and passes the directory of the current file ($ZED_DIRNAME) as an argument:
 {
    "label": "UPDATE pyright",
    "command": "python",
    "args": [
      "path_to_script.py",
      "$ZED_DIRNAME"
    ],
    "use_new_terminal": false,
    "allow_concurrent_runs": false,
    "reveal": "always",
    "hide": "never",
    "shell": "system"
  }
  1. Python Script:
    The Python script performs the following steps:
    • Reverse Traversal: It starts from the given directory (passed via $ZED_DIRNAME) and traverses upwards until it finds a pyproject.toml file, which identifies the root of the project.
    • Locate .venv: If a .venv folder exists in the project directory, it updates the pyrightconfig.json file to point to the .venv path.
    • Update Configuration: The script either modifies an existing pyrightconfig.json file or creates one if it doesn’t already exist, adding the correct venvPath and venv fields.
import json
import os


def find_pyproject_toml(start_path: str):
    current_dir = start_path
    while True:
        potential_path = os.path.join(current_dir, "pyproject.toml")
        print(f"Checking {potential_path}")
        if os.path.isfile(potential_path):
            return current_dir
        parent_dir = os.path.dirname(current_dir)
        if parent_dir == current_dir:
            return None
        current_dir = parent_dir


def update_pyright_config(base_dir, pyright_config_path):
    venv_path = os.path.join(
        base_dir, ".venv", "bin", "python"
    )

    if not os.path.isfile(venv_path):
        print(f"Python interpreter not found at {venv_path}")
        return

    pyright_config = {}

    if os.path.isfile(pyright_config_path):
        with open(pyright_config_path, "r") as file:
            pyright_config = json.load(file)
    pyright_config["venvPath"] = base_dir
    pyright_config["venv"] = ".venv"

    with open(pyright_config_path, "w") as file:
        json.dump(pyright_config, file, indent=4)

    print(f"Pyright configuration updated with virtual environment from {venv_path}")


if __name__ == "__main__":
    import sys

    print(sys.argv[1:])
    start_path = os.getenv("ZED_FILE")
    print(f"Searching for pyproject.toml starting from {start_path}")
    base_dir = find_pyproject_toml(start_path)
    print(f"Found base directory at {base_dir}")
    update_pyright_config(
        base_dir=base_dir,
        pyright_config_path=os.path.join(
            "/root_project_path/", "pyrightconfig.json" # change me
        ),
    )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug [core label] language An umbrella label for all programming languages syntax behaviors python Python programming language support
Projects
None yet
Development

No branches or pull requests

4 participants