aspect-build / aspect-build/rules_py

[Bug]: ty [environment] does not work on generated venv for ty IDE extension

Open
#938 2 comments 3 reactions 0 assignees View on GitHub
bug
Dominant language
Starlark
Stars
145
Forks
97
Avg merge
1d 1h
Merged PRs (30d)
71

Description

### What happened?

When trying to integrate with the [`ty` VSCode/Cursor extension](https://marketplace.visualstudio.com/items?itemName=astral-sh.ty), I was unable to configure things in a way where a virtual environment could be linked in my `ty.toml` due to it erroring when resolving the `home` path.

```
2026-04-16 21:16:05.993043258 ERROR Failed to create project for workspace `file:///<>`: Failed to parse the `pyvenv.cfg` file at `/<>/bazel-out/<>/bin/.python3.venv/pyvenv.cfg` because the following error was encountered when trying to resolve the `home` value to a directory on disk: No such file or directory (os error 2). Falling back to default settings
```

I believe the issue was due to the inability of the extension (which I believe utilizes the base VSCode interpreter search, but haven't confirmed) to resolve the relative `./bin/` path from the virtual environment that is set from the pyvenv.cfg template:
```
home = ./bin/ # <- this
implementation = CPython
version_info = {{MAJOR}}.{{MINOR}}.{{PATCH}}
include-system-site-packages = {{INCLUDE_SYSTEM_SITE}}
aspect-include-user-site-packages = {{INCLUDE_USER_SITE}}
relocatable = true
{{INTERPRETER}}
```

### Version

Development (host) and target OS/architectures: Linux ARM64

Output of `bazel --version`: `bazel 9.0.0`

Version of the Aspect rules, or other relevant rules from your
`WORKSPACE` or `MODULE.bazel` file:
- `rules_py` -> `1.11.2`
- `ty` -> `0.0.9`
- VSCode/Cursor extension: `astral-sh.ty@2026.36.0`

Language(s) and/or frameworks involved:

### How to reproduce

```shell
Create a simple ty.toml file

[src]
exclude = [
"pytest_test",
".pytest_main"
]

[rules]
unresolved-import = "ignore"
[environment]
python = ".python3.venv"

BUILD rules to generate the a minimal virtual environment:

load("@aspect_rules_py//py:defs.bzl", "py_binary")
load("@bazel_skylib//rules:write_file.bzl", "write_file")

write_file(
name = "dummy_script",
out = "dummy_script.py",
content = ["print('Hello, World!')"],
is_executable = True,
visibility = ["//visibility:private"],
)

py_binary(
name = "python3",
srcs = [":dummy_script"],
visibility = ["//visibility:private"],
)

Execute to create the virtual environment:

bazel run //:python3.venv

VSCode/Cursor settings for the ty extension:

"ty.path": ["/path/to/ty"],
"ty.configurationFile": "/path/to/ty.toml",

In VSCode/Cursor query for the client logs:

> ty: Show client logs

An error message along these lines should appear (go to `Console > Output > ty Language Server`):

2026-04-16 21:16:05.993043258 ERROR Failed to create project for workspace `file:///<>`: Failed to parse the `pyvenv.cfg` file at `/<>/bazel-out/<>/bin/.python3.venv/pyvenv.cfg` because the following error was encountered when trying to resolve the `home` value to a directory on disk: No such file or directory (os error 2). Falling back to default settings
```

### Any other information?

I was able to crudely patch things to make the path relative to the folder containing the virtual environment, rather than the virtual environment itself, which fixed the problem.

I don't have a great sense for if this would break other commonly used workflows, I assume you all would have some insight into this.
```diff
--- a/py/tools/py/src/pyvenv.cfg.tmpl
+++ b/py/tools/py/src/pyvenv.cfg.tmpl
@@ -1,4 +1,4 @@
-home = ./bin/
+home = {{HOME}}
implementation = CPython
version_info = {{MAJOR}}.{{MINOR}}.{{PATCH}}
include-system-site-packages = {{INCLUDE_SYSTEM_SITE}}

--- a/py/tools/py/src/venv.rs
+++ b/py/tools/py/src/venv.rs
@@ -341,9 +341,12 @@ aspect-runfiles-repo = {1}

// Create the `pyvenv.cfg` file
// FIXME: Should this come from the ruleset?
+ // NOTE(george): this takes the last two components of the home directory to yield the output: `/bin`
+ let home_dir: PathBuf = venv.home_dir.components().rev().take(2).collect::>().into_iter().collect();
fs::write(
&venv.home_dir.join("pyvenv.cfg"),
include_str!("pyvenv.cfg.tmpl")
+ .replace("{{HOME}}", &home_dir.to_str().unwrap())
.replace("{{MAJOR}}", &venv.version_info.major.to_string())
.replace("{{MINOR}}", &venv.version_info.minor.to_string())
.replace("{{PATCH}}", &venv.version_info.patch.to_string())
```

Contributor guide

Open the contributing guide

Research direction

Start with py/tools/py/src/pyvenv.cfg.tmpl and the virtual-environment generation in py/tools/py/src/venv.rs. Reproduce the Bazel-generated environment and inspect the ty language-server client logs in VSCode or Cursor. Done means the generated pyvenv.cfg resolves its home directory for the ty extension while preserving the existing virtual-environment workflow.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
build-system, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.