Skip to content

Commit 637f1c5

Browse files
authored
debt: refactor environment info collection and add helper file (#815)
should help with diagnosing bugs to have the following information in logging
1 parent 1917aaa commit 637f1c5

File tree

2 files changed

+204
-160
lines changed

2 files changed

+204
-160
lines changed

src/extension.ts

Lines changed: 16 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { commands, ExtensionContext, extensions, LogOutputChannel, Terminal, Uri, window, workspace } from 'vscode';
1+
import { commands, ExtensionContext, LogOutputChannel, Terminal, Uri, window } from 'vscode';
2+
import { version as extensionVersion } from '../package.json';
23
import { PythonEnvironment, PythonEnvironmentApi, PythonProjectCreator } from './api';
34
import { ensureCorrectVersion } from './common/extVersion';
4-
import { registerLogger, traceError, traceInfo, traceWarn } from './common/logging';
5+
import { registerLogger, traceError, traceInfo, traceVerbose, traceWarn } from './common/logging';
56
import { clearPersistentState, setPersistentState } from './common/persistentState';
67
import { newProjectSelection } from './common/pickers/managers';
78
import { StopWatch } from './common/stopWatch';
89
import { EventNames } from './common/telemetry/constants';
910
import { sendManagerSelectionTelemetry } from './common/telemetry/helpers';
1011
import { sendTelemetryEvent } from './common/telemetry/sender';
1112
import { createDeferred } from './common/utils/deferred';
12-
import { normalizePath } from './common/utils/pathUtils';
1313
import { isWindows } from './common/utils/platformUtils';
1414
import {
1515
activeTerminal,
@@ -61,19 +61,23 @@ import { cleanupStartupScripts } from './features/terminal/shellStartupSetupHand
6161
import { TerminalActivationImpl } from './features/terminal/terminalActivationState';
6262
import { TerminalEnvVarInjector } from './features/terminal/terminalEnvVarInjector';
6363
import { TerminalManager, TerminalManagerImpl } from './features/terminal/terminalManager';
64-
import { getAutoActivationType, getEnvironmentForTerminal } from './features/terminal/utils';
64+
import { getEnvironmentForTerminal } from './features/terminal/utils';
6565
import { EnvManagerView } from './features/views/envManagersView';
6666
import { ProjectView } from './features/views/projectView';
6767
import { PythonStatusBarImpl } from './features/views/pythonStatusBar';
6868
import { updateViewsAndStatus } from './features/views/revealHandler';
6969
import { ProjectItem } from './features/views/treeViewItems';
70+
import {
71+
collectEnvironmentInfo,
72+
getEnvManagerAndPackageManagerConfigLevels,
73+
resolveDefaultInterpreter,
74+
} from './helpers';
7075
import { EnvironmentManagers, ProjectCreators, PythonProjectManager } from './internal.api';
7176
import { registerSystemPythonFeatures } from './managers/builtin/main';
7277
import { SysPythonManager } from './managers/builtin/sysPythonManager';
7378
import {
7479
createNativePythonFinder,
7580
getNativePythonToolsPath,
76-
NativeEnvInfo,
7781
NativePythonFinder,
7882
} from './managers/common/nativePythonFinder';
7983
import { IDisposable } from './managers/common/types';
@@ -82,89 +86,6 @@ import { registerPipenvFeatures } from './managers/pipenv/main';
8286
import { registerPoetryFeatures } from './managers/poetry/main';
8387
import { registerPyenvFeatures } from './managers/pyenv/main';
8488

85-
/**
86-
* Collects relevant Python environment information for issue reporting
87-
*/
88-
async function collectEnvironmentInfo(
89-
context: ExtensionContext,
90-
envManagers: EnvironmentManagers,
91-
projectManager: PythonProjectManager,
92-
): Promise<string> {
93-
const info: string[] = [];
94-
95-
try {
96-
// Extension version
97-
const extensionVersion = context.extension?.packageJSON?.version || 'unknown';
98-
info.push(`Extension Version: ${extensionVersion}`);
99-
100-
// Python extension version
101-
const pythonExtension = extensions.getExtension('ms-python.python');
102-
const pythonVersion = pythonExtension?.packageJSON?.version || 'not installed';
103-
info.push(`Python Extension Version: ${pythonVersion}`);
104-
105-
// Environment managers
106-
const managers = envManagers.managers;
107-
info.push(`\nRegistered Environment Managers (${managers.length}):`);
108-
managers.forEach((manager) => {
109-
info.push(` - ${manager.id} (${manager.displayName})`);
110-
});
111-
112-
// Available environments
113-
const allEnvironments: PythonEnvironment[] = [];
114-
for (const manager of managers) {
115-
try {
116-
const envs = await manager.getEnvironments('all');
117-
allEnvironments.push(...envs);
118-
} catch (err) {
119-
info.push(` Error getting environments from ${manager.id}: ${err}`);
120-
}
121-
}
122-
123-
info.push(`\nTotal Available Environments: ${allEnvironments.length}`);
124-
if (allEnvironments.length > 0) {
125-
info.push('Environment Details:');
126-
allEnvironments.slice(0, 10).forEach((env, index) => {
127-
info.push(` ${index + 1}. ${env.displayName} (${env.version}) - ${env.displayPath}`);
128-
});
129-
if (allEnvironments.length > 10) {
130-
info.push(` ... and ${allEnvironments.length - 10} more environments`);
131-
}
132-
}
133-
134-
// Python projects
135-
const projects = projectManager.getProjects();
136-
info.push(`\nPython Projects (${projects.length}):`);
137-
for (let index = 0; index < projects.length; index++) {
138-
const project = projects[index];
139-
info.push(` ${index + 1}. ${project.uri.fsPath}`);
140-
try {
141-
const env = await envManagers.getEnvironment(project.uri);
142-
if (env) {
143-
info.push(` Environment: ${env.displayName}`);
144-
}
145-
} catch (err) {
146-
info.push(` Error getting environment: ${err}`);
147-
}
148-
}
149-
150-
// Current settings (non-sensitive)
151-
const config = workspace.getConfiguration('python-envs');
152-
const pyConfig = workspace.getConfiguration('python');
153-
info.push('\nExtension Settings:');
154-
info.push(` Default Environment Manager: ${config.get('defaultEnvManager')}`);
155-
info.push(` Default Package Manager: ${config.get('defaultPackageManager')}`);
156-
const pyenvAct = config.get('terminal.autoActivationType', undefined);
157-
const pythonAct = pyConfig.get('terminal.activateEnvironment', undefined);
158-
info.push(
159-
`Auto-activation is "${getAutoActivationType()}". Activation based on first 'py-env.terminal.autoActivationType' setting which is '${pyenvAct}' and 'python.terminal.activateEnvironment' if the first is undefined which is '${pythonAct}'.\n`,
160-
);
161-
} catch (err) {
162-
info.push(`\nError collecting environment information: ${err}`);
163-
}
164-
165-
return info.join('\n');
166-
}
167-
16889
export async function activate(context: ExtensionContext): Promise<PythonEnvironmentApi | undefined> {
16990
const useEnvironmentsExtension = getConfiguration('python').get<boolean>('useEnvironmentsExtension', true);
17091
traceInfo(`Experiment Status: useEnvironmentsExtension setting set to ${useEnvironmentsExtension}`);
@@ -183,6 +104,13 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
183104

184105
ensureCorrectVersion();
185106

107+
// log extension version
108+
traceVerbose(`Python-envs extension version: ${extensionVersion}`);
109+
// log settings
110+
const configLevels = getEnvManagerAndPackageManagerConfigLevels();
111+
traceInfo(`\n=== ${configLevels.section} ===`);
112+
traceInfo(JSON.stringify(configLevels, null, 2));
113+
186114
// Setup the persistent state for the extension.
187115
setPersistentState(context);
188116

@@ -595,78 +523,6 @@ export async function disposeAll(disposables: IDisposable[]): Promise<void> {
595523
);
596524
}
597525

598-
/**
599-
* Sets the default Python interpreter for the workspace if the user has not explicitly set 'defaultEnvManager' or it is set to venv.
600-
* @param nativeFinder - used to resolve interpreter paths.
601-
* @param envManagers - contains all registered managers.
602-
* @param api - The PythonEnvironmentApi for environment resolution and setting.
603-
*/
604-
async function resolveDefaultInterpreter(
605-
nativeFinder: NativePythonFinder,
606-
envManagers: EnvironmentManagers,
607-
api: PythonEnvironmentApi,
608-
) {
609-
const defaultInterpreterPath = getConfiguration('python').get<string>('defaultInterpreterPath');
610-
611-
if (defaultInterpreterPath) {
612-
const config = getConfiguration('python-envs');
613-
const inspect = config.inspect<string>('defaultEnvManager');
614-
const userDefinedDefaultManager =
615-
inspect?.workspaceFolderValue !== undefined ||
616-
inspect?.workspaceValue !== undefined ||
617-
inspect?.globalValue !== undefined;
618-
if (!userDefinedDefaultManager) {
619-
try {
620-
const resolved: NativeEnvInfo = await nativeFinder.resolve(defaultInterpreterPath);
621-
if (resolved && resolved.executable) {
622-
if (normalizePath(resolved.executable) === normalizePath(defaultInterpreterPath)) {
623-
// no action required, the path is already correct
624-
return;
625-
}
626-
const resolvedEnv = await api.resolveEnvironment(Uri.file(resolved.executable));
627-
traceInfo(`[resolveDefaultInterpreter] API resolved environment: ${JSON.stringify(resolvedEnv)}`);
628-
629-
let findEnvManager = envManagers.managers.find((m) => m.id === resolvedEnv?.envId.managerId);
630-
if (!findEnvManager) {
631-
findEnvManager = envManagers.managers.find((m) => m.id === 'ms-python.python:system');
632-
}
633-
if (resolvedEnv) {
634-
const newEnv: PythonEnvironment = {
635-
envId: {
636-
id: resolvedEnv?.envId.id,
637-
managerId: resolvedEnv?.envId.managerId ?? '',
638-
},
639-
name: 'defaultInterpreterPath: ' + (resolved.version ?? ''),
640-
displayName: 'defaultInterpreterPath: ' + (resolved.version ?? ''),
641-
version: resolved.version ?? '',
642-
displayPath: defaultInterpreterPath ?? '',
643-
environmentPath: defaultInterpreterPath ? Uri.file(defaultInterpreterPath) : Uri.file(''),
644-
sysPrefix: resolved.arch ?? '',
645-
execInfo: {
646-
run: {
647-
executable: defaultInterpreterPath ?? '',
648-
},
649-
},
650-
};
651-
if (workspace.workspaceFolders?.[0] && findEnvManager) {
652-
traceInfo(
653-
`[resolveDefaultInterpreter] Setting environment for workspace: ${workspace.workspaceFolders[0].uri.fsPath}`,
654-
);
655-
await api.setEnvironment(workspace.workspaceFolders[0].uri, newEnv);
656-
}
657-
}
658-
} else {
659-
traceWarn(
660-
`[resolveDefaultInterpreter] NativeFinder did not resolve an executable for path: ${defaultInterpreterPath}`,
661-
);
662-
}
663-
} catch (err) {
664-
traceError(`[resolveDefaultInterpreter] Error resolving default interpreter: ${err}`);
665-
}
666-
}
667-
}
668-
}
669-
670526
export async function deactivate(context: ExtensionContext) {
671527
await disposeAll(context.subscriptions);
672528
context.subscriptions.length = 0; // Clear subscriptions to prevent memory leaks

0 commit comments

Comments
 (0)