@@ -68,6 +68,7 @@ import {
6868} from '../../platform/interpreter/helpers' ;
6969import { JupyterServerCollection } from '../../api' ;
7070import { getJupyterDisplayName } from '../jupyter/connection/jupyterServerProviderRegistry' ;
71+ import { wasIPyKernelInstalAttempted } from '../../platform/interpreter/installer/productInstaller' ;
7172
7273/***
7374 * Common code for handling errors.
@@ -129,6 +130,21 @@ export abstract class DataScienceErrorHandler implements IDataScienceErrorHandle
129130 }
130131 }
131132 public async getErrorMessageForDisplayInCell ( error : Error , errorContext : KernelAction , resource : Resource ) {
133+ return this . getErrorMessageForDisplayInCellImpl ( error , errorContext , resource , false ) ;
134+ }
135+ public async getErrorMessageForDisplayInCellOutput (
136+ err : Error ,
137+ errorContext : KernelAction ,
138+ resource : Resource
139+ ) : Promise < string > {
140+ return this . getErrorMessageForDisplayInCellImpl ( err , errorContext , resource , true ) ;
141+ }
142+ private async getErrorMessageForDisplayInCellImpl (
143+ error : Error ,
144+ errorContext : KernelAction ,
145+ resource : Resource ,
146+ displayInCellOutput : boolean
147+ ) : Promise < string > {
132148 error = WrappedError . unwrap ( error ) ;
133149 if ( ! isCancellationError ( error ) ) {
134150 logger . error ( `Error in execution (get message for cell)` , error ) ;
@@ -138,7 +154,15 @@ export abstract class DataScienceErrorHandler implements IDataScienceErrorHandle
138154 // No need to display errors in each cell.
139155 return '' ;
140156 } else if ( error instanceof JupyterKernelDependencyError ) {
141- return getIPyKernelMissingErrorMessageForCell ( error . kernelConnectionMetadata ) || error . message ;
157+ const hasWorkspaceEnv = this . interpreterService
158+ ? await this . interpreterService . hasWorkspaceSpecificEnvironment ( )
159+ : false ;
160+ return (
161+ getIPyKernelMissingErrorMessageForCell (
162+ error . kernelConnectionMetadata ,
163+ ! hasWorkspaceEnv && ! isWebExtension ( ) && displayInCellOutput
164+ ) || error . message
165+ ) ;
142166 } else if ( error instanceof JupyterInstallError ) {
143167 return getJupyterMissingErrorMessageForCell ( error ) || error . message ;
144168 } else if ( error instanceof RemoteJupyterServerConnectionError && ! isWebExtension ( ) ) {
@@ -180,7 +204,15 @@ export abstract class DataScienceErrorHandler implements IDataScienceErrorHandle
180204 ) {
181205 // We don't look for ipykernel dependencies before we start a kernel, hence
182206 // its possible the kernel failed to start due to missing dependencies.
183- return getIPyKernelMissingErrorMessageForCell ( error . kernelConnectionMetadata ) || error . message ;
207+ const hasWorkspaceEnv = this . interpreterService
208+ ? await this . interpreterService . hasWorkspaceSpecificEnvironment ( )
209+ : false ;
210+ return (
211+ getIPyKernelMissingErrorMessageForCell (
212+ error . kernelConnectionMetadata ,
213+ ! hasWorkspaceEnv && ! isWebExtension ( ) && displayInCellOutput
214+ ) || error . message
215+ ) ;
184216 } else if ( error instanceof BaseKernelError || error instanceof WrappedKernelError ) {
185217 const [ files , sysPrefix ] = await Promise . all ( [
186218 this . getFilesInWorkingDirectoryThatCouldPotentiallyOverridePythonModules ( resource ) ,
@@ -199,7 +231,15 @@ export abstract class DataScienceErrorHandler implements IDataScienceErrorHandle
199231 failureInfo . reason === KernelFailureReason . moduleNotFoundFailure &&
200232 [ 'ipykernel_launcher' , 'ipykernel' ] . includes ( failureInfo . moduleName )
201233 ) {
202- return getIPyKernelMissingErrorMessageForCell ( error . kernelConnectionMetadata ) || error . message ;
234+ const hasWorkspaceEnv = this . interpreterService
235+ ? await this . interpreterService . hasWorkspaceSpecificEnvironment ( )
236+ : false ;
237+ return (
238+ getIPyKernelMissingErrorMessageForCell (
239+ error . kernelConnectionMetadata ,
240+ ! hasWorkspaceEnv && ! isWebExtension ( ) && displayInCellOutput
241+ ) || error . message
242+ ) ;
203243 }
204244 const messageParts = [ failureInfo . message ] ;
205245 if ( failureInfo . moreInfoLink ) {
@@ -569,7 +609,10 @@ function getCombinedErrorMessage(prefix: string = '', message: string = '') {
569609 }
570610 return errorMessage ;
571611}
572- function getIPyKernelMissingErrorMessageForCell ( kernelConnection : KernelConnectionMetadata ) {
612+ function getIPyKernelMissingErrorMessageForCell (
613+ kernelConnection : KernelConnectionMetadata ,
614+ recommendCreatingAndEnvironment : boolean
615+ ) {
573616 if (
574617 kernelConnection . kind === 'connectToLiveRemoteKernel' ||
575618 kernelConnection . kind === 'startUsingRemoteKernelSpec' ||
@@ -602,12 +645,23 @@ function getIPyKernelMissingErrorMessageForCell(kernelConnection: KernelConnecti
602645 getFilePath ( kernelConnection . interpreter . uri )
603646 ) } -m pip install ${ ipyKernelModuleName } -U --user --force-reinstall`;
604647 }
605- const message = DataScience . libraryRequiredToLaunchJupyterKernelNotInstalledInterpreter (
606- displayNameOfKernel ,
607- ProductNames . get ( Product . ipykernel ) !
608- ) ;
609- const installationInstructions = DataScience . installPackageInstructions ( ipyKernelName , installerCommand ) ;
610- return message + '\n' + installationInstructions ;
648+ const messages = [
649+ DataScience . libraryRequiredToLaunchJupyterKernelNotInstalledInterpreter (
650+ displayNameOfKernel ,
651+ ProductNames . get ( Product . ipykernel ) !
652+ )
653+ ] ;
654+ if ( recommendCreatingAndEnvironment ) {
655+ if ( wasIPyKernelInstalAttempted ( kernelConnection . interpreter ) ) {
656+ messages . push ( DataScience . createANewPythonEnvironment ( ) ) ;
657+ } else {
658+ messages . push ( DataScience . createANewPythonEnvironment ( ) ) ;
659+ messages . push ( DataScience . OrInstallPackageInstructions ( ipyKernelName , installerCommand ) ) ;
660+ }
661+ } else {
662+ messages . push ( DataScience . installPackageInstructions ( ipyKernelName , installerCommand ) ) ;
663+ }
664+ return messages . join ( '\n' ) ;
611665}
612666function getJupyterMissingErrorMessageForCell ( err : JupyterInstallError ) {
613667 const productNames = `${ ProductNames . get ( Product . jupyter ) } ${ Common . and } ${ ProductNames . get ( Product . notebook ) } ` ;
0 commit comments