Skip to content

Commit bbfec89

Browse files
authored
Prelimnary support to load ipyn files in native Notebook editor (#11841)
For #10496 If user is in notebook experiment, then make changes to package.json
1 parent 3c0e1b5 commit bbfec89

16 files changed

Lines changed: 849 additions & 16 deletions

File tree

build/ci/templates/steps/compile.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ steps:
88
compile: 'false'
99
installVSCEorNPX: 'false'
1010

11+
- task: Gulp@0
12+
displayName: 'Validate package.json'
13+
inputs:
14+
targets: 'validate-packagejson'
15+
1116
- task: Gulp@0
1217
displayName: 'Compile and check for errors'
1318
inputs:

experiments.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@
125125
"min": 0,
126126
"max": 100
127127
},
128+
{
129+
"name": "NativeNotebook - experiment",
130+
"salt": "NativeNotebook",
131+
"max": 0,
132+
"min": 0
133+
},
134+
{
135+
"name": "NativeNotebook - control",
136+
"salt": "NativeNotebook",
137+
"min": 0,
138+
"max": 100
139+
},
128140
{
129141
"name": "CollectLSRequestTiming - experiment",
130142
"salt": "CollectLSRequestTiming",

gulpfile.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,23 @@ gulp.task('checkNativeDependencies', (done) => {
114114

115115
gulp.task('check-datascience-dependencies', () => checkDatascienceDependencies());
116116

117+
gulp.task('validate-packagejson', () => validatePackageJson());
118+
117119
const webpackEnv = { NODE_OPTIONS: '--max_old_space_size=9096' };
118120

121+
async function validatePackageJson(){
122+
const json = require('./package.json');
123+
if (json.enableProposedApi){
124+
throw new Error('package.json has enableProposedApi setting enabled');
125+
}
126+
if (json.contributes.notebookOutputRenderer){
127+
throw new Error('Package.json contains entry for contributes.notebookOutputRenderer');
128+
}
129+
if (json.contributes.notebookProvider){
130+
throw new Error('Package.json contains entry for contributes.notebookProvider');
131+
}
132+
}
133+
119134
async function buildIPyWidgets() {
120135
await spawnAsync('npm', ['run', 'build-ipywidgets'], webpackEnv);
121136
}

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
"onCommand:python.datascience.selectjupytercommandline",
9292
"onCommand:python.enableSourceMapSupport",
9393
"onCustomEditor:NativeEditorProvider.ipynb",
94+
"onNotebookEditor:jupyter-notebook",
9495
"workspaceContains:**/mspythonconfig.json"
9596
],
9697
"main": "./out/client/extension",
@@ -1600,6 +1601,7 @@
16001601
"AA_testing - experiment",
16011602
"WebHostNotebook - experiment",
16021603
"LocalZMQKernel - experiment",
1604+
"NativeNotebook - experiment",
16031605
"UseTerminalToGetActivatedEnvVars - experiment",
16041606
"CollectLSRequestTiming - experiment",
16051607
"CollectNodeLSRequestTiming - experiment",
@@ -1625,6 +1627,7 @@
16251627
"AA_testing - experiment",
16261628
"WebHostNotebook - experiment",
16271629
"LocalZMQKernel - experiment",
1630+
"NativeNotebook - experiment",
16281631
"UseTerminalToGetActivatedEnvVars - experiment",
16291632
"CollectLSRequestTiming - experiment",
16301633
"CollectNodeLSRequestTiming - experiment",

src/client/common/constants.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ export const PYTHON_WARNINGS = 'PYTHONWARNINGS';
77
export const PYTHON = [
88
{ scheme: 'file', language: PYTHON_LANGUAGE },
99
{ scheme: 'untitled', language: PYTHON_LANGUAGE },
10-
{ scheme: 'vscode-notebook', language: PYTHON_LANGUAGE }
10+
{ scheme: 'vscode-notebook', language: PYTHON_LANGUAGE },
11+
{ scheme: 'vscode-notebook-cell', language: PYTHON_LANGUAGE }
1112
];
1213
export const PYTHON_ALLFILES = [{ language: PYTHON_LANGUAGE }];
1314

@@ -107,5 +108,6 @@ export function isUnitTestExecution(): boolean {
107108

108109
// Temporary constant, used to indicate whether we're using custom editor api or not.
109110
export const UseCustomEditorApi = Symbol('USE_CUSTOM_EDITOR');
111+
export const UseProposedApi = Symbol('USE_VSC_PROPOSED_API');
110112

111113
export * from '../constants';

src/client/common/experimentGroups.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ export enum LocalZMQKernel {
4848
experiment = 'LocalZMQKernel - experiment'
4949
}
5050

51+
// Experiment to use VSC Notebook Implementation
52+
export enum NativeNotebook {
53+
control = 'NativeNotebook - control',
54+
experiment = 'NativeNotebook - experiment'
55+
}
56+
5157
// Experiment for supporting run by line in data science notebooks
5258
export enum RunByLine {
5359
control = 'RunByLine - control',
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
'use strict';
5+
6+
import { inject, injectable } from 'inversify';
7+
import {
8+
CancellationToken,
9+
EventEmitter,
10+
NotebookContentProvider as VSCodeNotebookContentProvider,
11+
NotebookData,
12+
NotebookDocument,
13+
NotebookDocumentEditEvent,
14+
Uri
15+
} from 'vscode';
16+
import { INotebookStorageProvider } from '../interactive-ipynb/notebookStorageProvider';
17+
import { notebookModelToVSCNotebookData } from './helpers';
18+
19+
/**
20+
* This class is responsible for reading a notebook file (ipynb or other files) and returning VS Code with the NotebookData.
21+
* Its upto extension authors to read the files and return it in a format that VSCode understands.
22+
* Same with the cells and cell output.
23+
*
24+
* Also responsbile for saving of notebooks.
25+
* When saving, VSC will provide their model and we need to take that and merge it with an existing ipynb json (if any, to preserve metadata).
26+
*/
27+
@injectable()
28+
export class NotebookContentProvider implements VSCodeNotebookContentProvider {
29+
private notebookChanged = new EventEmitter<NotebookDocumentEditEvent>();
30+
public get onDidChangeNotebook() {
31+
return this.notebookChanged.event;
32+
}
33+
constructor(@inject(INotebookStorageProvider) private readonly notebookStorage: INotebookStorageProvider) {}
34+
public async openNotebook(uri: Uri): Promise<NotebookData> {
35+
const model = await this.notebookStorage.load(uri);
36+
return notebookModelToVSCNotebookData(model);
37+
}
38+
public async saveNotebook(document: NotebookDocument, cancellation: CancellationToken) {
39+
const model = await this.notebookStorage.load(document.uri);
40+
if (model.isUntitled) {
41+
return;
42+
}
43+
await this.notebookStorage.save(model, cancellation);
44+
}
45+
46+
public async saveNotebookAs(
47+
targetResource: Uri,
48+
document: NotebookDocument,
49+
cancellation: CancellationToken
50+
): Promise<void> {
51+
const model = await this.notebookStorage.load(document.uri);
52+
if (!cancellation.isCancellationRequested) {
53+
await this.notebookStorage.saveAs(model, targetResource);
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)