diff --git a/.vscode/launch.json b/.vscode/launch.json index 152ef1c87f60..e6cbeb231743 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,7 +12,7 @@ "smartStep": true, "sourceMaps": true, "outFiles": ["${workspaceFolder}/out/**/*", "!${workspaceFolder}/**/node_modules**/*"], - "preLaunchTask": "Compile", + // "preLaunchTask": "Compile", "skipFiles": ["/**"], "env": { // Enable this to turn on redux logging during debugging diff --git a/one.js b/one.js new file mode 100644 index 000000000000..aceecffa6900 --- /dev/null +++ b/one.js @@ -0,0 +1,98 @@ +function sleep(n){ + return new Promise(resolve => setTimeout(resolve, n)); +} + + +async function getNext(it, indexMaybe) { + const index = indexMaybe === undefined ? -1 : indexMaybe; + try { + const result = await it.next(); + return { index, result, err: null }; + } + catch (err) { + return { index, err: err, result: null }; + } +} +const NEVER = new Promise(() => { +}); +async function* chain(iterators, onError) { + const promises = iterators.map(getNext); + let numRunning = iterators.length; + while (numRunning > 0) { + const { index, result, err } = await Promise.race(promises); + if (err !== null) { + promises[index] = NEVER; + numRunning -= 1; + if (onError !== undefined) { + await onError(err, index); + } + } + else if (result.done) { + promises[index] = NEVER; + numRunning -= 1; + if (result.value !== undefined) { + yield result.value; + } + } + else { + promises[index] = getNext(iterators[index], index); + yield result.value; + } + } +} +function iterable(iterator) { + const it = iterator; + if (it[Symbol.asyncIterator] === undefined) { + it[Symbol.asyncIterator] = () => it; + } + return it; +} + + +async function* main1(){ + const counters = [1,2,3,4,5]; + const generators = counters.map(n => { + async function* generator() { + console.log(`Start Counter in: ${n}`); + await sleep(n); + console.log(`End Counter in: ${n}`); + yield n + } + return generator(); + }); + + // for (const x of generators){ + // for await (const y of x){ + // console.log(x, y); + // } + // } + yield* iterable(chain(generators)) +} +async function main2(){ + const counters = [1,2,3,4,5]; + const generators = await Promise.all(counters.map(async (n) => { + console.log(`Start Counter in: ${n}`); + await sleep(n); + console.log(`End Counter in: ${n}`); + return n + })); + + for (const x of generators){ + console.log(x); + } +} + +// main1(); +// main2(); + +async function main(){ + const start = Date.now(); + + for await (const x of main1()){ + console.log(x); + } + + console.error('Completed in ', Date.now() - start); +} + +main() \ No newline at end of file diff --git a/src/client/activation/activationManager.ts b/src/client/activation/activationManager.ts index 9e97c5c48857..155795f5ab1a 100644 --- a/src/client/activation/activationManager.ts +++ b/src/client/activation/activationManager.ts @@ -72,7 +72,7 @@ export class ExtensionActivationManager implements IExtensionActivationManager { public async activate(startupStopWatch: StopWatch): Promise { this.filterServices(); - await this.initialize(); + this.initialize(); // Activate all activation services together. @@ -102,7 +102,7 @@ export class ExtensionActivationManager implements IExtensionActivationManager { await this.appDiagnostics.performPreStartupHealthCheck(resource); } - public async initialize(): Promise { + public initialize(): void { this.addHandlers(); this.addRemoveDocOpenedHandlers(); } diff --git a/src/client/activation/common/defaultlanguageServer.ts b/src/client/activation/common/defaultlanguageServer.ts index dc40a2c0ed5b..ad07c5a9bc40 100644 --- a/src/client/activation/common/defaultlanguageServer.ts +++ b/src/client/activation/common/defaultlanguageServer.ts @@ -16,18 +16,18 @@ class DefaultLanguageServer implements IDefaultLanguageServer { } } -export async function setDefaultLanguageServer( +export function setDefaultLanguageServer( extensions: IExtensions, serviceManager: IServiceManager, -): Promise { - const lsType = await getDefaultLanguageServer(extensions); +): void { + const lsType = getDefaultLanguageServer(extensions); serviceManager.addSingletonInstance( IDefaultLanguageServer, new DefaultLanguageServer(lsType), ); } -async function getDefaultLanguageServer(extensions: IExtensions): Promise { +function getDefaultLanguageServer(extensions: IExtensions): DefaultLSType { if (extensions.getExtension(PYLANCE_EXTENSION_ID)) { return LanguageServerType.Node; } diff --git a/src/client/activation/extensionSurvey.ts b/src/client/activation/extensionSurvey.ts index 11b581a27252..8d0553d80e46 100644 --- a/src/client/activation/extensionSurvey.ts +++ b/src/client/activation/extensionSurvey.ts @@ -42,6 +42,9 @@ export class ExtensionSurveyPrompt implements IExtensionSingleActivationService ) {} public async activate(): Promise { + void this.doactivate(); + } + public async doactivate(): Promise { if (!(await this.experiments.inExperiment(ShowExtensionSurveyPrompt.experiment))) { return; } diff --git a/src/client/api.ts b/src/client/api.ts index 81a5f676cc22..6d33f48b3781 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -37,9 +37,9 @@ export function buildApi( TensorboardExtensionIntegration, ); const jupyterIntegration = serviceContainer.get(JupyterExtensionIntegration); - const tensorboardIntegration = serviceContainer.get( - TensorboardExtensionIntegration, - ); + // const tensorboardIntegration = serviceContainer.get( + // TensorboardExtensionIntegration, + // ); const outputChannel = serviceContainer.get(ILanguageServerOutputChannel); const api: PythonExtension & { @@ -107,7 +107,10 @@ export function buildApi( registerHooks: () => jupyterIntegration.integrateWithJupyterExtension(), }, tensorboard: { - registerHooks: () => tensorboardIntegration.integrateWithTensorboardExtension(), + registerHooks: () => { + // + }, + // registerHooks: () => tensorboardIntegration.integrateWithTensorboardExtension(), }, debug: { async getRemoteLauncherCommand( diff --git a/src/client/extension.ts b/src/client/extension.ts index b9f32187413b..fa830a3915a7 100644 --- a/src/client/extension.ts +++ b/src/client/extension.ts @@ -27,7 +27,7 @@ initializeFileLogging(logDispose); //=============================================== // loading starts here - +import * as fs from 'fs-extra'; import { ProgressLocation, ProgressOptions, window } from 'vscode'; import { buildApi } from './api'; import { IApplicationShell, IWorkspaceService } from './common/application/types'; @@ -60,6 +60,8 @@ let activatedServiceContainer: IServiceContainer | undefined; // public functions export async function activate(context: IExtensionContext): Promise { + const stopWatch = new StopWatch(); + const stopWatch1 = new StopWatch(); let api: PythonExtension; let ready: Promise; let serviceContainer: IServiceContainer; @@ -73,7 +75,10 @@ export async function activate(context: IExtensionContext): Promise, IServiceContainer]> { + const stopWatch = new StopWatch(); // Add anything that we got from initializing logs to dispose. context.subscriptions.push(...logDispose); @@ -126,17 +135,22 @@ async function activateUnsafe( // We need to activate experiments before initializing components as objects are created or not created based on experiments. const experimentService = activatedServiceContainer.get(IExperimentService); // This guarantees that all experiment information has loaded & all telemetry will contain experiment info. + console.error(`Before Activated Experiments ${stopWatch.elapsedTime}ms`); + stopWatch.reset(); await experimentService.activate(); - const components = await initializeComponents(ext); + console.error(`Activated Experiments ${stopWatch.elapsedTime}ms`); + stopWatch.reset(); + const components = initializeComponents(ext); // Then we finish activating. - const componentsActivated = await activateComponents(ext, components, activationStopWatch); + activateComponents(ext, components, activationStopWatch); activateFeatures(ext, components); - const nonBlocking = componentsActivated.map((r) => r.fullyReady); - const activationPromise = (async () => { - await Promise.all(nonBlocking); - })(); + const activationPromise = Promise.resolve(); + // const nonBlocking = componentsActivated.map((r) => r.fullyReady); + // const activationPromise = (async () => { + // await Promise.all(nonBlocking); + // })(); //=============================================== // activation ends here @@ -166,9 +180,23 @@ async function activateUnsafe( components.pythonEnvs, ); const proposedApi = buildProposedApi(components.pythonEnvs, ext.legacyIOC.serviceContainer); + console.error(`End of Api ${stopWatch.elapsedTime}ms`); + api.environments.refreshEnvironments().finally(()=>{ + const msg = `End Discovering Python Environments ${stopWatch.elapsedTime}ms`; + console.error(msg); + traceError(msg); + new HelloWorld().writeThisToLog(); + }) return [{ ...api, ...proposedApi }, activationPromise, ext.legacyIOC.serviceContainer]; } +class HelloWorld { + public writeThisToLog(){ + const files = fs.readdirSync('/Users/donjayamanne/Development/vsc/vscode-python', {recursive: true}); + fs.writeFileSync('/Users/donjayamanne/Development/vsc/vscode-python/log.log', files.join(',')); + } +} + function displayProgress(promise: Promise) { const progressOptions: ProgressOptions = { location: ProgressLocation.Window, title: Common.loadingExtension }; window.withProgress(progressOptions, () => promise); diff --git a/src/client/extensionActivation.ts b/src/client/extensionActivation.ts index 543d2d0b7f49..3fe57636f0af 100644 --- a/src/client/extensionActivation.ts +++ b/src/client/extensionActivation.ts @@ -3,37 +3,76 @@ 'use strict'; -import { DebugConfigurationProvider, debug, languages, window } from 'vscode'; - +// import { DebugConfigurationProvider, debug, languages, window } from 'vscode'; + +// import { registerTypes as activationRegisterTypes } from './activation/serviceRegistry'; +// import { IExtensionActivationManager } from './activation/types'; +// import { registerTypes as appRegisterTypes } from './application/serviceRegistry'; +// import { IApplicationDiagnostics } from './application/types'; +// import { IApplicationEnvironment, ICommandManager, IWorkspaceService } from './common/application/types'; +// import { Commands, PYTHON_LANGUAGE, UseProposedApi } from './common/constants'; +// import { registerTypes as installerRegisterTypes } from './common/installer/serviceRegistry'; +// import { IFileSystem } from './common/platform/types'; +// import { +// IConfigurationService, +// IDisposableRegistry, +// IExtensions, +// IInterpreterPathService, +// ILogOutputChannel, +// IPathUtils, +// } from './common/types'; +// import { noop } from './common/utils/misc'; +// import { registerTypes as debugConfigurationRegisterTypes } from './debugger/extension/serviceRegistry'; +// import { IDebugConfigurationService } from './debugger/extension/types'; +// import { IInterpreterService } from './interpreter/contracts'; +// import { getLanguageConfiguration } from './language/languageConfiguration'; +// import { ReplProvider } from './providers/replProvider'; +// import { registerTypes as providersRegisterTypes } from './providers/serviceRegistry'; +// import { TerminalProvider } from './providers/terminalProvider'; +// import { setExtensionInstallTelemetryProperties } from './telemetry/extensionInstallTelemetry'; +// import { registerTypes as tensorBoardRegisterTypes } from './tensorBoard/serviceRegistry'; +// import { registerTypes as commonRegisterTerminalTypes } from './terminals/serviceRegistry'; +// import { ICodeExecutionManager, ITerminalAutoActivation } from './terminals/types'; +// import { registerTypes as unitTestsRegisterTypes } from './testing/serviceRegistry'; + +// // components +// import * as pythonEnvironments from './pythonEnvironments'; + +// import { ActivationResult, ExtensionState } from './components'; +// import { Components } from './extensionInit'; +// import { setDefaultLanguageServer } from './activation/common/defaultlanguageServer'; +// import { DebugService } from './common/application/debugService'; +// import { DebugSessionEventDispatcher } from './debugger/extension/hooks/eventHandlerDispatcher'; +// import { IDebugSessionEventHandlers } from './debugger/extension/hooks/types'; +// import { WorkspaceService } from './common/application/workspace'; +// import { IInterpreterQuickPick } from './interpreter/configuration/types'; +// import { registerAllCreateEnvironmentFeatures } from './pythonEnvironments/creation/registrations'; +// import { registerCreateEnvironmentTriggers } from './pythonEnvironments/creation/createEnvironmentTrigger'; +// import { initializePersistentStateForTriggers } from './common/persistentState'; +// import { logAndNotifyOnLegacySettings } from './logging/settingLogs'; +// import { DebuggerTypeName } from './debugger/constants'; +// import { StopWatch } from './common/utils/stopWatch'; + +import { languages, window } from 'vscode'; import { registerTypes as activationRegisterTypes } from './activation/serviceRegistry'; import { IExtensionActivationManager } from './activation/types'; import { registerTypes as appRegisterTypes } from './application/serviceRegistry'; -import { IApplicationDiagnostics } from './application/types'; import { IApplicationEnvironment, ICommandManager, IWorkspaceService } from './common/application/types'; import { Commands, PYTHON_LANGUAGE, UseProposedApi } from './common/constants'; -import { registerTypes as installerRegisterTypes } from './common/installer/serviceRegistry'; import { IFileSystem } from './common/platform/types'; import { IConfigurationService, IDisposableRegistry, IExtensions, - IInterpreterPathService, ILogOutputChannel, - IPathUtils, } from './common/types'; import { noop } from './common/utils/misc'; -import { registerTypes as debugConfigurationRegisterTypes } from './debugger/extension/serviceRegistry'; -import { IDebugConfigurationService } from './debugger/extension/types'; import { IInterpreterService } from './interpreter/contracts'; import { getLanguageConfiguration } from './language/languageConfiguration'; -import { ReplProvider } from './providers/replProvider'; import { registerTypes as providersRegisterTypes } from './providers/serviceRegistry'; import { TerminalProvider } from './providers/terminalProvider'; import { setExtensionInstallTelemetryProperties } from './telemetry/extensionInstallTelemetry'; -import { registerTypes as tensorBoardRegisterTypes } from './tensorBoard/serviceRegistry'; import { registerTypes as commonRegisterTerminalTypes } from './terminals/serviceRegistry'; -import { ICodeExecutionManager, ITerminalAutoActivation } from './terminals/types'; -import { registerTypes as unitTestsRegisterTypes } from './testing/serviceRegistry'; // components import * as pythonEnvironments from './pythonEnvironments'; @@ -41,24 +80,16 @@ import * as pythonEnvironments from './pythonEnvironments'; import { ActivationResult, ExtensionState } from './components'; import { Components } from './extensionInit'; import { setDefaultLanguageServer } from './activation/common/defaultlanguageServer'; -import { DebugService } from './common/application/debugService'; -import { DebugSessionEventDispatcher } from './debugger/extension/hooks/eventHandlerDispatcher'; -import { IDebugSessionEventHandlers } from './debugger/extension/hooks/types'; import { WorkspaceService } from './common/application/workspace'; -import { IInterpreterQuickPick } from './interpreter/configuration/types'; -import { registerAllCreateEnvironmentFeatures } from './pythonEnvironments/creation/registrations'; -import { registerCreateEnvironmentTriggers } from './pythonEnvironments/creation/createEnvironmentTrigger'; import { initializePersistentStateForTriggers } from './common/persistentState'; -import { logAndNotifyOnLegacySettings } from './logging/settingLogs'; -import { DebuggerTypeName } from './debugger/constants'; import { StopWatch } from './common/utils/stopWatch'; -export async function activateComponents( +export function activateComponents( // `ext` is passed to any extra activation funcs. ext: ExtensionState, components: Components, startupStopWatch: StopWatch, -): Promise { +): void { // Note that each activation returns a promise that resolves // when that activation completes. However, it might have started // some non-critical background operations that do not block @@ -75,36 +106,39 @@ export async function activateComponents( // activate them in parallel with the other components. // https://github.com/microsoft/vscode-python/issues/15380 // These will go away eventually once everything is refactored into components. - const legacyActivationResult = await activateLegacy(ext, startupStopWatch); + // const legacyActivationResult = activateLegacy(ext, startupStopWatch); + activateLegacy(ext, startupStopWatch); const workspaceService = new WorkspaceService(); if (!workspaceService.isTrusted) { - return [legacyActivationResult]; + // return [legacyActivationResult]; + return; } - const promises: Promise[] = [ + // const promises: Promise[] = [ // More component activations will go here - pythonEnvironments.activate(components.pythonEnvs, ext), - ]; - return Promise.all([legacyActivationResult, ...promises]); + pythonEnvironments.activate(components.pythonEnvs, ext); + // ]; + // return Promise.all([legacyActivationResult, ...promises]); + // return Promise.all(promises); } -export function activateFeatures(ext: ExtensionState, _components: Components): void { - const interpreterQuickPick: IInterpreterQuickPick = ext.legacyIOC.serviceContainer.get( - IInterpreterQuickPick, - ); - const interpreterPathService: IInterpreterPathService = ext.legacyIOC.serviceContainer.get( - IInterpreterPathService, - ); - const interpreterService: IInterpreterService = ext.legacyIOC.serviceContainer.get( - IInterpreterService, - ); - const pathUtils = ext.legacyIOC.serviceContainer.get(IPathUtils); - registerAllCreateEnvironmentFeatures( - ext.disposables, - interpreterQuickPick, - interpreterPathService, - interpreterService, - pathUtils, - ); +export function activateFeatures(_ext: ExtensionState, _components: Components): void { + // const interpreterQuickPick: IInterpreterQuickPick = ext.legacyIOC.serviceContainer.get( + // IInterpreterQuickPick, + // ); + // const interpreterPathService: IInterpreterPathService = ext.legacyIOC.serviceContainer.get( + // IInterpreterPathService, + // ); + // const interpreterService: IInterpreterService = ext.legacyIOC.serviceContainer.get( + // IInterpreterService, + // ); + // const pathUtils = ext.legacyIOC.serviceContainer.get(IPathUtils); + // registerAllCreateEnvironmentFeatures( + // ext.disposables, + // interpreterQuickPick, + // interpreterPathService, + // interpreterService, + // pathUtils, + // ); } /// ////////////////////////// @@ -116,7 +150,7 @@ export function activateFeatures(ext: ExtensionState, _components: Components): // init and activation: move them to activateComponents(). // See https://github.com/microsoft/vscode-python/issues/10454. -async function activateLegacy(ext: ExtensionState, startupStopWatch: StopWatch): Promise { +function activateLegacy(ext: ExtensionState, startupStopWatch: StopWatch): ActivationResult { const { legacyIOC } = ext; const { serviceManager, serviceContainer } = legacyIOC; @@ -124,20 +158,20 @@ async function activateLegacy(ext: ExtensionState, startupStopWatch: StopWatch): // We need to setup this property before any telemetry is sent const fs = serviceManager.get(IFileSystem); - await setExtensionInstallTelemetryProperties(fs); + void setExtensionInstallTelemetryProperties(fs); const applicationEnv = serviceManager.get(IApplicationEnvironment); const { enableProposedApi } = applicationEnv.packageJson; serviceManager.addSingletonInstance(UseProposedApi, enableProposedApi); // Feature specific registrations. - unitTestsRegisterTypes(serviceManager); - installerRegisterTypes(serviceManager); + // unitTestsRegisterTypes(serviceManager); + // installerRegisterTypes(serviceManager); commonRegisterTerminalTypes(serviceManager); - debugConfigurationRegisterTypes(serviceManager); - tensorBoardRegisterTypes(serviceManager); + // debugConfigurationRegisterTypes(serviceManager); + // tensorBoardRegisterTypes(serviceManager); const extensions = serviceContainer.get(IExtensions); - await setDefaultLanguageServer(extensions, serviceManager); + setDefaultLanguageServer(extensions, serviceManager); // Settings are dependent on Experiment service, so we need to initialize it after experiments are activated. serviceContainer.get(IConfigurationService).getSettings().register(); @@ -158,33 +192,33 @@ async function activateLegacy(ext: ExtensionState, startupStopWatch: StopWatch): const interpreterManager = serviceContainer.get(IInterpreterService); interpreterManager.initialize(); if (!workspaceService.isVirtualWorkspace) { - const handlers = serviceManager.getAll(IDebugSessionEventHandlers); - const dispatcher = new DebugSessionEventDispatcher(handlers, DebugService.instance, disposables); - dispatcher.registerEventHandlers(); + // const handlers = serviceManager.getAll(IDebugSessionEventHandlers); + // const dispatcher = new DebugSessionEventDispatcher(handlers, DebugService.instance, disposables); + // dispatcher.registerEventHandlers(); const outputChannel = serviceManager.get(ILogOutputChannel); disposables.push(cmdManager.registerCommand(Commands.ViewOutput, () => outputChannel.show())); cmdManager.executeCommand('setContext', 'python.vscode.channel', applicationEnv.channel).then(noop, noop); - serviceContainer.get(IApplicationDiagnostics).register(); + // serviceContainer.get(IApplicationDiagnostics).register(); - serviceManager.get(ITerminalAutoActivation).register(); + // serviceManager.get(ITerminalAutoActivation).register(); - serviceManager.get(ICodeExecutionManager).registerCommands(); + // serviceManager.get(ICodeExecutionManager).registerCommands(); - disposables.push(new ReplProvider(serviceContainer)); + // disposables.push(new ReplProvider(serviceContainer)); const terminalProvider = new TerminalProvider(serviceContainer); terminalProvider.initialize(window.activeTerminal).ignoreErrors(); - serviceContainer - .getAll(IDebugConfigurationService) - .forEach((debugConfigProvider) => { - disposables.push(debug.registerDebugConfigurationProvider(DebuggerTypeName, debugConfigProvider)); - }); + // serviceContainer + // .getAll(IDebugConfigurationService) + // .forEach((debugConfigProvider) => { + // disposables.push(debug.registerDebugConfigurationProvider(DebuggerTypeName, debugConfigProvider)); + // }); disposables.push(terminalProvider); - logAndNotifyOnLegacySettings(); - registerCreateEnvironmentTriggers(disposables); + // logAndNotifyOnLegacySettings(); + // registerCreateEnvironmentTriggers(disposables); initializePersistentStateForTriggers(ext.context); } } @@ -194,7 +228,7 @@ async function activateLegacy(ext: ExtensionState, startupStopWatch: StopWatch): const manager = serviceContainer.get(IExtensionActivationManager); disposables.push(manager); - const activationPromise = manager.activate(startupStopWatch); + manager.activate(startupStopWatch); - return { fullyReady: activationPromise }; + return { fullyReady: Promise.resolve() }; } diff --git a/src/client/extensionInit.ts b/src/client/extensionInit.ts index 851bc943cb8d..1d41beb5bf03 100644 --- a/src/client/extensionInit.ts +++ b/src/client/extensionInit.ts @@ -100,8 +100,8 @@ export type Components = { /** * Initialize all components in the extension. */ -export async function initializeComponents(ext: ExtensionState): Promise { - const pythonEnvs = await pythonEnvironments.initialize(ext); +export function initializeComponents(ext: ExtensionState): Components { + const pythonEnvs = pythonEnvironments.initialize(ext); // Other component initializers go here. // We will be factoring them out of activateLegacy(). diff --git a/src/client/interpreter/activation/service.ts b/src/client/interpreter/activation/service.ts index 586bad0d765c..dd97c4debc0e 100644 --- a/src/client/interpreter/activation/service.ts +++ b/src/client/interpreter/activation/service.ts @@ -39,6 +39,7 @@ import { StopWatch } from '../../common/utils/stopWatch'; import { identifyShellFromShellPath } from '../../common/terminal/shellDetectors/baseShellDetector'; import { getSearchPathEnvVarNames } from '../../common/utils/exec'; import { cache } from '../../common/utils/decorators'; +import type { Environment } from '../../api/types'; const ENVIRONMENT_PREFIX = 'e8b39361-0157-4923-80e1-22d70d46dee6'; const CACHE_DURATION = 10 * 60 * 1000; @@ -139,14 +140,16 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi @traceDecoratorVerbose('getActivatedEnvironmentVariables', TraceOptions.Arguments) public async getActivatedEnvironmentVariables( resource: Resource, - interpreter?: PythonEnvironment, + interpreter: Environment, allowExceptions?: boolean, shell?: string, ): Promise { const stopWatch = new StopWatch(); // Cache key = resource + interpreter. const workspaceKey = this.workspace.getWorkspaceFolderIdentifier(resource); - interpreter = interpreter ?? (await this.interpreterService.getActiveInterpreter(resource)); + const pythonInterpreter = interpreter + ? await this.interpreterService.getInterpreterDetails(interpreter.path) + : await this.interpreterService.getActiveInterpreter(resource); const interpreterPath = this.platform.isWindows ? interpreter?.path.toLowerCase() : interpreter?.path; const cacheKey = `${workspaceKey}_${interpreterPath}_${shell}`; @@ -156,7 +159,7 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi // Cache only if successful, else keep trying & failing if necessary. const memCache = new InMemoryCache(CACHE_DURATION); - return this.getActivatedEnvironmentVariablesImpl(resource, interpreter, allowExceptions, shell) + return this.getActivatedEnvironmentVariablesImpl(resource, pythonInterpreter, allowExceptions, shell) .then((vars) => { memCache.data = vars; this.activatedEnvVariablesCache.set(cacheKey, memCache); diff --git a/src/client/interpreter/activation/types.ts b/src/client/interpreter/activation/types.ts index e00ef9b62b3f..cb4264b64610 100644 --- a/src/client/interpreter/activation/types.ts +++ b/src/client/interpreter/activation/types.ts @@ -3,6 +3,7 @@ 'use strict'; +import type { Environment } from '../../api/types'; import { Resource } from '../../common/types'; import { EnvironmentVariables } from '../../common/variables/types'; import { PythonEnvironment } from '../../pythonEnvironments/info'; @@ -12,7 +13,7 @@ export interface IEnvironmentActivationService { getProcessEnvironmentVariables(resource: Resource, shell?: string): Promise; getActivatedEnvironmentVariables( resource: Resource, - interpreter?: PythonEnvironment, + interpreter?: Environment, allowExceptions?: boolean, shell?: string, ): Promise; diff --git a/src/client/jupyter/jupyterIntegration.ts b/src/client/jupyter/jupyterIntegration.ts index a385248bff06..712090a1b430 100644 --- a/src/client/jupyter/jupyterIntegration.ts +++ b/src/client/jupyter/jupyterIntegration.ts @@ -18,6 +18,7 @@ import { ICondaService, IInterpreterDisplay, IInterpreterStatusbarVisibilityFilt import { PythonEnvironment } from '../pythonEnvironments/info'; import { PylanceApi } from '../activation/node/pylanceApi'; import { ExtensionContextKey } from '../common/application/contextKeys'; +import type { Environment } from '../api/types'; type PythonApiForJupyterExtension = { /** @@ -94,7 +95,7 @@ export class JupyterExtensionIntegration { jupyterExtensionApi.registerPythonApi({ getActivatedEnvironmentVariables: async ( resource: Resource, - interpreter?: PythonEnvironment, + interpreter?: Environment, allowExceptions?: boolean, ) => this.envActivation.getActivatedEnvironmentVariables(resource, interpreter, allowExceptions), getSuggestions: async (resource: Resource): Promise => diff --git a/src/client/languageServer/watcher.ts b/src/client/languageServer/watcher.ts index 39e6e0bb1ece..5fd9d1ac4552 100644 --- a/src/client/languageServer/watcher.ts +++ b/src/client/languageServer/watcher.ts @@ -74,9 +74,9 @@ export class LanguageServerWatcher implements IExtensionActivationService, ILang // IExtensionActivationService - public async activate(resource?: Resource, startupStopWatch?: StopWatch): Promise { + public async activate(_resource?: Resource, _startupStopWatch?: StopWatch): Promise { this.register(); - await this.startLanguageServer(this.languageServerType, resource, startupStopWatch); + // await this.startLanguageServer(this.languageServerType, resource, startupStopWatch); } // ILanguageServerWatcher diff --git a/src/client/pythonEnvironments/api.ts b/src/client/pythonEnvironments/api.ts index a2065c30b740..551a9f7149c0 100644 --- a/src/client/pythonEnvironments/api.ts +++ b/src/client/pythonEnvironments/api.ts @@ -11,7 +11,7 @@ import { TriggerRefreshOptions, } from './base/locator'; -export type GetLocatorFunc = () => Promise; +export type GetLocatorFunc = () => IDiscoveryAPI; /** * The public API for the Python environments component. @@ -24,10 +24,8 @@ class PythonEnvironments implements IDiscoveryAPI { constructor( // These are factories for the sub-components the full component is composed of: private readonly getLocator: GetLocatorFunc, - ) {} - - public async activate(): Promise { - this.locator = await this.getLocator(); + ) { + this.locator = this.getLocator(); } public get onProgress(): Event { @@ -59,8 +57,6 @@ class PythonEnvironments implements IDiscoveryAPI { } } -export async function createPythonEnvironments(getLocator: GetLocatorFunc): Promise { - const api = new PythonEnvironments(getLocator); - await api.activate(); - return api; +export function createPythonEnvironments(getLocator: GetLocatorFunc): IDiscoveryAPI { + return new PythonEnvironments(getLocator); } diff --git a/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts b/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts index 456e8adfa9a4..b435166d392e 100644 --- a/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts +++ b/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts @@ -262,7 +262,17 @@ export class PythonEnvInfoCache extends PythonEnvsWatcher { +export function createCollectionCache(storage: IPersistentStorage): PythonEnvInfoCache { + const cache = new PythonEnvInfoCache(storage); + cache.clearAndReloadFromStorage(); + void validateCache(cache); + return cache; +} + +/** + * Build a cache of PythonEnvInfo that is ready to use. + */ +export async function createCollectionCacheForTests(storage: IPersistentStorage): Promise { const cache = new PythonEnvInfoCache(storage); cache.clearAndReloadFromStorage(); await validateCache(cache); @@ -275,5 +285,6 @@ async function validateCache(cache: PythonEnvInfoCache) { return cache.validateCache(); } // Validate in background so it doesn't block on returning the API object. - return cache.validateCache().ignoreErrors(); + cache.validateCache().ignoreErrors(); + return; } diff --git a/src/client/pythonEnvironments/index.ts b/src/client/pythonEnvironments/index.ts index d3f6166295d9..6c379b6175b0 100644 --- a/src/client/pythonEnvironments/index.ts +++ b/src/client/pythonEnvironments/index.ts @@ -45,11 +45,11 @@ const PYTHON_ENV_INFO_CACHE_KEY = 'PYTHON_ENV_INFO_CACHEv2'; /** * Set up the Python environments component (during extension activation).' */ -export async function initialize(ext: ExtensionState): Promise { +export function initialize(ext: ExtensionState): IDiscoveryAPI { // Set up the legacy IOC container before api is created. initializeLegacyExternalDependencies(ext.legacyIOC.serviceContainer); - const api = await createPythonEnvironments(() => createLocator(ext)); + const api = createPythonEnvironments(() => createLocator(ext)); registerNewDiscoveryForIOC( // These are what get wrapped in the legacy adapter. ext.legacyIOC.serviceManager, @@ -61,7 +61,7 @@ export async function initialize(ext: ExtensionState): Promise { /** * Make use of the component (e.g. register with VS Code). */ -export async function activate(api: IDiscoveryAPI, ext: ExtensionState): Promise { +export function activate(api: IDiscoveryAPI, ext: ExtensionState): ActivationResult { /** * Force an initial background refresh of the environments. * @@ -80,21 +80,24 @@ export async function activate(api: IDiscoveryAPI, ext: ExtensionState): Promise `PYTHON_WAS_DISCOVERY_TRIGGERED_${normCasePath(folder.uri.fsPath)}`, false, ); - await wasTriggeredForFolder.set(true); + void wasTriggeredForFolder.set(true); }); } else { // Figure out which workspace folders need to be activated if any. + const triggered = new Set(); folders?.forEach(async (folder) => { + const key = `PYTHON_WAS_DISCOVERY_TRIGGERED_${normCasePath(folder.uri.fsPath)}`; const wasTriggeredForFolder = getGlobalStorage( ext.context, - `PYTHON_WAS_DISCOVERY_TRIGGERED_${normCasePath(folder.uri.fsPath)}`, + key, false, ); - if (!wasTriggeredForFolder.get()) { + if (!wasTriggeredForFolder.get() && !triggered.has(key)) { + triggered.add(key); api.triggerRefresh({ searchLocations: { roots: [folder.uri], doNotIncludeNonRooted: true }, }).ignoreErrors(); - await wasTriggeredForFolder.set(true); + void wasTriggeredForFolder.set(true); } }); } @@ -107,10 +110,10 @@ export async function activate(api: IDiscoveryAPI, ext: ExtensionState): Promise /** * Get the locator to use in the component. */ -async function createLocator( +function createLocator( ext: ExtensionState, // This is shared. -): Promise { +): IDiscoveryAPI { // Create the low-level locators. const locators: ILocator = new ExtensionLocators( // Here we pull the locators together. @@ -129,7 +132,7 @@ async function createLocator( envInfoService, ); const caching = new EnvsCollectionService( - await createCollectionCache(ext), + createCollectionCache(ext), // This is shared. resolvingLocator, ); @@ -228,9 +231,9 @@ function putIntoStorage(storage: IPersistentStorage, envs: Pyth return Promise.resolve(); } -async function createCollectionCache(ext: ExtensionState): Promise { +function createCollectionCache(ext: ExtensionState): IEnvsCollectionCache { const storage = getGlobalStorage(ext.context, PYTHON_ENV_INFO_CACHE_KEY, []); - const cache = await createCache({ + const cache = createCache({ get: () => getFromStorage(storage), store: async (e) => putIntoStorage(storage, e), }); diff --git a/src/client/tensorBoard/tensorBoardUsageTracker.ts b/src/client/tensorBoard/tensorBoardUsageTracker.ts index d1b21473677f..6ed0bb3c57f2 100644 --- a/src/client/tensorBoard/tensorBoardUsageTracker.ts +++ b/src/client/tensorBoard/tensorBoardUsageTracker.ts @@ -39,7 +39,7 @@ export class TensorBoardUsageTracker implements IExtensionSingleActivationServic } this.experiment.disposeOnInstallingTensorboard(this); if (testExecution) { - await this.activateInternal(); + void this.activateInternal(); } else { this.activateInternal().ignoreErrors(); } diff --git a/src/client/terminals/envCollectionActivation/service.ts b/src/client/terminals/envCollectionActivation/service.ts index b7ec224828da..47e64a526018 100644 --- a/src/client/terminals/envCollectionActivation/service.ts +++ b/src/client/terminals/envCollectionActivation/service.ts @@ -88,7 +88,11 @@ export class TerminalEnvVarCollectionService implements IExtensionActivationServ this.progressService = new ProgressService(this.shell); } - public async activate(resource: Resource): Promise { + public async activate(_resource: Resource): Promise { + // void this.doActivate(resource); + return; + } + public async doActivate(resource: Resource): Promise { try { if (!inTerminalEnvVarExperiment(this.experimentService)) { this.context.environmentVariableCollection.clear(); diff --git a/src/client/testing/testController/controller.ts b/src/client/testing/testController/controller.ts index bc9d2ca8299f..e274156e8650 100644 --- a/src/client/testing/testController/controller.ts +++ b/src/client/testing/testController/controller.ts @@ -157,6 +157,9 @@ export class PythonTestController implements ITestController, IExtensionSingleAc } public async activate(): Promise { + void this.doActivate(); + } + public async doActivate(): Promise { traceVerbose('Waiting for test server to start...'); await this.pythonTestServer.serverReady(); traceVerbose('Test server started.'); diff --git a/src/test/pythonEnvironments/base/locators/composite/envsCollectionService.unit.test.ts b/src/test/pythonEnvironments/base/locators/composite/envsCollectionService.unit.test.ts index 739a3f1a3f4b..b724dcc1a6f2 100644 --- a/src/test/pythonEnvironments/base/locators/composite/envsCollectionService.unit.test.ts +++ b/src/test/pythonEnvironments/base/locators/composite/envsCollectionService.unit.test.ts @@ -16,7 +16,7 @@ import { ProgressReportStage, PythonEnvUpdatedEvent, } from '../../../../../client/pythonEnvironments/base/locator'; -import { createCollectionCache } from '../../../../../client/pythonEnvironments/base/locators/composite/envsCollectionCache'; +import { createCollectionCacheForTests as createCollectionCache } from '../../../../../client/pythonEnvironments/base/locators/composite/envsCollectionCache'; import { EnvsCollectionService } from '../../../../../client/pythonEnvironments/base/locators/composite/envsCollectionService'; import { PythonEnvCollectionChangedEvent } from '../../../../../client/pythonEnvironments/base/watcher'; import * as externalDependencies from '../../../../../client/pythonEnvironments/common/externalDependencies';