Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Modify resolveEnv()
  • Loading branch information
Kartik Raj
Kartik Raj committed Sep 22, 2020
commit 3b24031d8c043225f2e569ff811321b7db556ad7
19 changes: 14 additions & 5 deletions src/client/pythonEnvironments/base/info/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,22 @@ export type PythonEnvInfo = _PythonEnvInfo & {
* @param environment2 - one of the two envs to compare
*/
export function areSameEnvironment(
Comment thread
karthiknadig marked this conversation as resolved.
Resolved
Comment thread
karrtikr marked this conversation as resolved.
Resolved
environment1: PythonEnvInfo,
environment2: PythonEnvInfo,
environment1: PythonEnvInfo | string,
environment2: PythonEnvInfo | string,
): boolean {
if (!environment1 || !environment2) {
return false;
let path1: string;
let path2: string;
if (typeof environment1 === 'string') {
path1 = environment1;
} else {
path1 = environment1.executable.filename;
}
if (arePathsSame(environment1.executable.filename, environment2.executable.filename)) {
if (typeof environment2 === 'string') {
path2 = environment2;
} else {
path2 = environment2.executable.filename;
}
if (arePathsSame(path1, path2)) {
return true;
}
return false;
Expand Down
27 changes: 25 additions & 2 deletions src/client/pythonEnvironments/collection/environmentsReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { cloneDeep, isEqual } from 'lodash';
import { Event, EventEmitter } from 'vscode';
import { traceVerbose } from '../../common/logger';
import { createDeferred } from '../../common/utils/async';
import { areSameEnvironment, PythonEnvInfo, PythonEnvKind } from '../base/info';
import {
ILocator, IPythonEnvsIterator, PythonEnvUpdatedEvent, QueryForEvent,
Expand All @@ -20,8 +21,30 @@ export class PythonEnvsReducer implements ILocator {

constructor(private readonly pythonEnvsManager: ILocator) {}
Comment thread
karrtikr marked this conversation as resolved.
Resolved

public resolveEnv(env: string | PythonEnvInfo): Promise<PythonEnvInfo | undefined> {
return this.pythonEnvsManager.resolveEnv(env);
public async resolveEnv(env: string | PythonEnvInfo): Promise<PythonEnvInfo | undefined> {
let environment: PythonEnvInfo | undefined;
const waitForUpdatesDeferred = createDeferred<void>();
const iterator = this.iterEnvs();
iterator.onUpdated!((event) => {
if (event === null) {
waitForUpdatesDeferred.resolve();
} else if (environment && areSameEnvironment(environment, event.new)) {
environment = event.new;
}
});
let result = await iterator.next();
while (!result.done) {
if (areSameEnvironment(result.value, env)) {
environment = result.value;
}
// eslint-disable-next-line no-await-in-loop
result = await iterator.next();
}
if (!environment) {
return undefined;
}
await waitForUpdatesDeferred.promise;
return this.pythonEnvsManager.resolveEnv(environment);
Comment thread
karrtikr marked this conversation as resolved.
Resolved
}

public iterEnvs(query?: QueryForEvent<PythonEnvsChangedEvent>): IPythonEnvsIterator {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import { createEnv, getEnvs, SimpleLocator } from '../base/common';
suite('Environments Reducer', () => {
suite('iterEnvs()', () => {
test('Iterator only yields unique environments', async () => {
const env1 = createEnv('env1', '3.5.12b1', PythonEnvKind.Venv, path.join('path', 'to', 'exec1'));
const env2 = createEnv('env2', '3.8.1', PythonEnvKind.Conda, path.join('path', 'to', 'exec2'));
const env1 = createEnv('env1', '3.5', PythonEnvKind.Venv, path.join('path', 'to', 'exec1'));
const env2 = createEnv('env2', '3.8', PythonEnvKind.Conda, path.join('path', 'to', 'exec2'));
const env3 = createEnv('env3', '2.7', PythonEnvKind.System, path.join('path', 'to', 'exec3'));
const env4 = createEnv('env4', '3.9.0rc2', PythonEnvKind.Unknown, path.join('path', 'to', 'exec2')); // Same as env2
const env5 = createEnv('env5', '3.8', PythonEnvKind.Venv, path.join('path', 'to', 'exec1')); // Same as env1
const env4 = createEnv('env4', '3.8.1', PythonEnvKind.Unknown, path.join('path', 'to', 'exec2')); // Same as env2
const env5 = createEnv('env5', '3.5.12b1', PythonEnvKind.Venv, path.join('path', 'to', 'exec1')); // Same as env1
const environmentsToBeIterated = [env1, env2, env3, env4, env5]; // Contains 3 unique environments
const pythonEnvManager = new SimpleLocator(environmentsToBeIterated);
const reducer = new PythonEnvsReducer(pythonEnvManager);
Expand All @@ -36,11 +36,11 @@ suite('Environments Reducer', () => {

test('Single updates for multiple environments are sent correctly followed by the null event', async () => {
// Arrange
const env1 = createEnv('env1', '3.5.12b1', PythonEnvKind.Unknown, path.join('path', 'to', 'exec1'));
const env2 = createEnv('env2', '3.8.1', PythonEnvKind.Unknown, path.join('path', 'to', 'exec2'));
const env1 = createEnv('env1', '3.5', PythonEnvKind.Unknown, path.join('path', 'to', 'exec1'));
const env2 = createEnv('env2', '3.8', PythonEnvKind.Unknown, path.join('path', 'to', 'exec2'));
const env3 = createEnv('env3', '2.7', PythonEnvKind.System, path.join('path', 'to', 'exec3'));
const env4 = createEnv('env4', '3.9.0rc2', PythonEnvKind.Conda, path.join('path', 'to', 'exec2')); // Same as env2;
const env5 = createEnv('env5', '3.8', PythonEnvKind.Venv, path.join('path', 'to', 'exec1')); // Same as env1;
const env4 = createEnv('env4', '3.8.1', PythonEnvKind.Conda, path.join('path', 'to', 'exec2')); // Same as env2;
const env5 = createEnv('env5', '3.5.12b1', PythonEnvKind.Venv, path.join('path', 'to', 'exec1')); // Same as env1;
const environmentsToBeIterated = [env1, env2, env3, env4, env5]; // Contains 3 unique environments
const pythonEnvManager = new SimpleLocator(environmentsToBeIterated);
const onUpdatedEvents: (PythonEnvUpdatedEvent | null)[] = [];
Expand Down Expand Up @@ -160,21 +160,59 @@ suite('Environments Reducer', () => {
assert.deepEqual(events, expected);
});

test('Calls locator manager to resolves environments', async () => {
const env = createEnv('env1', '3.8', PythonEnvKind.Unknown, path.join('path', 'to', 'exec'));
const resolvedEnv = createEnv('env1', '3.8.1', PythonEnvKind.Conda, 'resolved/path/to/exec');
const pythonEnvManager = new SimpleLocator([], {
resolve: async (e: PythonEnvInfo) => {
if (e === env) {
return resolvedEnv;
}
return undefined;
},
suite('resolveEnv()', () => {
test('Iterates environments from the reducer to get resolved environment, then calls into locator manager to resolve environment further and return it', async () => {
const env1 = createEnv('env1', '3.8', PythonEnvKind.Unknown, path.join('path', 'to', 'exec'));
const env2 = createEnv('env2', '2.7', PythonEnvKind.System, path.join('path', 'to', 'exec3'));
const env3 = createEnv('env3', '3.8.1', PythonEnvKind.Conda, path.join('path', 'to', 'exec'));
const env4 = createEnv('env4', '3.8.1', PythonEnvKind.Conda, path.join('path', 'to', 'exec2'));
const env5 = createEnv('env5', '3.5.12b1', PythonEnvKind.Venv, path.join('path', 'to', 'exec1'));
const env6 = createEnv('env6', '3.8.1', PythonEnvKind.System, path.join('path', 'to', 'exec'));
const environmentsToBeIterated = [env1, env2, env3, env4, env5, env6]; // env1 env3 env6 are same

const env13 = mergeEnvironments(env1, env3);
const env136 = mergeEnvironments(env13, env6);
const expectedResolvedEnv = createEnv('resolvedEnv', '3.8.1', PythonEnvKind.Conda, 'resolved/path/to/exec');
const pythonEnvManager = new SimpleLocator(environmentsToBeIterated, {
resolve: async (e: PythonEnvInfo) => {
if (isEqual(e, env136)) {
return expectedResolvedEnv;
}
return undefined;
},
});
const reducer = new PythonEnvsReducer(pythonEnvManager);

// Trying to resolve the environment corresponding to env1 env3 env6
const expected = await reducer.resolveEnv(path.join('path', 'to', 'exec'));

assert.deepEqual(expected, expectedResolvedEnv);
});
const reducer = new PythonEnvsReducer(pythonEnvManager);

const expected = await reducer.resolveEnv(env);
test("If the reducer isn't able to resolve environment, return undefined", async () => {
const env1 = createEnv('env1', '3.8', PythonEnvKind.Unknown, path.join('path', 'to', 'exec'));
const env2 = createEnv('env2', '2.7', PythonEnvKind.System, path.join('path', 'to', 'exec3'));
const env3 = createEnv('env3', '3.8.1', PythonEnvKind.Conda, path.join('path', 'to', 'exec'));
const env4 = createEnv('env4', '3.8.1', PythonEnvKind.Conda, path.join('path', 'to', 'exec2'));
const env5 = createEnv('env5', '3.5.12b1', PythonEnvKind.Venv, path.join('path', 'to', 'exec1'));
const env6 = createEnv('env6', '3.8.1', PythonEnvKind.System, path.join('path', 'to', 'exec'));
const environmentsToBeIterated = [env1, env2, env3, env4, env5, env6]; // env1 env3 env6 are same

const env13 = mergeEnvironments(env1, env3);
const env136 = mergeEnvironments(env13, env6);
const pythonEnvManager = new SimpleLocator(environmentsToBeIterated, {
resolve: async (e: PythonEnvInfo) => {
if (isEqual(e, env136)) {
return createEnv('resolvedEnv', '3.8.1', PythonEnvKind.Conda, 'resolved/path/to/exec');
}
return undefined;
},
});
const reducer = new PythonEnvsReducer(pythonEnvManager);

const expected = await reducer.resolveEnv(path.join('path', 'to', 'execNeverSeenBefore'));

assert.deepEqual(expected, resolvedEnv);
assert.deepEqual(expected, undefined);
});
});
});