Skip to content

Commit 4fd7f38

Browse files
author
Kartik Raj
committed
Code reviews
1 parent 37db846 commit 4fd7f38

File tree

2 files changed

+110
-90
lines changed

2 files changed

+110
-90
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
import { Event, EventEmitter } from 'vscode';
5+
import { PythonEnvInfo } from '../base/info';
6+
import {
7+
ILocator, IPythonEnvsIterator, PythonEnvUpdatedEvent, QueryForEvent,
8+
} from '../base/locator';
9+
import { PythonEnvsChangedEvent } from '../base/watcher';
10+
import { mergeEnvironments } from '../info';
11+
12+
type PythonEnvsIteratorState = {
13+
/**
14+
* Set to true when all information from incoming iterator has been received
15+
*/
16+
done: boolean;
17+
/**
18+
* Carries the number of pending background calls ongoing at the moment
19+
*/
20+
pending: number;
21+
};
22+
23+
export class PythonEnvsReducer implements ILocator {
24+
public get onChanged(): Event<PythonEnvsChangedEvent> {
25+
return this.pythonEnvsManager.onChanged;
26+
}
27+
28+
constructor(private readonly pythonEnvsManager: ILocator) {}
29+
30+
public resolveEnv(env: string | PythonEnvInfo): Promise<PythonEnvInfo | undefined> {
31+
return this.pythonEnvsManager.resolveEnv(env);
32+
}
33+
34+
public iterEnvs(query?: QueryForEvent<PythonEnvsChangedEvent>): IPythonEnvsIterator {
35+
const didUpdate = new EventEmitter<PythonEnvUpdatedEvent | null>();
36+
return { ...this.iterEnvsIterator(didUpdate, query), onUpdated: didUpdate.event };
37+
}
38+
39+
private async* iterEnvsIterator(
40+
didUpdate: EventEmitter<PythonEnvUpdatedEvent | null>,
41+
query?: QueryForEvent<PythonEnvsChangedEvent>,
42+
): AsyncIterator<PythonEnvInfo, void> {
43+
const state: PythonEnvsIteratorState = {
44+
done: false,
45+
pending: 0,
46+
};
47+
const seen: PythonEnvInfo[] = [];
48+
const iterator = this.pythonEnvsManager.iterEnvs(query);
49+
50+
if (iterator.onUpdated !== undefined) {
51+
iterator.onUpdated((event) => {
52+
if (event === null) {
53+
state.done = true;
54+
checkIfFinishedAndNotify(state, didUpdate);
55+
} else {
56+
const old = seen.find((s) => s.location === event.old.location);
57+
if (old !== undefined) {
58+
state.pending += 1;
59+
resolveDifferencesInBackground(old, event.new, state, didUpdate).ignoreErrors();
60+
}
61+
}
62+
});
63+
}
64+
65+
let result = await iterator.next();
66+
while (!result.done) {
67+
const currEnv = result.value;
68+
const old = seen.find((s) => s.location === currEnv.location);
69+
if (old !== undefined) {
70+
state.pending += 1;
71+
resolveDifferencesInBackground(old, currEnv, state, didUpdate).ignoreErrors();
72+
} else {
73+
yield currEnv;
74+
seen.push(currEnv);
75+
}
76+
// eslint-disable-next-line no-await-in-loop
77+
result = await iterator.next();
78+
}
79+
if (iterator.onUpdated === undefined) {
80+
state.done = true;
81+
}
82+
}
83+
}
84+
85+
async function resolveDifferencesInBackground(
86+
oldEnv: PythonEnvInfo,
87+
newEnv: PythonEnvInfo,
88+
state: PythonEnvsIteratorState,
89+
didUpdate: EventEmitter<PythonEnvUpdatedEvent | null>,
90+
) {
91+
const merged = mergeEnvironments([oldEnv, newEnv])[0];
92+
didUpdate.fire({ old: oldEnv, new: merged });
93+
state.pending -= 1;
94+
checkIfFinishedAndNotify(state, didUpdate);
95+
}
96+
97+
/**
98+
* When all info from incoming iterator has been received and all background calls finishes, notify that we're done
99+
* @param state Carries the current state of progress
100+
* @param didUpdate Used to notify when finished
101+
*/
102+
function checkIfFinishedAndNotify(
103+
state: PythonEnvsIteratorState,
104+
didUpdate: EventEmitter<PythonEnvUpdatedEvent | null>,
105+
) {
106+
if (state.done && state.pending === 0) {
107+
didUpdate.fire(null);
108+
didUpdate.dispose();
109+
}
110+
}

src/client/pythonEnvironments/environmentsReducer.ts

Lines changed: 0 additions & 90 deletions
This file was deleted.

0 commit comments

Comments
 (0)