Skip to content

Commit 30d4de0

Browse files
authored
Merge pull request #1302 from jasongrout/embeddedoutput2
Serialize/deserialize binary values to the serialization format
2 parents f452016 + 814fa2a commit 30d4de0

File tree

14 files changed

+326
-162
lines changed

14 files changed

+326
-162
lines changed

docs/source/embedding.md

Lines changed: 2 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -30,92 +30,15 @@ This HTML snippet is composed of multiple `<script>` tags:
3030
- The second script tag contains the state of all the widget models currently
3131
in use. It has the mime type `application/vnd.jupyter.widget-state+json`.
3232

33-
The JSON schema for the content of that script tag is:
34-
35-
```json
36-
{
37-
"$schema": "http://json-schema.org/draft-04/schema#",
38-
"description": "Jupyter Interactive Widget State JSON schema.",
39-
"type": "object",
40-
"properties" : {
41-
"version_major" : {
42-
"description": "Format version (major)",
43-
"type": "number",
44-
"minimum": 1,
45-
"maximum": 1
46-
},
47-
"version_minor" : {
48-
"description": "Format version (minor)",
49-
"type": "number"
50-
},
51-
"state": {
52-
"description": "Model State for All Widget Models",
53-
"type": "object",
54-
"additionalProperties": true,
55-
"additionalProperties" : {
56-
"type": "object",
57-
"properties": {
58-
"model_name": {
59-
"description" : "Name of the JavaScript class holding the model implementation",
60-
"type": "string"
61-
},
62-
"model_module": {
63-
"description" : "Name of the JavaScript module holding the model implementation",
64-
"type": "string"
65-
},
66-
"model_module_version": {
67-
"description" : "Semver range for the JavaScript module holding the model implementation",
68-
"type": "string"
69-
},
70-
"state": {
71-
"description" : "Serialized state of the model",
72-
"type": "object",
73-
"additional_properties": true
74-
}
75-
},
76-
"required": [ "model_name", "model_module", "state" ],
77-
"additionalProperties": false
78-
}
79-
}
80-
},
81-
"required": [ "version_major", "version_minor", "state" ],
82-
"additionalProperties": false
83-
}
84-
```
33+
The JSON schema for the content of that script tag is found in the jupyter-widgets-schema npm package.
8534

8635
- The following script tags correspond to the views which you want to display
8736
in the web page. They have the mime type `application/vnd.jupyter.widget-view+json`.
8837

8938
The *Embed Widgets* action currently creates such a tag for each view
9039
displayed in the notebook at this time.
9140

92-
The JSON schema for the content of that script tag is:
93-
94-
```json
95-
{
96-
"$schema": "http://json-schema.org/draft-04/schema#",
97-
"description": "Jupyter Interactive Widget View JSON schema.",
98-
"type": "object",
99-
"properties" : {
100-
"version_major" : {
101-
"description": "Format version (major)",
102-
"type": "number",
103-
"minimum": 1,
104-
"maximum": 1
105-
},
106-
"version_minor" : {
107-
"description": "Format version (minor)",
108-
"type": "number"
109-
},
110-
"model_id": {
111-
"description": "Unique identifier of the widget model to be displayed",
112-
"type": "string"
113-
},
114-
"required": [ "model_id" ]
115-
},
116-
"additionalProperties": false
117-
}
118-
```
41+
The JSON schema for the content of that script tag is found in the jupyter-widgets-schema npm package.
11942

12043
If you want to lay out these script tags in a custom fashion or only keep
12144
some of them, you can change their location in the DOM when including the

ipywidgets/state.schema.json

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@
66
"version_major" : {
77
"description": "Format version (major)",
88
"type": "number",
9-
"minimum": 1,
10-
"maximum": 1
9+
"minimum": 2,
10+
"maximum": 2
1111
},
1212
"version_minor" : {
1313
"description": "Format version (minor)",
14-
"type": "number"
14+
"type": "number",
15+
"minimum": 0,
16+
"maximum": 0
1517
},
1618
"state": {
17-
"description": "Model State for All Widget Models",
19+
"description": "Model State for All Widget Models - keys are model ids, values are model state",
1820
"type": "object",
19-
"additionalProperties": true,
2021
"additionalProperties" : {
2122
"type": "object",
2223
"properties": {
@@ -34,15 +35,44 @@
3435
},
3536
"state": {
3637
"description" : "Serialized state of the model",
37-
"type": "object",
38-
"additional_properties": true
38+
"type": "object"
39+
},
40+
"buffers": {
41+
"description": "Binary buffers in the state",
42+
"type": "array",
43+
"items": {
44+
"type": "object",
45+
"properties": {
46+
"path": {
47+
"description": "A path for a binary buffer value.",
48+
"type": "array",
49+
"items": {
50+
"description": "An object key or array index",
51+
"type": ["string", "number"]
52+
}
53+
},
54+
"data": {
55+
"description" : "A binary buffer encoded as specified in the 'encoding' property",
56+
"type": "string"
57+
},
58+
"encoding": {
59+
"description": "The encoding of the buffer data",
60+
"type": "string",
61+
"oneOf": [
62+
{"enum": ["hex"], "description": "Base 16 encoding, as specified in RFC 4648, section 8 (https://tools.ietf.org/html/rfc4648#section-8)"},
63+
{"enum": ["base64"], "description": "Base 64 encoding, as specified in RFC 4648, section 4 (https://tools.ietf.org/html/rfc4648#section-4)"}
64+
65+
]
66+
}
67+
68+
},
69+
"required": ["path", "data", "encoding"]
70+
}
3971
}
4072
},
41-
"required": [ "model_name", "model_module", "state" ],
42-
"additionalProperties": false
73+
"required": [ "model_name", "model_module", "state" ]
4374
}
4475
}
4576
},
46-
"required": [ "version_major", "version_minor", "state" ],
47-
"additionalProperties": false
77+
"required": [ "version_major", "version_minor", "state" ]
4878
}

ipywidgets/widgets/widget.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
from ipython_genutils.py3compat import string_types, PY3
1717
from IPython.display import display
1818

19+
from base64 import standard_b64decode, standard_b64encode
20+
1921
from .._version import __protocol_version__
2022

2123

@@ -279,17 +281,26 @@ def handle_comm_opened(comm, msg):
279281

280282
@staticmethod
281283
def get_manager_state(drop_defaults=False):
282-
return dict(version_major=1, version_minor=0, state={
283-
k: {
284-
'model_name': Widget.widgets[k]._model_name,
285-
'model_module': Widget.widgets[k]._model_module,
286-
'model_module_version': Widget.widgets[k]._model_module_version,
287-
'state': Widget.widgets[k].get_state(drop_defaults=drop_defaults)
288-
} for k in Widget.widgets
289-
})
284+
manager_state = {}
285+
for model_id, model in Widget.widgets.items():
286+
state = {
287+
'model_name': model._model_name,
288+
'model_module': model.model_module,
289+
'model_module_version': model._model_module_version
290+
}
291+
model_state, buffer_paths, buffers = _remove_buffers(model.get_state(drop_defaults=drop_defaults))
292+
state['state'] = model_state
293+
if len(buffers) > 0:
294+
state['buffers'] = {
295+
'buffers': [{'path': p, 'data': standard_b64encode(d).decode('ascii')}
296+
for p, d in zip(buffer_paths, buffers)],
297+
'encoding': 'base64'
298+
}
299+
manager_state[model_id] = state
300+
return {'version_major': 2, 'version_minor': 0, 'state': manager_state}
290301

291302
def get_view_spec(self):
292-
return dict(version_major=1, version_minor=0, model_id=self._model_id)
303+
return dict(version_major=2, version_minor=0, model_id=self._model_id)
293304

294305
#-------------------------------------------------------------------------
295306
# Traits
@@ -619,6 +630,8 @@ def _ipython_display_(self, **kwargs):
619630
data = {
620631
'text/plain': "A Jupyter Widget",
621632
'application/vnd.jupyter.widget-view+json': {
633+
'version_major': '2',
634+
'version_minor': '0',
622635
'model_id': self._model_id
623636
}
624637
}

jupyter-js-widgets/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,12 @@
9191
"@types/semver": "^5.3.30",
9292
"ajv": "^4.9.0",
9393
"backbone": "1.2.0",
94+
"base64-js": "1.2.0",
9495
"d3-format": "^0.5.1",
9596
"font-awesome": "^4.5.0",
9697
"jquery": "^3.1.1",
9798
"jquery-ui": "^1.12.1",
98-
"jupyter-widgets-schema": "^0.1.1",
99+
"jupyter-widgets-schema": "^0.3.0-beta.2",
99100
"lolex": "^1.4.0",
100101
"scriptjs": "^2.5.8",
101102
"semver": "^5.1.0",

jupyter-js-widgets/src-embed/embed-webpack.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ require('../css/widgets.css');
1919

2020
// Load json schema validator
2121
var Ajv = require('ajv');
22-
var widget_state_schema = require('jupyter-widgets-schema').v1.state;
23-
var widget_view_schema = require('jupyter-widgets-schema').v1.view;
22+
var widget_state_schema = require('jupyter-widgets-schema').v2.state;
23+
var widget_view_schema = require('jupyter-widgets-schema').v2.view;
2424

2525
// Magic global widget rendering function:
2626
import * as widgets from '../../jupyter-js-widgets/lib/index';
@@ -90,7 +90,7 @@ function renderManager(element, tag) {
9090
console.log(model_validate.errors);
9191
}
9292
var manager = new embed.EmbedManager();
93-
manager.set_state(widgetStateObject.state, {}).then(function(models) {
93+
manager.set_state(widgetStateObject, {}).then(function(models) {
9494
var tags = element.querySelectorAll('script[type="application/vnd.jupyter.widget-view+json"]');
9595
for (var i=0; i!=tags.length; ++i) {
9696
// TODO: validate view schema

0 commit comments

Comments
 (0)