From 3d42a2eed56607fdd88f65194c310e877d6c8588 Mon Sep 17 00:00:00 2001 From: ml7715 Date: Fri, 18 May 2018 15:12:05 +0100 Subject: [PATCH 1/6] Added interactive/special types --- src-backend/interpreter.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src-backend/interpreter.ts b/src-backend/interpreter.ts index c4489e1..d7dc7a9 100644 --- a/src-backend/interpreter.ts +++ b/src-backend/interpreter.ts @@ -148,8 +148,12 @@ export class ContentHelpers{ static chooseTypeFromComplexData(data: JSONValue) { let validDataTypes = - ['text/html', 'image/svg+xml', 'image/png', 'image/jpeg', 'text/markdown', 'application/pdf', - 'text/latex', 'application/javascript', 'application/json', 'text/plain'] + ['application/vnd.jupyter', 'application/vnd.jupyter.cells', + 'application/vnd.jupyter.dragindex', 'application/x-ipynb+json', + 'application/geo+json', 'application/vnd.plotly.v1+json', + 'application/vdom.v1+json', 'text/html', 'image/svg+xml', + 'image/png', 'image/jpeg', 'text/markdown', 'application/pdf', + 'text/latex', 'application/json', 'text/plain'] .filter(dataType => this.validateData(data, dataType)); return validDataTypes[0]; } From d612c23b7d4878865c69878572d8670f46ba02e2 Mon Sep 17 00:00:00 2001 From: ml7715 Date: Fri, 18 May 2018 16:20:09 +0100 Subject: [PATCH 2/6] Plotly now fully supported, enjoy 3d plots :-) --- src-backend/interpreter.ts | 32 +++++++++++++++++++++++++++----- src-frontend/src/index.html | 1 + 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src-backend/interpreter.ts b/src-backend/interpreter.ts index d7dc7a9..214e468 100644 --- a/src-backend/interpreter.ts +++ b/src-backend/interpreter.ts @@ -76,6 +76,7 @@ export class ContentHelpers{ static sourceTmp = ''; static contentTmp: Array = []; static id = 0; + static contentId = 0; private static _onStatusChanged: EventEmitter = new EventEmitter(); static get onStatusChanged(): Event { return this._onStatusChanged.event; } @@ -132,11 +133,7 @@ export class ContentHelpers{ // The output is rich } else if('data' in content){ let data = content.data; - let chosenType = this.chooseTypeFromComplexData(data); - let output = data[chosenType]; - if(typeof output === 'string'){ - this.contentTmp.push(new CardOutput(chosenType, output)); - } + this.interpretRich(data); // The code could not be executed, an error was returned } else if(['ename', 'evalue', 'traceback'].every(value => value in content)) { let ename = content['ename']; @@ -146,6 +143,31 @@ export class ContentHelpers{ } } + static interpretRich(data){ + let chosenType = this.chooseTypeFromComplexData(data); + let output = ''; + + if(chosenType === 'application/vnd.plotly.v1+json'){ + let plotlyJson = data[chosenType]; + if(ContentHelpers.validateData(plotlyJson, 'data')){ + output = + '
' + + '
'; + + this.contentId++; + } + chosenType = 'text/html'; + } + else{ + output = data[chosenType]; + } + if(typeof output === 'string'){ + this.contentTmp.push(new CardOutput(chosenType, output)); + } + } + static chooseTypeFromComplexData(data: JSONValue) { let validDataTypes = ['application/vnd.jupyter', 'application/vnd.jupyter.cells', diff --git a/src-frontend/src/index.html b/src-frontend/src/index.html index d88ba94..2cc62ef 100644 --- a/src-frontend/src/index.html +++ b/src-frontend/src/index.html @@ -8,6 +8,7 @@ + From 7832caa703acd9ee15873c6492e87f6da119d5e5 Mon Sep 17 00:00:00 2001 From: ml7715 Date: Fri, 18 May 2018 16:22:37 +0100 Subject: [PATCH 3/6] Added python samples to test plotting --- python_samples.py | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 python_samples.py diff --git a/python_samples.py b/python_samples.py new file mode 100644 index 0000000..3b90117 --- /dev/null +++ b/python_samples.py @@ -0,0 +1,75 @@ +from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot + +from plotly.graph_objs import Scatter, Figure, Layout + +init_notebook_mode(connected=True) + +iplot([{"x": [1, 2, 3], "y": [3, 1, 6]}]) + + + +from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot + +import plotly.graph_objs as go + +import pandas as pd + +# Read data from a csv +z_data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv') + +data = [ + go.Surface( + z=z_data.as_matrix() + ) +] +layout = go.Layout( + title='Mt Bruno Elevation', + autosize=False, + width=500, + height=500, + margin=dict( + l=65, + r=50, + b=65, + t=90 + ) +) +fig = go.Figure(data=data, layout=layout) +iplot(fig) + + + +from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot + +import plotly.graph_objs as go + + +z1 = [ + [8.83,8.89,8.81,8.87,8.9,8.87], + [8.89,8.94,8.85,8.94,8.96,8.92], + [8.84,8.9,8.82,8.92,8.93,8.91], + [8.79,8.85,8.79,8.9,8.94,8.92], + [8.79,8.88,8.81,8.9,8.95,8.92], + [8.8,8.82,8.78,8.91,8.94,8.92], + [8.75,8.78,8.77,8.91,8.95,8.92], + [8.8,8.8,8.77,8.91,8.95,8.94], + [8.74,8.81,8.76,8.93,8.98,8.99], + [8.89,8.99,8.92,9.1,9.13,9.11], + [8.97,8.97,8.91,9.09,9.11,9.11], + [9.04,9.08,9.05,9.25,9.28,9.27], + [9,9.01,9,9.2,9.23,9.2], + [8.99,8.99,8.98,9.18,9.2,9.19], + [8.93,8.97,8.97,9.18,9.2,9.18] +] + +z2 = [[zij+1 for zij in zi] for zi in z1] +z3 = [[zij-1 for zij in zi] for zi in z1] + +data = [ + go.Surface(z=z1), + go.Surface(z=z2, showscale=False, opacity=0.9), + go.Surface(z=z3, showscale=False, opacity=0.9) + +] + +iplot(data,filename='python-docs/multiple-surfaces') \ No newline at end of file From be096101c3f568f631cc222f58410f94ba5257ec Mon Sep 17 00:00:00 2001 From: ml7715 Date: Fri, 18 May 2018 17:17:03 +0100 Subject: [PATCH 4/6] Ask user to install missing modules, fixed pull request issues --- src-backend/interpreter.ts | 45 ++++++++++++++----- .../samples/python_samples.py | 0 2 files changed, 35 insertions(+), 10 deletions(-) rename python_samples.py => test/samples/python_samples.py (100%) diff --git a/src-backend/interpreter.ts b/src-backend/interpreter.ts index 214e468..7ed8360 100644 --- a/src-backend/interpreter.ts +++ b/src-backend/interpreter.ts @@ -76,7 +76,6 @@ export class ContentHelpers{ static sourceTmp = ''; static contentTmp: Array = []; static id = 0; - static contentId = 0; private static _onStatusChanged: EventEmitter = new EventEmitter(); static get onStatusChanged(): Event { return this._onStatusChanged.event; } @@ -133,38 +132,55 @@ export class ContentHelpers{ // The output is rich } else if('data' in content){ let data = content.data; - this.interpretRich(data); + this.contentTmp.push(this.interpretRich(data)); // The code could not be executed, an error was returned } else if(['ename', 'evalue', 'traceback'].every(value => value in content)) { let ename = content['ename']; let evalue = content['evalue']; + this.getMissingModule(evalue as string); let traceback = (content['traceback'] as string[]).join('\n'); this.contentTmp.push(new CardOutput('error', traceback)); } } - static interpretRich(data){ + static interpretRich(data: JSONValue){ let chosenType = this.chooseTypeFromComplexData(data); - let output = ''; + let output: string = ''; if(chosenType === 'application/vnd.plotly.v1+json'){ let plotlyJson = data[chosenType]; if(ContentHelpers.validateData(plotlyJson, 'data')){ + let guid = this.generateGuid() output = - '
' + '
' + '
'; - - this.contentId++; + + guid + '",' + JSON.stringify(plotlyJson.data) + ', {}, {"showLink": true, "linkText": "Export to plot.ly"})});'; } chosenType = 'text/html'; } else{ output = data[chosenType]; } - if(typeof output === 'string'){ - this.contentTmp.push(new CardOutput(chosenType, output)); + return new CardOutput(chosenType, output); + } + + static getMissingModule(evalue: string){ + if(evalue.match(/No module named/i)){ + let moduleMatch = /'.+'/i.exec(evalue); + if(moduleMatch && moduleMatch.length){ + let module = moduleMatch[0].replace(/\'/g, ''); + vscode.window.showInformationMessage('Jupyter requires the module ' + moduleMatch[0] + ' to be installed. Install now?', 'Install') + .then(data => this.installMissingModule(data, module)); + } + } + } + + static installMissingModule(data, module: string){ + if (module) { + let terminal = vscode.window.createTerminal('pip'); + terminal.show(); + terminal.sendText('pip install '+module, true); } } @@ -185,4 +201,13 @@ export class ContentHelpers{ this.contentTmp = []; this.id++; } + + static generateGuid() { + function s4() { + return Math.floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); + } + return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); + } } diff --git a/python_samples.py b/test/samples/python_samples.py similarity index 100% rename from python_samples.py rename to test/samples/python_samples.py From 25ff5a34d40111bd7c62b65a9dd9a548f67c8775 Mon Sep 17 00:00:00 2001 From: ml7715 Date: Fri, 18 May 2018 20:08:53 +0100 Subject: [PATCH 5/6] interpreter code refactored --- src-backend/interpreter.ts | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src-backend/interpreter.ts b/src-backend/interpreter.ts index 7ed8360..61eec73 100644 --- a/src-backend/interpreter.ts +++ b/src-backend/interpreter.ts @@ -143,14 +143,14 @@ export class ContentHelpers{ } } - static interpretRich(data: JSONValue){ + static interpretRich(data: JSONValue): CardOutput{ let chosenType = this.chooseTypeFromComplexData(data); let output: string = ''; if(chosenType === 'application/vnd.plotly.v1+json'){ let plotlyJson = data[chosenType]; if(ContentHelpers.validateData(plotlyJson, 'data')){ - let guid = this.generateGuid() + let guid = this.generateGuid(); output = '
' + '