forked from microsoft/vscode-python-environments
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfastPath.ts
More file actions
105 lines (95 loc) · 3.95 KB
/
fastPath.ts
File metadata and controls
105 lines (95 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { Uri } from 'vscode';
import { GetEnvironmentScope, PythonEnvironment, PythonEnvironmentApi } from '../../api';
import { traceError, traceVerbose, traceWarn } from '../../common/logging';
import { createDeferred, Deferred } from '../../common/utils/deferred';
/**
* Options for the fast-path resolution in manager.get().
*/
export interface FastPathOptions {
/** The current _initialized deferred (may be undefined if init hasn't started). */
initialized: Deferred<void> | undefined;
/** Updates the manager's _initialized deferred. */
setInitialized: (initialized: Deferred<void> | undefined) => void;
/** The scope passed to get(). */
scope: GetEnvironmentScope;
/** Label for log messages, e.g. 'venv', 'conda'. */
label: string;
/** Gets the project fsPath for a given Uri scope. */
getProjectFsPath: (scope: Uri) => string;
/** Reads the persisted env path for a workspace fsPath. */
getPersistedPath: (workspaceFsPath: string) => Promise<string | undefined>;
/** Resolves a persisted path to a full PythonEnvironment. */
resolve: (persistedPath: string) => Promise<PythonEnvironment | undefined>;
/** Starts background initialization (full discovery). Returns a promise that completes when init is done. */
startBackgroundInit: () => Promise<void> | Thenable<void>;
}
/**
* Result from a successful fast-path resolution.
*/
export interface FastPathResult {
/** The resolved environment. */
env: PythonEnvironment;
}
/**
* Gets the fsPath for a scope by preferring the resolved project path when available.
*/
export function getProjectFsPathForScope(api: Pick<PythonEnvironmentApi, 'getPythonProject'>, scope: Uri): string {
return api.getPythonProject(scope)?.uri.fsPath ?? scope.fsPath;
}
/**
* Attempts fast-path resolution for manager.get(): if full initialization hasn't completed yet
* and there's a persisted environment for the workspace, resolve it directly via nativeFinder
* instead of waiting for full discovery.
*
* Returns the resolved environment (with an optional new deferred) if successful, or undefined
* to fall through to the normal init path.
*/
export async function tryFastPathGet(opts: FastPathOptions): Promise<FastPathResult | undefined> {
if (!(opts.scope instanceof Uri)) {
return undefined;
}
if (opts.initialized?.completed) {
return undefined;
}
let deferred = opts.initialized;
if (!deferred) {
deferred = createDeferred<void>();
opts.setInitialized(deferred);
const deferredRef = deferred;
try {
Promise.resolve(opts.startBackgroundInit()).then(
() => deferredRef.resolve(),
(err) => {
traceError(`[${opts.label}] Background initialization failed:`, err);
// Allow subsequent get()/initialize() calls to retry after a background init failure.
opts.setInitialized(undefined);
deferredRef.resolve();
},
);
} catch (syncErr) {
traceError(`[${opts.label}] Background initialization threw synchronously:`, syncErr);
opts.setInitialized(undefined);
deferredRef.resolve();
}
}
const fsPath = opts.getProjectFsPath(opts.scope);
const persistedPath = await opts.getPersistedPath(fsPath);
if (persistedPath) {
try {
const resolved = await opts.resolve(persistedPath);
if (resolved) {
return { env: resolved };
}
} catch (err) {
traceWarn(
`[${opts.label}] Fast path resolve failed for '${persistedPath}', falling back to full init:`,
err,
);
}
} else {
traceVerbose(`[${opts.label}] Fast path: no persisted path, falling through to slow path`);
}
return undefined;
}