Skip to content

Register PEP 723 scripts as exact projects (PEP 723 PR 10/16) - #1744

Open
Stella Huang (StellaHuang95) wants to merge 1 commit into
microsoft:mainfrom
StellaHuang95:copilot/pep723-pr10-wave1a
Open

Register PEP 723 scripts as exact projects (PEP 723 PR 10/16)#1744
Stella Huang (StellaHuang95) wants to merge 1 commit into
microsoft:mainfrom
StellaHuang95:copilot/pep723-pr10-wave1a

Conversation

@StellaHuang95

@StellaHuang95 Stella Huang (StellaHuang95) commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Part of #1602 (PEP 723 inline script env support). Design doc: #1601.

Roadmap context

This is PR 10 of 16 in the PEP 723 inline-script roadmap. PRs 7-9 persist, discover, validate, and route per-script environments; this PR gives each configured script an exact project identity that survives restart and can be consumed by per-file integrations.

Phase 3 / integration PR Status
PR 7: per-script persistence merged (#1697)
PR 8: activation-time discovery merged (#1722)
PR 9: automatic per-script routing merged (#1729)
PR 10: exact script project registration this PR
PRs 11-12: CodeLens and bulk setup UX follow-up
PR 17: Pylance per-file Python path microsoft/pyrx#9265
PR 19: Python extension per-file lookup microsoft/vscode-python#26129

Why this PR

PR 9 can route a saved script to a validated inline environment, but the project manager still identifies the script through its containing workspace project. That prevents the per-file identity from surviving restart consistently and leaves downstream configuration and environment-change consumers without an exact script scope.

The registration also needs an ownership boundary: clearing inline environments must remove entries created by the extension without deleting user-authored project settings.

What this PR does

  • Registers an exact pythonProjects entry before binding an inline environment.
  • Stores the normal environment and package manager as the script's fallback rather than replacing them with the inline manager.
  • Marks extension-managed entries as either:
    • created: remove the entry during inline cleanup;
    • adopted: remove only the marker and preserve the user's entry.
  • Ignores the managed fallback entry while a validated inline association is routeable.
  • Uses that entry normally when the feature is disabled or the association becomes stale.
  • Rolls back a newly prepared registration if inline association binding fails.
  • Supports single and batch script selection.
  • Converts a managed entry into an ordinary user-owned entry when the user explicitly selects a non-inline manager.
  • Coordinates explicit managed selections with the dedicated clear-cache operation.
  • Resolves and updates same-named scripts correctly in multi-root workspaces.

Registration and cleanup semantics

Condition Behavior
No exact project entry exists Create a marked entry containing the ordinary fallback managers
An exact user entry exists Temporarily mark it without changing its manager choices
Inline binding fails Roll back the marker/created entry and any newly added in-memory project
Validated association exists Route through the inline manager
Association is stale or unavailable Use the stored fallback manager
User selects a non-inline manager Update the owning setting and remove the managed marker
Clear Script Environment Cache Remove created entries; restore adopted entries
Two roots contain the same relative script path Match using the workspace discriminator

Performance and safety

  • No workspace scan is introduced.
  • Configuration writes occur only during explicit persisted selection, rollback, manager changes, or dedicated cache cleanup.
  • Serialization is limited to managed inline-script project mutations; unrelated environment routing and refresh operations are not queued.
  • User-owned project settings are never deleted by inline cleanup.

User impact

The feature remains behind python-envs.inlineScripts.enabled. Existing users and projects without a managed inline-script entry retain their current manager-selection behavior. After setup, a script has a stable exact project scope across reloads; when inline routing is unavailable, its previous project/workspace environment remains the fallback.

Tests

  • npm run compile-tests
  • npm run compile
  • npm run lint
  • Focused command, environment-manager, and settings tests: 92 passing
  • The full unit suite was also run. Six unchanged timing-sensitive inline-manager tests failed only under full-suite load and passed together in an isolated rerun.

Scope and follow-up

This PR does not add the setup CodeLens, bulk setup command, TTL eviction, or public feature enablement. Those remain in PRs 11, 12, and 14. Per-file language-service and debugger integration are handled by the companion cross-repository PRs above.

@rchiodo

Rich Chiodo (rchiodo) commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

🔒 Automated review in progress — Rich Chiodo (@rchiodo) is auto-reviewing this PR.

if (!project || normalizePath(project.uri.fsPath) !== normalizePath(scope.fsPath)) {
return undefined;
}
const exactSetting = getExactPythonProjectSetting(this.pm, scope);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning · Non-blocking recommendation

This ignores the managed exact-project setting unconditionally, so once inline routing becomes stale or disabled, manager resolution falls through to the workspace default rather than the stored fallback. Only bypass this setting while inline routing is active, and cover a case where the fallback and workspace-default manager IDs differ.

return workspaceApis.getWorkspaceFile()
? ConfigurationTarget.WorkspaceFolder
: ConfigurationTarget.Workspace;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning · Non-blocking recommendation

Selecting a target based on whether it contains any entries can miss a matching user project at another target; for example, an unrelated workspace-folder entry causes a matching workspace entry to be shadowed by a new created entry. Search defined targets for the matching project first, then choose a target only when creating a genuinely new entry; cover this mixed-scope case with a stateful test.

return scopes.some((uri) =>
getManagedInlineScriptProjectRegistration(getExactPythonProjectSetting(this.pm, uri)),
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning · Non-blocking recommendation

A non-inline selection issued immediately after an inline selection can bypass this queue because the managed marker is installed asynchronously, allowing invocation order to be lost. Track pending inline scopes synchronously or serialize all persisted exact-script selections, and test by pausing registration before issuing the ordinary selection.

@rchiodo

Copy link
Copy Markdown
Contributor

Verification: The relevant tests could not be fully run in the isolated environment; this review is not fully verified.

Result: could-not-verify

Summary: Verification could not run because no trusted sandbox image is configured for this repository, and local execution was not authorized. The three focused unit suites were therefore not run. I identified 12 tests added by the PR covering registration, rollback, fallback routing, cleanup, and multi-root behavior. Runtime confidence remains low until the sandbox configuration is available.

Test runs: 4 not run

  • ⚠️ Not run | Clear Script Environment Cache Command Tests | npm run unittest -- --grep "Clear Script Environment Cache Command Tests"
  • ⚠️ Not run | PythonEnvironmentManagers getLastKnownEnvironment | npm run unittest -- --grep "PythonEnvironmentManagers getLastKnownEnvironment"
  • ⚠️ Not run | Setting Helpers - Project Removal | npm run unittest -- --grep "Setting Helpers - Project Removal"
  • ⚠️ Not run | Verification environment preflight | git diff --name-status upstream/main...HEAD && printf '\nnode_modules: ' && if [ -d node_modules ]; then echo present; else echo missing; fi && printf 'compiled tests: ' && if [ -f out/test/features/envManagers.lastKnown.unit.test.js ]; then echo present; else echo missing; fi && printf '\nAdded test declarations:\n' && git diff --unified=0 upstream/main...HEAD -- 'src/test/**/*.ts' | grep '^+.*test(' | sed 's/^+//'
⚠️ Clear Script Environment Cache Command Tests diagnostic output
Container verification could not start: no trusted sandbox image is configured for microsoft/vscode-python-environments.
⚠️ PythonEnvironmentManagers getLastKnownEnvironment diagnostic output
Container verification could not start: no trusted sandbox image is configured for microsoft/vscode-python-environments.
⚠️ Setting Helpers - Project Removal diagnostic output
Container verification could not start: no trusted sandbox image is configured for microsoft/vscode-python-environments.
⚠️ Verification environment preflight diagnostic output
Container verification could not start and local execution was not authorized. No trusted sandbox image is configured for microsoft/vscode-python-environments.

@rchiodo Rich Chiodo (rchiodo) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

@rchiodo Rich Chiodo (rchiodo) added the review-auto:approved Automated review: no blocking findings (approval posted). label Aug 28, 2026
Persist extension-managed per-script project entries while preserving ordinary fallback settings and user-owned entries. Coordinate registration, rollback, explicit manager changes, and cache cleanup.

Part of microsoft#1602.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Stella Huang (StellaHuang95) added a commit to StellaHuang95/vscode-python-environments that referenced this pull request Aug 29, 2026
Update sections 6, 7, 9, and 10 to reflect what was actually built and
the in-flight PRs (vscode-python-environments microsoft#1744/microsoft#1745, pyrx #9265,
vscode-python #26129):

- Q6: dedicated InlineScriptAssociationStore + metadata-identity
  binding (pending/matched) instead of reusing VenvManager persistence;
  clarify pythonProjects[] is user-visible registration, not routing.
- Q7: TTL runs once per session (runTtlEvictionOnce) and protects
  entries referenced by a live association (PR microsoft#1745).
- Q9: Pylance re-routes via the existing didChangeConfiguration signal
  (_revalidateOpenRegularFiles / revalidateWorkspaceForFile), so PR 18's
  dedicated notification is optional; fix persistence/event-source bullets.
- Q10: correct the '~10 LOC' estimate to the real exactResource +
  __pythonIsProgramInterpreter + middleware change; add useEnvExtension
  gating caveat for Run and Debug.

Add a status banner noting the doc was revised post-implementation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature-request Request for new features or functionality review-auto:approved Automated review: no blocking findings (approval posted).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants