Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 2 additions & 3 deletions src/kernels/errors/kernelErrorHandler.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ export class DataScienceErrorHandlerNode extends DataScienceErrorHandler {
) {
// Looks like some other module is missing.
// Sometimes when you create files like xml.py, then kernel startup fails due to xml.dom module not being found.
const problematicFiles = await this.getFilesInWorkingDirectoryThatCouldPotentiallyOverridePythonModules(
resource
);
const problematicFiles =
await this.getFilesInWorkingDirectoryThatCouldPotentiallyOverridePythonModules(resource);
if (problematicFiles.length > 0) {
const cwd = resource ? path.dirname(resource) : undefined;
const fileLinks = problematicFiles.map((item) => {
Expand Down
4 changes: 2 additions & 2 deletions src/kernels/errors/kernelErrorHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,8 @@ export abstract class DataScienceErrorHandler implements IDataScienceErrorHandle
err instanceof InvalidRemoteJupyterServerUriHandleError
? ''
: err instanceof RemoteJupyterServerConnectionError
? err.originalError.message || ''
: err.originalError?.message || err.message;
? err.originalError.message || ''
: err.originalError?.message || err.message;

const extensionId = err.serverProviderHandle.extensionId;
const id = err.serverProviderHandle.id;
Expand Down
9 changes: 5 additions & 4 deletions src/kernels/execution/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,9 @@ export function traceCellMessage(cell: NotebookCell, message: string | (() => st
() =>
`Cell Index:${cell.index}, of document ${uriPath.basename(
cell.notebook.uri
)} with state:${NotebookCellStateTracker.getCellStatus(cell)}, exec: ${cell.executionSummary
?.executionOrder}. ${messageToLog()}. called from ${getExtensionSpecificStack()}`
)} with state:${NotebookCellStateTracker.getCellStatus(cell)}, exec: ${
cell.executionSummary?.executionOrder
}. ${messageToLog()}. called from ${getExtensionSpecificStack()}`
);
}

Expand Down Expand Up @@ -651,8 +652,8 @@ export async function updateNotebookMetadataWithSelectedKernel(
kernelConnection && kernelConnectionMetadataHasKernelModel(kernelConnection)
? kernelConnection.kernelModel
: kernelConnection && 'kernelSpec' in kernelConnection
? kernelConnection.kernelSpec
: undefined;
? kernelConnection.kernelSpec
: undefined;
if (kernelConnection?.kind === 'startUsingPythonInterpreter') {
// Store interpreter name, we expect the kernel finder will find the corresponding interpreter based on this name.
const kernelSpec = kernelConnection.kernelSpec;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,8 @@ suite('Jupyter InterpreterSubCommandExecutionService', () => {
});
test('Jupyter cannot be started because no interpreter has been selected', async () => {
when(interpreterService.getActiveInterpreter(undefined)).thenResolve(undefined);
const reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(
undefined
);
const reason =
await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined);
assert.equal(reason, DataScience.selectJupyterInterpreter);
});
test('Jupyter cannot be started because jupyter is not installed', async () => {
Expand Down Expand Up @@ -152,9 +151,8 @@ suite('Jupyter InterpreterSubCommandExecutionService', () => {
when(jupyterDependencyService.getDependenciesNotInstalled(activePythonInterpreter, undefined)).thenResolve([
Product.jupyter
]);
const reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(
undefined
);
const reason =
await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined);
assert.equal(reason, expectedReason);
});
test('Jupyter cannot be started because notebook is not installed', async () => {
Expand Down Expand Up @@ -183,9 +181,8 @@ suite('Jupyter InterpreterSubCommandExecutionService', () => {
when(jupyterDependencyService.getDependenciesNotInstalled(activePythonInterpreter, undefined)).thenResolve([
Product.notebook
]);
const reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(
undefined
);
const reason =
await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined);
assert.equal(reason, expectedReason);
});
test('Cannot start notebook', async () => {
Expand Down Expand Up @@ -306,9 +303,8 @@ suite('Jupyter InterpreterSubCommandExecutionService', () => {
jupyterDependencyService.getDependenciesNotInstalled(selectedJupyterInterpreter, undefined)
).thenResolve([Product.jupyter]);

let reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(
undefined
);
let reason =
await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined);

// replace interpreter name with *** to workaround flakey test.
reason = reason.replace(/('.*?')/g, "'***'");
Expand Down Expand Up @@ -343,9 +339,8 @@ suite('Jupyter InterpreterSubCommandExecutionService', () => {
jupyterDependencyService.getDependenciesNotInstalled(selectedJupyterInterpreter, undefined)
).thenResolve([Product.notebook]);

let reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(
undefined
);
let reason =
await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined);
// replace interpreter name with *** to workaround flakey test.
reason = reason.replace(/('.*?')/g, "'***'");

Expand All @@ -356,9 +351,8 @@ suite('Jupyter InterpreterSubCommandExecutionService', () => {
jupyterDependencyService.getDependenciesNotInstalled(selectedJupyterInterpreter, undefined)
).thenResolve([Product.kernelspec]);

const reason = await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(
undefined
);
const reason =
await jupyterInterpreterExecutionService.getReasonForJupyterNotebookNotBeingSupported(undefined);

assert.equal(reason, DataScience.jupyterKernelSpecModuleNotFound(selectedJupyterInterpreter.uri.fsPath));
});
Expand Down
12 changes: 6 additions & 6 deletions src/kernels/kernel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,8 @@ abstract class BaseKernel implements IBaseKernel {
this._session = this._session
? this._session
: this._jupyterSessionPromise
? await this._jupyterSessionPromise.catch(() => undefined)
: undefined;
? await this._jupyterSessionPromise.catch(() => undefined)
: undefined;
this._jupyterSessionPromise = undefined;
this._postInitializedOnStartPromise = undefined;
if (this._session) {
Expand Down Expand Up @@ -875,11 +875,11 @@ abstract class BaseKernel implements IBaseKernel {
logger.error('Failed to determine version of IPyWidgets', ex)
);
if (Array.isArray(version)) {
const isVersion8 = version.some(
(output) => (output.text || '')?.toString().includes(`${widgetVersionOutPrefix}8.`)
const isVersion8 = version.some((output) =>
(output.text || '')?.toString().includes(`${widgetVersionOutPrefix}8.`)
);
const isVersion7 = version.some(
(output) => (output.text || '')?.toString().includes(`${widgetVersionOutPrefix}7.`)
const isVersion7 = version.some((output) =>
(output.text || '')?.toString().includes(`${widgetVersionOutPrefix}7.`)
);

const newVersion = (this._ipywidgetsVersion = isVersion7 ? 7 : isVersion8 ? 8 : undefined);
Expand Down
4 changes: 2 additions & 2 deletions src/kernels/raw/session/kernelWorkingDirectory.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ export async function computeLocalWorkingDirectory(
suggestedDir && suggestedDir.includes('${')
? suggestedDir
: suggestedDir
? getFilePath(Uri.file(suggestedDir))
: undefined;
? getFilePath(Uri.file(suggestedDir))
: undefined;
const expandedWorkingDir = expandWorkingDir(workingDir, resource, configService.getSettings(resource));
if (await fs.exists(Uri.file(expandedWorkingDir))) {
return expandedWorkingDir;
Expand Down
4 changes: 2 additions & 2 deletions src/notebooks/debugger/kernelDebugAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class KernelDebugAdapter extends KernelDebugAdapterBase {
return;
}
const cell = this.notebookDocument.getCells().find((c) => c.document.uri.toString() === mapping.toString());
const offset = cell ? this.lineOffsets.get(cell) ?? 0 : 0;
const offset = cell ? (this.lineOffsets.get(cell) ?? 0) : 0;
source.name = path.basename(mapping.path);
source.path = mapping.toString();
if (offset && typeof location?.endLine === 'number') {
Expand Down Expand Up @@ -79,7 +79,7 @@ export class KernelDebugAdapter extends KernelDebugAdapterBase {
return;
}
const cell = this.notebookDocument.getCells().find((c) => c.document.uri.toString() === source.path);
const offset = cell ? this.lineOffsets.get(cell) ?? 0 : 0;
const offset = cell ? (this.lineOffsets.get(cell) ?? 0) : 0;
source.path = mapping;
if (offset && typeof location.line === 'number') {
if (location.line < offset) {
Expand Down
8 changes: 4 additions & 4 deletions src/platform/api/pythonApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,14 +508,14 @@ export class InterpreterService implements IInterpreterService {
return isUri(pythonPath)
? areInterpreterPathsSame(item.executable.uri, pythonPath)
: typeof pythonPath === 'string'
? item.id === pythonPath
: areInterpreterPathsSame(Uri.file(item.path), Uri.file(pythonPath.path));
? item.id === pythonPath
: areInterpreterPathsSame(Uri.file(item.path), Uri.file(pythonPath.path));
});
const pythonPathForLogging = isUri(pythonPath)
? getDisplayPath(pythonPath)
: typeof pythonPath === 'string'
? pythonPath
: getDisplayPath(Uri.file(pythonPath.path));
? pythonPath
: getDisplayPath(Uri.file(pythonPath.path));
if (matchedPythonEnv) {
const env = await api.environments.resolveEnvironment(matchedPythonEnv);
const resolved = this.trackResolvedEnvironment(env);
Expand Down
4 changes: 2 additions & 2 deletions src/platform/common/application/workspace.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export function getWorkspaceFolderIdentifier(resource: Resource, defaultValue: s
const workspaceFolder = resource
? workspace.getWorkspaceFolder(resource)
: workspace.workspaceFolders
? workspace.workspaceFolders[0] // Default to first folder if resource not passed in.
: undefined;
? workspace.workspaceFolders[0] // Default to first folder if resource not passed in.
: undefined;
return workspaceFolder
? path.normalize(
getOSType() === OSType.Windows ? workspaceFolder.uri.path.toUpperCase() : workspaceFolder.uri.path
Expand Down
4 changes: 2 additions & 2 deletions src/platform/common/configuration/service.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ export abstract class BaseConfigurationService implements IConfigurationService
target === ConfigurationTarget.Global
? setting.globalValue
: target === ConfigurationTarget.Workspace
? setting.workspaceValue
: setting.workspaceFolderValue;
? setting.workspaceValue
: setting.workspaceFolderValue;
if (actual === value) {
break;
}
Expand Down
4 changes: 2 additions & 2 deletions src/platform/common/providerBasedQuickPick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,8 +474,8 @@ export class BaseProviderBasedQuickPick<T extends { id: string }> extends Dispos
const activeItems = selectedQuickPickItem
? [selectedQuickPickItem]
: quickPick.activeItems.length
? [quickPick.activeItems[0]]
: [];
? [quickPick.activeItems[0]]
: [];
if (activeItems.length && !items.includes(activeItems[0])) {
const oldActiveItem = activeItems[0];
const newActiveQuickPickItem =
Expand Down
8 changes: 4 additions & 4 deletions src/platform/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,13 +296,13 @@ export function parseForComments(
const isMultilineComment = trim.startsWith(SingleQuoteMultiline)
? SingleQuoteMultiline
: trim.startsWith(DoubleQuoteMultiline)
? DoubleQuoteMultiline
: undefined;
? DoubleQuoteMultiline
: undefined;
const isMultilineQuote = trim.includes(SingleQuoteMultiline)
? SingleQuoteMultiline
: trim.includes(DoubleQuoteMultiline)
? DoubleQuoteMultiline
: undefined;
? DoubleQuoteMultiline
: undefined;

// Check for ending quotes of multiline string
if (insideMultilineQuote) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ export class CustomEnvironmentVariablesProvider implements ICustomEnvironmentVar
resource = resource
? resource
: workspace.workspaceFolders?.length
? workspace.workspaceFolders[0].uri
: undefined;
? workspace.workspaceFolders[0].uri
: undefined;

if (purpose === 'RunPythonCode') {
// No need to cache for Python code, as we get these env vars from Python extension.
Expand Down Expand Up @@ -87,8 +87,8 @@ export class CustomEnvironmentVariablesProvider implements ICustomEnvironmentVar
resource = resource
? resource
: workspace.workspaceFolders?.length
? workspace.workspaceFolders[0].uri
: undefined;
? workspace.workspaceFolders[0].uri
: undefined;
const workspaceFolderUri = this.getWorkspaceFolderUri(resource);
if (!workspaceFolderUri) {
logger.ci(`No workspace folder found for ${resource ? resource.fsPath : '<No Resource>'}`);
Expand Down
4 changes: 2 additions & 2 deletions src/platform/interpreter/environmentActivationService.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi
resource = resource
? resource
: workspace.workspaceFolders?.length
? workspace.workspaceFolders[0].uri
: undefined;
? workspace.workspaceFolders[0].uri
: undefined;
const stopWatch = new StopWatch();
// We'll need this later.
const customEnvVarsPromise = this.customEnvVarsService
Expand Down
8 changes: 7 additions & 1 deletion src/platform/interpreter/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ const environmentTypes = [
EnvironmentType.Pyenv,
EnvironmentType.Venv,
EnvironmentType.VirtualEnv,
EnvironmentType.VirtualEnvWrapper
EnvironmentType.VirtualEnvWrapper,
EnvironmentType.UV
];

export function getEnvironmentType(interpreter: { id: string }): EnvironmentType {
Expand All @@ -93,6 +94,11 @@ function getEnvironmentTypeImpl(env: Environment): EnvironmentType {
return EnvironmentType.Conda;
}

// Check for UV environment by looking for uv tools
if (env.tools.some((tool) => tool.toLowerCase() === 'uv')) {
return EnvironmentType.UV;
}

// Map the Python env tool to a Jupyter environment type.
const orderOrEnvs: [pythonEnvTool: KnownEnvironmentTools, JupyterEnv: EnvironmentType][] = [
['Conda', EnvironmentType.Conda],
Expand Down
34 changes: 21 additions & 13 deletions src/platform/interpreter/installer/channelManager.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { IPlatformService } from '../../common/platform/types';
import { Installer } from '../../common/utils/localize';
import { IServiceContainer } from '../../ioc/types';
import { IInstallationChannelManager, IModuleInstaller, Product } from './types';
import { Uri, env, window } from 'vscode';
import { Uri, env, window, l10n } from 'vscode';
import { getEnvironmentType } from '../helpers';

/**
Expand Down Expand Up @@ -61,21 +61,29 @@ export class InstallationChannelManager implements IInstallationChannelManager {

public async showNoInstallersMessage(interpreter: PythonEnvironment): Promise<void> {
const envType = getEnvironmentType(interpreter);
const result = await window.showErrorMessage(
envType === EnvironmentType.Conda ? Installer.noCondaOrPipInstaller : Installer.noPipInstaller,
{ modal: true },
Installer.searchForHelp
);
let message: string;
let searchTerm: string;

switch (envType) {
case EnvironmentType.Conda:
message = Installer.noCondaOrPipInstaller;
searchTerm = 'Install Pip Conda';
break;
case EnvironmentType.UV:
message = l10n.t('There is no UV installer available in the selected environment.');
searchTerm = 'Install UV Python';
break;
default:
message = Installer.noPipInstaller;
searchTerm = 'Install Pip';
break;
}

const result = await window.showErrorMessage(message, { modal: true }, Installer.searchForHelp);
if (result === Installer.searchForHelp) {
const platform = this.serviceContainer.get<IPlatformService>(IPlatformService);
const osName = platform.isWindows ? 'Windows' : platform.isMac ? 'MacOS' : 'Linux';
void env.openExternal(
Uri.parse(
`https://www.bing.com/search?q=Install Pip ${osName} ${
envType === EnvironmentType.Conda ? 'Conda' : ''
}`
)
);
void env.openExternal(Uri.parse(`https://www.bing.com/search?q=${searchTerm} ${osName}`));
}
}
}
3 changes: 2 additions & 1 deletion src/platform/interpreter/installer/pipInstaller.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ export class PipInstaller extends ModuleInstaller {
}
public async isSupported(interpreter: PythonEnvironment | Environment): Promise<boolean> {
const envType = getEnvironmentType(interpreter);
// Skip this on conda, poetry, and pipenv environments
// Skip this on conda, poetry, pipenv, and UV environments
switch (envType) {
case EnvironmentType.Conda:
case EnvironmentType.Pipenv:
case EnvironmentType.Poetry:
case EnvironmentType.UV:
return false;
}

Expand Down
3 changes: 2 additions & 1 deletion src/platform/interpreter/installer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export enum ModuleInstallerType {
Conda = 'Conda',
Pip = 'Pip',
Poetry = 'Poetry',
Pipenv = 'Pipenv'
Pipenv = 'Pipenv',
UV = 'UV'
}

export enum ProductType {
Expand Down
Loading