fix: hide Python activity bar icon in non-Python workspaces - #1663
fix: hide Python activity bar icon in non-Python workspaces#1663Mohit Yadav (mohityadav8) wants to merge 6 commits into
Conversation
Fixes microsoft/vscode-python#26015 Added context key python-envs.workspaceHasPython via findFiles + FileSystemWatcher. ANDed into when clauses of the activitybar container and both views. Signed-off-by: Mohit Yadav <ymohit799057@gmail.com>
Eduardo Villalpando Mello (edvilme)
left a comment
There was a problem hiding this comment.
Thanks for your contributions!
LGTML :)
|
hi @edvilme Both CI failures are unrelated to this PR's changes: 1. 2. Integration test failure ( The failure is: 'Python 3.14.6.final.0-j5ae0pzs6ek' |
| "icon": "files/logo.svg", | ||
| "contextualTitle": "Python Projects", | ||
| "when": "config.python.useEnvironmentsExtension != false" | ||
| "when": "config.python.useEnvironmentsExtension != false && python-envs.workspaceHasPython" |
There was a problem hiding this comment.
The PR hides the activity-bar icon unless this context key is true:
python-envs.workspaceHasPython
That key is not defined initially. It only gets set after the extension’s activate() function runs:
registerWorkspacePythonContext(context.subscriptions);
However, package.json currently activates the extension only when VS Code opens a Python-language document:
"activationEvents": [ "onLanguage:python" ]
This creates a circular dependency:
- The extension must activate to detect Python files and set the context key.
- The activity-bar icon is hidden until that key is set.
- A hidden view cannot be opened to activate the extension.
- If no .py file is opened,
onLanguage:pythonnever activates the extension.
Example
A user opens a repository containing:
my-project/
├── pyproject.toml
├── requirements.txt
└── README.md
The repository is clearly a Python project, but the user has not opened a .py file yet.
Expected: The Python activity-bar icon appears because pyproject.toml identifies the workspace as Python.
Actual: The extension does not activate, so it never searches for pyproject.toml . The context key remains unset, and the icon stays hidden.
There was a problem hiding this comment.
Good catch. Fix is to add workspaceContains activation events to package.json so the extension activates even before a .py file is opened:
"activationEvents": [
"onLanguage:python",
"workspaceContains:**/*.py",
"workspaceContains:pyproject.toml",
"workspaceContains:requirements.txt",
"workspaceContains:Pipfile",
"workspaceContains:setup.py",
"workspaceContains:mspythonconfig.json",
"workspaceContains:.venv",
"workspaceContains:.conda"
]
This breaks the circular dependency - extension activates when any marker file is present in the workspace, sets the context key, and the icon appears without needing a .py file open first.
| const EXCLUDE = '**/{node_modules,.git,site-packages}/**'; | ||
|
|
||
| async function refresh(): Promise<void> { | ||
| const hits = await findFiles(MARKER_GLOB, EXCLUDE, 1); |
There was a problem hiding this comment.
Is this only searching inside open workspaces folders. What if user opens a standalone Python file without opening the folder?
There was a problem hiding this comment.
findFiles only searches workspace folders, so standalone file case is missed. Will add a fallback check on open text documents:
async function refresh(): Promise<void> {
const hits = await findFiles(MARKER_GLOB, EXCLUDE, 1);
if (hits.length > 0) {
await executeCommand('setContext', PYTHON_WORKSPACE_KEY, true);
return;
}
const hasPythonDoc = workspace.textDocuments.some(
(doc) => doc.languageId === 'python',
);
await executeCommand('setContext', PYTHON_WORKSPACE_KEY, hasPythonDoc);
}And subscribe to onDidOpenTextDocument in registerWorkspacePythonContext.
|
|
||
| export function registerWorkspacePythonContext(disposables: Disposable[]): void { | ||
| const watcher = createFileSystemWatcher(MARKER_GLOB, false, true, false); | ||
| disposables.push( |
There was a problem hiding this comment.
Is EXCLUDE only passed to findFiles() but not the createFileSystemWatchter? Does that mean the watcher still listens for every .py file created or deleted under site-packages? I am a bit worried about the perf here.
There was a problem hiding this comment.
Correct-- createFileSystemWatcher has no exclude parameter in the VS Code API, so it fires for site-packages too. Fix is to filter in the event handlers:
const EXCLUDE_RE = /[\\/](node_modules|\.git|site-packages)[\\/]/;
watcher.onDidCreate((uri) => { if (!EXCLUDE_RE.test(uri.fsPath)) void refresh(); }),
watcher.onDidDelete((uri) => { if (!EXCLUDE_RE.test(uri.fsPath)) void refresh(); }),This avoids unnecessary refresh() calls from excluded directories.
|
Hello Mohit Yadav (@mohityadav8) thanks for following on with the reviews. I think there is still one unresolved issue and a merge conflict before we can take another look :) |
Solve conflict can u please share what's the issue I forgot to see in workflow |
…oft#1651) > Part of microsoft#1602 (PEP 723 inline script env support). Design doc: microsoft#1601. > **Split for review (3 PRs).** Reviewers flagged the original PR 5 as too large, so it is split into three stacked PRs grouped by dependency layer: > - **5a — generic env-creation utilities — this PR (microsoft#1651).** Based on `main`; independent; merges first. > - **5b — inline-script cache + interpreter utilities — microsoft#1655.** Stacked on 5a. > - **5c — `create()` happy path (manager + wiring) — microsoft#1656.** Stacked on 5b. > > Applied together the three PRs are byte-for-byte identical to the original single change. **Merge order: 5a → 5b → 5c.** ### Roadmap context This is the first slice of **PR 5 of 16** in the PEP 723 inline-script roadmap. The full plan lives in microsoft#1602. | Phase | PR | Status | |---|---|---| | **Phase 1: Foundation** | PR 1: cache key hash utility | merged (microsoft#1634) | | | PR 2: cache layout + `meta.json` sidecar | merged (microsoft#1635) | | | PR 3: `requires-python` to interpreter selection | merged (microsoft#1636) | | **Phase 2: Manager** | PR 4: `InlineScriptEnvManager` skeleton | merged (microsoft#1610) | | | **PR 5a: generic env-creation utilities** | **this PR (microsoft#1651)** | | | **PR 5b: inline-script cache + interpreter utilities** | **microsoft#1655** | | | **PR 5c: `create()` happy path (manager + wiring)** | **microsoft#1656** | | | PR 6: `create()` uv-install fallback | not started (needs 3, 5) | | | PR 7: persistence with `get`, `set`, and Memento | not started (needs 4) | | | PR 8: activation-time discovery | not started (needs 2, 4, 7) | | **Phase 3: Routing** | PR 9: route PEP 723 scripts to the inline manager | not started (needs 4, 7) | | | PR 10: per-script project registration | not started (needs 9) | | **Phase 4+: UX / lifecycle** | PRs 11-16 | not started | ### Why this PR PR 5c implements `InlineScriptEnvManager.create()`. Before touching the manager, this PR lands the **generic, reusable primitives** it relies on — a cross-process file lock, a venv Python-path helper, a cancellation-hardened process runner, and two small `createWithProgress` options. None of this code is inline-script-specific, so it is reviewed on its own. ### What this PR adds **Cross-process file lock** (`src/common/lockfile.apis.ts`, new): `acquireFileLock` uses an atomic `mkdir` of a `<path>.lock` directory plus a per-owner marker file, returning `AcquiredFileLock { release, retain }`. `retain()` writes a `retained` marker so a later acquirer **fails fast with `ELOCKRETAINED`** instead of waiting out the 5-minute timeout — used when a build is cancelled mid-flight. Distinct error codes (`ELOCKED`, `ELOCKRETAINED`, `ELOCKORPHANED`, `ECOMPROMISED`, `ERETAINFAILED`) separate contention from corruption. **Shared `getVenvPythonPath`** (`src/common/utils/virtualEnvironment.ts`, new): returns `Scripts\python.exe` on Windows, else `bin/python`. Replaces an inline copy in `venvUtils` and is reused by 5b/5c. **Hardened process helper** (`src/managers/builtin/helpers.ts`): `runUV` and `runPython` now share one `runProcess` implementation whose cancellation guards `kill()` in `try/catch` and still emits a clean `CancellationError` if the process errors after a cancel. Per-caller options preserve existing behavior (`collectStderr`, `logPrefix`). **`venvUtils.ts`:** `createWithProgress` gains `CreateWithProgressOptions { trackUvEnvironment }`, and `CreateEnvironmentResult` gains `pkgInstallationCancelled` so a caller can tell cancellation apart from a real install failure. Existing callers are unaffected (both are optional / additive). ### Tests - **`lockfile.apis.unit.test.ts`** — 9 tests: contention, retain/fail-fast, orphaned and compromised locks, and timeout. - **`virtualEnvironment.unit.test.ts`** — 2 tests for `getVenvPythonPath` on Windows and POSIX. - **`helpers.cancellation.unit.test.ts`** — 4 tests for `runProcess` cancellation safety. - **`venvUtils.createWithProgress.unit.test.ts`** — 3 tests for `trackUvEnvironment` and `pkgInstallationCancelled`. On this branch alone `npm run compile-tests` is clean and `npm run unittest` reports **1447 passing, 0 failing, 4 pending**. ### User impact **None.** These are internal primitives with no new user-visible behavior. The refactors to `helpers.ts` and `venvUtils.ts` are behavior-preserving for existing callers. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 39dcc6a3-0fbd-4f36-9d0f-68677de49c27
## Summary - remove the extension-level Marketplace preview designation - remove stale README language about the completed rollout - retain labels for individual features that are still experimental Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…#1670) The `version-match` CI job blocked release PRs (e.g. microsoft#1668) whenever the extension and API package versions diverged. These versions should be independent — the API package is separately published and versioned. ## Changes - **`api/package.json`** — Reset version `1.37.0` → `1.0.0` - **`api/package-lock.json`** — Reset both root-level and `packages[""]` version fields to match - **`.github/workflows/pr-file-check.yml`** — Remove the `version-match` job entirely; the check requiring `api/package.json` to be bumped on public API changes (`src/api.ts`) is preserved --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
…ironments into fix/conditional-activity-bar-icon-v2
5a4705f to
f922e06
Compare
Signed-off-by: Mohit Yadav <ymohit799057@gmail.com>
Fixes microsoft/vscode-python#26015
Added context key python-envs.workspaceHasPython via findFiles + FileSystemWatcher. ANDed into when clauses of the activitybar container and both views.