Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/extensionApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ export class PythonEnvironmentApiImpl implements PythonEnvironmentApi {
}
return this.envManagers.getLastKnownEnvironment(currentScope);
}
getEnvironmentSync(scope: GetEnvironmentScope): PythonEnvironment | undefined {
const currentScope = checkUri(scope) as GetEnvironmentScope;
return this.envManagers.getLastKnownEnvironment(currentScope);
}
onDidChangeEnvironment: Event<DidChangeEnvironmentEventArgs> = this._onDidChangeEnvironment.event;
async resolveEnvironment(context: ResolveEnvironmentContext): Promise<PythonEnvironment | undefined> {
await waitForAllEnvManagers();
Expand Down
64 changes: 64 additions & 0 deletions src/test/extensionApi.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,67 @@ suite('PythonEnvironmentApiImpl - package resolution', () => {
assert.ok(manage.calledOnceWithExactly(environment, { install: ['example'] }));
});
});

suite('PythonEnvironmentApiImpl - getEnvironmentSync', () => {
type ApiArgs = ConstructorParameters<typeof PythonEnvironmentApiImpl>;
const workspaceUri = Uri.joinPath(Uri.file(process.cwd()), 'workspace');
const environmentUri = Uri.joinPath(workspaceUri, '.venv');
const scope = Uri.joinPath(workspaceUri, 'script.py');
const lastKnown = {
envId: { id: 'selected', managerId: 'ms-python.python:venv' },
name: 'selected',
displayName: 'selected',
displayPath: environmentUri.fsPath,
version: '3.12.0',
environmentPath: environmentUri,
execInfo: { run: { executable: Uri.joinPath(environmentUri, 'python').fsPath, args: [] } },
sysPrefix: environmentUri.fsPath,
} as PythonEnvironment;

function createApi(environment: PythonEnvironment | undefined): {
api: PythonEnvironmentApiImpl;
getLastKnownEnvironment: sinon.SinonStub;
} {
const getLastKnownEnvironment = sinon.stub().returns(environment);
const api = new PythonEnvironmentApiImpl(
{
onDidChangeActiveEnvironment: new EventEmitter().event,
onDidChangePackageProviderPackages: new EventEmitter().event,
getLastKnownEnvironment,
} as unknown as ApiArgs[0],
{
getProjects: () => [],
onDidChangeProjects: new EventEmitter<void>().event,
} as unknown as ApiArgs[1],
{} as unknown as ApiArgs[2],
{} as unknown as ApiArgs[3],
{ onDidChangeEnvironmentVariables: new EventEmitter().event } as unknown as ApiArgs[4],
);
return { api, getLastKnownEnvironment };
}

teardown(() => {
sinon.restore();
});

test('returns the last-known environment without waiting for manager readiness', () => {
const { api, getLastKnownEnvironment } = createApi(lastKnown);

assert.strictEqual(api.getEnvironmentSync(scope), lastKnown);
sinon.assert.calledOnceWithExactly(getLastKnownEnvironment, scope);
});

test('returns the last-known global environment', () => {
const { api, getLastKnownEnvironment } = createApi(lastKnown);

assert.strictEqual(api.getEnvironmentSync(undefined), lastKnown);
sinon.assert.calledOnceWithExactly(getLastKnownEnvironment, undefined);
});

test('returns undefined when no environment has been resolved', () => {
const { api, getLastKnownEnvironment } = createApi(undefined);

assert.strictEqual(api.getEnvironmentSync(scope), undefined);
sinon.assert.calledOnceWithExactly(getLastKnownEnvironment, scope);
});
});
8 changes: 8 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,14 @@ export interface PythonProjectEnvironmentApi {
*/
getEnvironment(scope: GetEnvironmentScope): Promise<PythonEnvironment | undefined>;

/**
* Synchronously retrieves the last-known Python environment within the specified scope.
* This does not trigger environment discovery or refresh.
* @param scope - The scope within which to retrieve the environment.
* @returns The last-known Python environment, or undefined if none has been resolved.
*/
getEnvironmentSync(scope: GetEnvironmentScope): PythonEnvironment | undefined;

/**
* Event that is fired when the selected Python environment changes for Project, Folder or File.
* @see {@link DidChangeEnvironmentEventArgs}
Expand Down
Loading