@@ -7,7 +7,7 @@ import * as os from 'os';
77import * as path from 'path' ;
88
99import { IWorkspaceService } from '../../common/application/types' ;
10- import { IFileSystem } from '../../common/platform/types' ;
10+ import { IFileSystem , IPlatformService } from '../../common/platform/types' ;
1111import { IConfigurationService , IDisposableRegistry } from '../../common/types' ;
1212import * as localize from '../../common/utils/localize' ;
1313import { noop } from '../../common/utils/misc' ;
@@ -38,7 +38,9 @@ export class JupyterImporter implements INotebookImporter {
3838 @inject ( IDisposableRegistry ) private disposableRegistry : IDisposableRegistry ,
3939 @inject ( IConfigurationService ) private configuration : IConfigurationService ,
4040 @inject ( IJupyterExecution ) private jupyterExecution : IJupyterExecution ,
41- @inject ( IWorkspaceService ) private workspaceService : IWorkspaceService ) {
41+ @inject ( IWorkspaceService ) private workspaceService : IWorkspaceService ,
42+ @inject ( IPlatformService ) private readonly platform : IPlatformService
43+ ) {
4244 this . templatePromise = this . createTemplateFile ( ) ;
4345 }
4446
@@ -49,7 +51,7 @@ export class JupyterImporter implements INotebookImporter {
4951 const settings = this . configuration . getSettings ( ) ;
5052 let directoryChange : string | undefined ;
5153 if ( settings . datascience . changeDirOnImportExport ) {
52- directoryChange = this . calculateDirectoryChange ( file ) ;
54+ directoryChange = await this . calculateDirectoryChange ( file ) ;
5355 }
5456
5557 // Use the jupyter nbconvert functionality to turn the notebook into a python file
@@ -70,27 +72,39 @@ export class JupyterImporter implements INotebookImporter {
7072 }
7173
7274 private addDirectoryChange = ( pythonOutput : string , directoryChange : string ) : string => {
73- const newCode = CodeSnippits . ChangeDirectory . join ( os . EOL ) . format ( localize . DataScience . importChangeDirectoryComment ( ) , directoryChange ) ;
75+ const newCode = CodeSnippits . ChangeDirectory . join ( os . EOL ) . format ( localize . DataScience . importChangeDirectoryComment ( ) , CodeSnippits . ChangeDirectoryCommentIdentifier , directoryChange ) ;
7476 return newCode . concat ( pythonOutput ) ;
7577 }
7678
7779 // When importing a file, calculate if we can create a %cd so that the relative paths work
78- private calculateDirectoryChange = ( notebookFile : string ) : string | undefined = > {
80+ private async calculateDirectoryChange ( notebookFile : string ) : Promise < string | undefined > {
7981 let directoryChange : string | undefined ;
80- const notebookFilePath = path . dirname ( notebookFile ) ;
81- // First see if we have a workspace open, this only works if we have a workspace root to be relative to
82- if ( this . workspaceService . hasWorkspaceFolders ) {
83- const workspacePath = this . workspaceService . workspaceFolders ! [ 0 ] . uri . fsPath ;
84-
85- // Make sure that we have everything that we need here
86- if ( workspacePath && path . isAbsolute ( workspacePath ) && notebookFilePath && path . isAbsolute ( notebookFilePath ) ) {
87- directoryChange = path . relative ( workspacePath , notebookFilePath ) ;
82+ // Make sure we don't already have an import/export comment in the file
83+ const contents = await this . fileSystem . readFile ( notebookFile ) ;
84+ const haveChangeAlready = contents . includes ( CodeSnippits . ChangeDirectoryCommentIdentifier ) ;
85+
86+ if ( ! haveChangeAlready ) {
87+ const notebookFilePath = path . dirname ( notebookFile ) ;
88+ // First see if we have a workspace open, this only works if we have a workspace root to be relative to
89+ if ( this . workspaceService . hasWorkspaceFolders ) {
90+ const workspacePath = this . workspaceService . workspaceFolders ! [ 0 ] . uri . fsPath ;
91+
92+ // Make sure that we have everything that we need here
93+ if ( workspacePath && path . isAbsolute ( workspacePath ) && notebookFilePath && path . isAbsolute ( notebookFilePath ) ) {
94+ directoryChange = path . relative ( workspacePath , notebookFilePath ) ;
95+ }
8896 }
8997 }
9098
9199 // If path.relative can't calculate a relative path, then it just returns the full second path
92100 // so check here, we only want this if we were able to calculate a relative path, no network shares or drives
93101 if ( directoryChange && ! path . isAbsolute ( directoryChange ) ) {
102+
103+ // Escape windows path chars so they end up in the source escaped
104+ if ( this . platform . isWindows ) {
105+ directoryChange = directoryChange . replace ( '\\' , '\\\\' ) ;
106+ }
107+
94108 return directoryChange ;
95109 } else {
96110 return undefined ;
0 commit comments