Skip to content

Commit d4c3132

Browse files
authored
Add ipywidget deps to main package.json and update builds(#10615)
1 parent 164727a commit d4c3132

26 files changed

+1926
-7406
lines changed

build/webpack/webpack.datascience-ui.config.builder.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ function buildConfiguration(isNotebook) {
185185
{
186186
from: path.join(constants.ExtensionRootDir, 'node_modules/requirejs/require.js'),
187187
to: path.join(constants.ExtensionRootDir, 'out', 'datascience-ui', bundleFolder)
188+
},
189+
{
190+
from: path.join(constants.ExtensionRootDir, 'out/ipywidgets/dist/ipywidgets.js'),
191+
to: path.join(constants.ExtensionRootDir, 'out', 'datascience-ui', bundleFolder)
188192
}
189193
],
190194
{ context: 'src' }

gulpfile.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,11 @@ gulp.task('check-datascience-dependencies', () => checkDatascienceDependencies()
116116

117117
const webpackEnv = { NODE_OPTIONS: '--max_old_space_size=9096' };
118118

119+
async function buildIPyWidgets() {
120+
await spawnAsync('npm', ['run', 'build-ipywidgets'], webpackEnv);
121+
}
119122
async function buildDataScienceUI() {
123+
await buildIPyWidgets();
120124
await spawnAsync(
121125
'npm',
122126
[
@@ -158,6 +162,7 @@ gulp.task('webpack', async () => {
158162
);
159163
// Build DS stuff (separately as it uses far too much memory and slows down CI).
160164
// Individually is faster on CI.
165+
await buildIPyWidgets();
161166
await buildWebPack(
162167
'production',
163168
['--config', './build/webpack/webpack.datascience-ui-notebooks.config.js'],

package-lock.json

Lines changed: 1320 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,9 @@
13771377
"default": "127.0.0.1"
13781378
}
13791379
},
1380-
"required": ["port"]
1380+
"required": [
1381+
"port"
1382+
]
13811383
},
13821384
"listen": {
13831385
"type": "object",
@@ -1393,7 +1395,9 @@
13931395
"default": "127.0.0.1"
13941396
}
13951397
},
1396-
"required": ["port"]
1398+
"required": [
1399+
"port"
1400+
]
13971401
},
13981402
"port": {
13991403
"type": "number",
@@ -2872,7 +2876,12 @@
28722876
"scripts": {
28732877
"package": "gulp clean && gulp prePublishBundle && vsce package -o ms-python-insiders.vsix",
28742878
"compile": "tsc -watch -p ./",
2875-
"compile-webviews-watch": "cross-env NODE_OPTIONS=--max_old_space_size=9096 webpack --config ./build/webpack/webpack.datascience-ui.config.js --watch",
2879+
"compile-webviews-watch": "npm run build-ipywidgets && cross-env NODE_OPTIONS=--max_old_space_size=9096 webpack --config ./build/webpack/webpack.datascience-ui.config.js --watch",
2880+
"build-ipywidgets": "npm run build-ipywidgets-clean && npm run build-ipywidgets-compile && npm run build-ipywidgets-webpack && npm run build-ipywidgets-update",
2881+
"build-ipywidgets-clean": "node ./src/ipywidgets/scripts/clean.js",
2882+
"build-ipywidgets-compile": "tsc -p ./src/ipywidgets && rimraf ./out/tsconfig.tsbuildinfo && node ./src/ipywidgets/scripts/copyfiles.js",
2883+
"build-ipywidgets-webpack": "cross-env NODE_OPTIONS=--max_old_space_size=9096 webpack --config ./src/ipywidgets/webpack.config.js",
2884+
"build-ipywidgets-update": "node ./src/ipywidgets/scripts/copyBuild.js",
28762885
"checkDependencies": "gulp checkDependencies",
28772886
"postinstall": "node ./build/ci/postInstall.js",
28782887
"test": "node ./out/test/standardTest.js && node ./out/test/multiRootTest.js",
@@ -2889,6 +2898,7 @@
28892898
"testSmoke": "node ./out/test/smokeTest.js",
28902899
"lint-staged": "node gulpfile.js",
28912900
"lint": "tslint src/**/*.ts -t verbose",
2901+
"prettier-fix": "prettier 'src/**/*.ts*' --write && prettier 'build/**/*.js' --write",
28922902
"clean": "gulp clean",
28932903
"updateBuildNumber": "gulp updateBuildNumber",
28942904
"verifyBundle": "gulp verifyBundle",
@@ -2971,13 +2981,15 @@
29712981
"@jupyter-widgets/base": "^2.0.1",
29722982
"@jupyter-widgets/controls": "^1.5.2",
29732983
"@jupyter-widgets/html-manager": "^0.18.3",
2984+
"@jupyter-widgets/output": "^2.0.1",
29742985
"@nteract/plotly": "^1.48.3",
29752986
"@nteract/transform-dataresource": "^4.3.5",
29762987
"@nteract/transform-geojson": "^3.2.3",
29772988
"@nteract/transform-model-debug": "^3.2.3",
29782989
"@nteract/transform-plotly": "^6.0.0",
29792990
"@nteract/transform-vega": "^6.0.3",
29802991
"@nteract/transforms": "^4.4.4",
2992+
"@phosphor/widgets": "^1.9.3",
29812993
"@testing-library/react": "^9.4.0",
29822994
"@types/ansi-regex": "^4.0.0",
29832995
"@types/chai": "^4.1.2",
@@ -3064,6 +3076,7 @@
30643076
"expose-loader": "^0.7.5",
30653077
"extract-zip": "^1.6.7",
30663078
"fast-xml-parser": "^3.16.0",
3079+
"file-loader": "^5.1.0",
30673080
"filemanager-webpack-plugin": "^2.0.5",
30683081
"flat": "^4.0.0",
30693082
"gulp": "^4.0.0",
@@ -3080,6 +3093,7 @@
30803093
"husky": "^1.1.2",
30813094
"immutable": "^4.0.0-rc.12",
30823095
"jsdom": "^15.0.0",
3096+
"json-loader": "^0.5.7",
30833097
"less": "^3.9.0",
30843098
"less-loader": "^5.0.0",
30853099
"less-plugin-inline-urls": "^1.2.0",
@@ -3097,6 +3111,10 @@
30973111
"node-has-native-dependencies": "^1.0.2",
30983112
"node-html-parser": "^1.1.13",
30993113
"nyc": "^15.0.0",
3114+
"postcss": "^7.0.27",
3115+
"postcss-cssnext": "^3.1.0",
3116+
"postcss-import": "^12.0.1",
3117+
"postcss-loader": "^3.0.0",
31003118
"prettier": "^1.19.1",
31013119
"range-inclusive": "^1.0.2",
31023120
"raw-loader": "^0.5.1",
@@ -3115,6 +3133,7 @@
31153133
"remove-files-webpack-plugin": "^1.4.0",
31163134
"requirejs": "^2.3.6",
31173135
"rewiremock": "^3.13.0",
3136+
"rimraf": "^3.0.2",
31183137
"sass-loader": "^7.1.0",
31193138
"serialize-javascript": "^2.1.2",
31203139
"shortid": "^2.2.8",

src/client/datascience/interactive-ipynb/nativeEditor.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,9 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
402402
if (this.disposable) {
403403
this.disposable.dispose();
404404
}
405+
if (!this.notebook) {
406+
return;
407+
}
405408
this.disposable = (this.notebook as JupyterNotebookBase).onIOPub(this.handleOnIOPub.bind(this));
406409
if ((this.notebook as JupyterNotebookBase).onIOPub) {
407410
// tslint:disable-next-line: no-console

src/datascience-ui/ipywidgets/callbackManager.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,15 @@ import { Deferred } from '../../client/common/utils/async';
88
import { IPyWidgetMessages } from '../../client/datascience/interactive-common/interactiveWindowTypes';
99

1010
export class ClassicCommShellCallbackManager {
11-
private requestFutureMap = new Map<string, { future: Kernel.IShellFuture; deferred: Deferred<KernelMessage.IShellMessage | undefined> }>();
12-
public registerFuture(requestId: string, future: Kernel.IShellFuture, deferred: Deferred<KernelMessage.IShellMessage | undefined>) {
11+
private requestFutureMap = new Map<
12+
string,
13+
{ future: Kernel.IShellFuture; deferred: Deferred<KernelMessage.IShellMessage | undefined> }
14+
>();
15+
public registerFuture(
16+
requestId: string,
17+
future: Kernel.IShellFuture,
18+
deferred: Deferred<KernelMessage.IShellMessage | undefined>
19+
) {
1320
this.requestFutureMap.set(requestId, { future, deferred });
1421
}
1522
public unregisterFuture(requestId: string) {

src/datascience-ui/ipywidgets/classicComm.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ export class ClassicComm implements Kernel.IComm {
2424
private readonly callbackManager: ClassicCommShellCallbackManager
2525
) {}
2626
// tslint:disable-next-line: no-any
27-
public open(data?: any, metadata?: any, buffers?: (ArrayBuffer | ArrayBufferView)[] | undefined): Kernel.IShellFuture {
27+
public open(
28+
data?: any,
29+
metadata?: any,
30+
buffers?: (ArrayBuffer | ArrayBufferView)[] | undefined
31+
): Kernel.IShellFuture {
2832
// tslint:disable-next-line: no-console
2933
const requestId = uuid();
3034
const commId: string = this.commId;
@@ -64,15 +68,24 @@ export class ClassicComm implements Kernel.IComm {
6468
return future;
6569
}
6670
// tslint:disable-next-line: no-any
67-
public close(_data?: any, _metadata?: any, _buffers?: (ArrayBuffer | ArrayBufferView)[] | undefined): Kernel.IShellFuture {
71+
public close(
72+
_data?: any,
73+
_metadata?: any,
74+
_buffers?: (ArrayBuffer | ArrayBufferView)[] | undefined
75+
): Kernel.IShellFuture {
6876
this.registeredFutures.forEach(item => this.callbackManager.unregisterFuture(item));
6977
throw new Error('VSCPython.IClassicComm.Close method not implemented!');
7078
}
7179
public dispose(): void {
7280
this.registeredFutures.forEach(item => this.callbackManager.unregisterFuture(item));
7381
}
7482
// tslint:disable-next-line: no-any
75-
public send(data: any, metadata?: any, buffers?: (ArrayBuffer | ArrayBufferView)[] | undefined, disposeOnDone?: boolean | undefined): Kernel.IShellFuture {
83+
public send(
84+
data: any,
85+
metadata?: any,
86+
buffers?: (ArrayBuffer | ArrayBufferView)[] | undefined,
87+
disposeOnDone?: boolean | undefined
88+
): Kernel.IShellFuture {
7689
// tslint:disable-next-line: no-console
7790
const requestId = uuid();
7891
const commId: string = this.commId;

src/datascience-ui/ipywidgets/container.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,34 @@ import { IStore } from '../interactive-common/redux/store';
1111
import { WidgetManager } from './manager';
1212

1313
// tslint:disable-next-line: no-any
14-
type Props = { messages: Observable<{type: string; payload?: any}>; sendMessage<M extends IInteractiveWindowMapping, T extends keyof M>(type: T, payload?: M[T]): void };
14+
type Props = {
15+
messages: Observable<{ type: string; payload?: any }>;
16+
sendMessage<M extends IInteractiveWindowMapping, T extends keyof M>(type: T, payload?: M[T]): void;
17+
};
1518

1619
function mapStateToProps(state: IStore): Props {
17-
return { messages: state.widgetMessagses, sendMessage: state.sendMessage } ;
20+
return { messages: state.widgetMessagses, sendMessage: state.sendMessage };
1821
}
1922
// Default dispatcher (not required, but required for strictness).
2023
function mapDispatchToProps(dispatch: Function) {
21-
return {dispatch};
24+
return { dispatch };
2225
}
2326

2427
class Container extends React.Component<Props> {
2528
private readonly widgetManager: WidgetManager;
2629

2730
constructor(props: Props) {
2831
super(props);
29-
this.widgetManager = new WidgetManager(document.getElementById('rootWidget')!, props.messages, props.sendMessage);
32+
this.widgetManager = new WidgetManager(
33+
document.getElementById('rootWidget')!,
34+
props.messages,
35+
props.sendMessage
36+
);
3037
}
3138
public render() {
3239
return null;
3340
}
34-
public componentWillUnmount(){
41+
public componentWillUnmount() {
3542
this.widgetManager.dispose();
3643
}
3744
}

src/datascience-ui/ipywidgets/kernel.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ export class ProxyKernel implements Partial<Kernel.IKernel> {
5050
}
5151
}
5252
public initialize(): void {
53-
this.commRegistrationMessagesToSend.forEach(targetName => this.messageSender.sendMessage(IPyWidgetMessages.IPyWidgets_registerCommTarget, targetName));
53+
this.commRegistrationMessagesToSend.forEach(targetName =>
54+
this.messageSender.sendMessage(IPyWidgetMessages.IPyWidgets_registerCommTarget, targetName)
55+
);
5456
this.commRegistrationMessagesToSend = [];
5557
}
5658
// tslint:disable-next-line: no-any

src/datascience-ui/ipywidgets/manager.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import { IDisposable } from '../../client/common/types';
1111
import { createDeferred, Deferred } from '../../client/common/utils/async';
1212
import { noop } from '../../client/common/utils/misc';
1313
import { deserializeDataViews } from '../../client/common/utils/serializers';
14-
import { IInteractiveWindowMapping, IPyWidgetMessages } from '../../client/datascience/interactive-common/interactiveWindowTypes';
14+
import {
15+
IInteractiveWindowMapping,
16+
IPyWidgetMessages
17+
} from '../../client/datascience/interactive-common/interactiveWindowTypes';
1518
import { ProxyKernel } from './kernel';
1619
import { IHtmlWidgetManager, IHtmlWidgetManagerCtor, IIPyWidgetManager, IMessageSender } from './types';
1720

@@ -41,7 +44,10 @@ export class WidgetManager implements IIPyWidgetManager, IMessageSender {
4144
// tslint:disable-next-line: no-any
4245
private readonly messages: Observable<{ type: string; payload?: any }>,
4346
// tslint:disable-next-line: no-any
44-
private readonly dispatcher: <M extends IInteractiveWindowMapping, T extends keyof M>(type: T, payload?: M[T]) => void
47+
private readonly dispatcher: <M extends IInteractiveWindowMapping, T extends keyof M>(
48+
type: T,
49+
payload?: M[T]
50+
) => void
4551
) {
4652
this.proxyKernel = new ProxyKernel(this);
4753
// tslint:disable-next-line: no-any
@@ -71,7 +77,11 @@ export class WidgetManager implements IIPyWidgetManager, IMessageSender {
7177
// General IOPub message
7278
const displayMsg = payload as KernelMessage.IDisplayDataMsg;
7379

74-
if (displayMsg.content && displayMsg.content.data && displayMsg.content.data['application/vnd.jupyter.widget-view+json']) {
80+
if (
81+
displayMsg.content &&
82+
displayMsg.content.data &&
83+
displayMsg.content.data['application/vnd.jupyter.widget-view+json']
84+
) {
7585
// tslint:disable-next-line: no-any
7686
const data = displayMsg.content.data['application/vnd.jupyter.widget-view+json'] as any;
7787
const modelId = data.model_id;
@@ -96,9 +106,14 @@ export class WidgetManager implements IIPyWidgetManager, IMessageSender {
96106
* @returns {Promise<{ dispose: Function }>}
97107
* @memberof WidgetManager
98108
*/
99-
public async renderWidget(data: nbformat.IMimeBundle & { model_id: string; version_major: number }, ele: HTMLElement): Promise<IDisposable> {
109+
public async renderWidget(
110+
data: nbformat.IMimeBundle & { model_id: string; version_major: number },
111+
ele: HTMLElement
112+
): Promise<IDisposable> {
100113
if (!data) {
101-
throw new Error('application/vnd.jupyter.widget-view+json not in msg.content.data, as msg.content.data is \'undefined\'.');
114+
throw new Error(
115+
"application/vnd.jupyter.widget-view+json not in msg.content.data, as msg.content.data is 'undefined'."
116+
);
102117
}
103118

104119
if (!data || data.version_major !== 2) {

src/datascience-ui/native-editor/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const ConnectedNativeEditor = getConnectedNativeEditor();
3737
// tslint:disable:no-typeof-undefined
3838
ReactDOM.render(
3939
<Provider store={store}>
40-
<ConnectedNativeEditor/>
40+
<ConnectedNativeEditor />
4141
<WidgetManagerComponent />
4242
</Provider>,
4343
document.getElementById('root') as HTMLElement

src/ipywidgets/.prettierrc.js

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/ipywidgets/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
* We have built a custom solution based on `web3` sample to host ipywidgets outside of `Jupyter Notebook`.
44

5+
# Warning
6+
* Most of the code has been copied as is from `https://github.com/jupyter-widgets/ipywidgets/blob/master/examples/web3` & `https://github.com/jupyter-widgets/ipywidgets/blob/master/packages/html-manager/webpack.config.js`.
7+
* Please try to minimize changes to original code to facilitate easier updatess.
8+
59
# Solution for IPywidgets
610

711
* IPywidgets traditionally use [requirejs](https://requirejs.org).
@@ -22,3 +26,6 @@
2226
* Solution is to include everything thats in `embed-amd.js` into our bundle.
2327
* The `embed-amd.js` includes source from files other than the widget controls, those include `libembed-amd.js` and `embed-amd-render.js`.
2428
* The source for this can be found in [scripts/concat-amd-build.js](https://github.com/jupyter-widgets/ipywidgets/blob/857bee9c15ca25bd6b47b7777e8fcd07407214cf/packages/html-manager/scripts/concat-amd-build.js#L15)
29+
* We need types for `requirejs`, but installing this into `node_modules`, for extension causes conflicts as we use `require` in standard node (extension and UI).
30+
* Solution is to just copy the `@types/requirejs/index.d.ts` into the `types` folder.
31+

0 commit comments

Comments
 (0)