|
3 | 3 | // Copyright (c) Microsoft Corporation. All rights reserved.
|
4 | 4 | // Licensed under the MIT License.
|
5 | 5 |
|
6 |
| -import { EventEmitter } from 'vscode'; |
7 | 6 | import { PythonEnvKind, PythonEnvSource } from '../../info';
|
8 |
| -import { |
9 |
| - BasicEnvInfo, |
10 |
| - IPythonEnvsIterator, |
11 |
| - Locator, |
12 |
| - ProgressNotificationEvent, |
13 |
| - ProgressReportStage, |
14 |
| - PythonEnvUpdatedEvent, |
15 |
| -} from '../../locator'; |
| 7 | +import { BasicEnvInfo, IPythonEnvsIterator, Locator, PythonLocatorQuery, IEmitter } from '../../locator'; |
16 | 8 | import { getRegistryInterpreters } from '../../../common/windowsUtils';
|
17 | 9 | import { traceError, traceVerbose } from '../../../../logging';
|
18 | 10 | import { isMicrosoftStoreDir } from '../../../common/environmentManagers/microsoftStoreEnv';
|
19 | 11 | import { inExperiment } from '../../../common/externalDependencies';
|
20 | 12 | import { DiscoveryUsingWorkers } from '../../../../common/experiments/groups';
|
| 13 | +import { PythonEnvsChangedEvent } from '../../watcher'; |
| 14 | + |
| 15 | +export const WINDOWS_REG_PROVIDER_ID = 'windows-registry'; |
21 | 16 |
|
22 | 17 | export class WindowsRegistryLocator extends Locator<BasicEnvInfo> {
|
23 |
| - public readonly providerId: string = 'windows-registry'; |
| 18 | + public readonly providerId: string = WINDOWS_REG_PROVIDER_ID; |
24 | 19 |
|
25 | 20 | // eslint-disable-next-line class-methods-use-this
|
26 | 21 | public iterEnvs(
|
27 |
| - _?: unknown, |
| 22 | + query?: PythonLocatorQuery, |
28 | 23 | useWorkerThreads = inExperiment(DiscoveryUsingWorkers.experiment),
|
29 | 24 | ): IPythonEnvsIterator<BasicEnvInfo> {
|
30 |
| - const didUpdate = new EventEmitter<PythonEnvUpdatedEvent<BasicEnvInfo> | ProgressNotificationEvent>(); |
31 |
| - const iterator = useWorkerThreads ? iterEnvsIterator(didUpdate) : oldIterEnvsIterator(); |
32 | 25 | if (useWorkerThreads) {
|
33 |
| - iterator.onUpdated = didUpdate.event; |
| 26 | + /** |
| 27 | + * Windows registry is slow and often not necessary, so notify completion immediately, but use watcher |
| 28 | + * change events to signal for any new envs which are found. |
| 29 | + */ |
| 30 | + if (query?.providerId === this.providerId) { |
| 31 | + // Query via change event, so iterate all envs. |
| 32 | + return iterateEnvs(true); |
| 33 | + } |
| 34 | + return iterateEnvsLazily(this.emitter); |
34 | 35 | }
|
35 |
| - return iterator; |
| 36 | + return iterateEnvs(false); |
36 | 37 | }
|
37 | 38 | }
|
38 | 39 |
|
39 |
| -/** |
40 |
| - * Windows registry is slow and often not necessary, so notify completion immediately, while still updating lazily as we find stuff. |
41 |
| - * To accomplish this, use an empty iterator while lazily firing environments using updates. |
42 |
| - */ |
43 |
| -async function* iterEnvsIterator( |
44 |
| - didUpdate: EventEmitter<PythonEnvUpdatedEvent<BasicEnvInfo> | ProgressNotificationEvent>, |
45 |
| -): IPythonEnvsIterator<BasicEnvInfo> { |
46 |
| - updateLazily(didUpdate).ignoreErrors(); |
| 40 | +async function* iterateEnvsLazily(changed: IEmitter<PythonEnvsChangedEvent>): IPythonEnvsIterator<BasicEnvInfo> { |
| 41 | + loadAllEnvs(changed).ignoreErrors(); |
47 | 42 | }
|
48 | 43 |
|
49 |
| -async function updateLazily(didUpdate: EventEmitter<PythonEnvUpdatedEvent<BasicEnvInfo> | ProgressNotificationEvent>) { |
| 44 | +async function loadAllEnvs(changed: IEmitter<PythonEnvsChangedEvent>) { |
50 | 45 | traceVerbose('Searching for windows registry interpreters');
|
51 |
| - const interpreters = await getRegistryInterpreters(true); |
52 |
| - for (const interpreter of interpreters) { |
53 |
| - try { |
54 |
| - // Filter out Microsoft Store app directories. We have a store app locator that handles this. |
55 |
| - // The python.exe available in these directories might not be python. It can be a store install |
56 |
| - // shortcut that takes you to microsoft store. |
57 |
| - if (isMicrosoftStoreDir(interpreter.interpreterPath)) { |
58 |
| - continue; |
59 |
| - } |
60 |
| - const env: BasicEnvInfo = { |
61 |
| - kind: PythonEnvKind.OtherGlobal, |
62 |
| - executablePath: interpreter.interpreterPath, |
63 |
| - source: [PythonEnvSource.WindowsRegistry], |
64 |
| - }; |
65 |
| - didUpdate.fire({ update: env }); |
66 |
| - } catch (ex) { |
67 |
| - traceError(`Failed to process environment: ${interpreter}`, ex); |
68 |
| - } |
69 |
| - } |
70 |
| - didUpdate.fire({ stage: ProgressReportStage.discoveryFinished }); |
| 46 | + await getRegistryInterpreters(true); |
| 47 | + changed.fire({ providerId: WINDOWS_REG_PROVIDER_ID }); |
71 | 48 | traceVerbose('Finished searching for windows registry interpreters');
|
72 | 49 | }
|
73 | 50 |
|
74 |
| -async function* oldIterEnvsIterator(): IPythonEnvsIterator<BasicEnvInfo> { |
75 |
| - const interpreters = await getRegistryInterpreters(false); |
| 51 | +async function* iterateEnvs(useWorkerThreads: boolean): IPythonEnvsIterator<BasicEnvInfo> { |
| 52 | + const interpreters = await getRegistryInterpreters(useWorkerThreads); |
76 | 53 | for (const interpreter of interpreters) {
|
77 | 54 | try {
|
78 | 55 | // Filter out Microsoft Store app directories. We have a store app locator that handles this.
|
|
0 commit comments