1 |
|
2 |
|
3 |
|
4 |
|
5 | import * as nbformat from '@jupyterlab/nbformat';
|
6 | import { ObservableJSON } from '@jupyterlab/observables';
|
7 | import { JSONExt } from '@lumino/coreutils';
|
8 | import { Signal } from '@lumino/signaling';
|
9 |
|
10 |
|
11 |
|
12 | export class OutputModel {
|
13 | |
14 |
|
15 |
|
16 | constructor(options) {
|
17 | this._changed = new Signal(this);
|
18 | this._raw = {};
|
19 | const { data, metadata, trusted } = Private.getBundleOptions(options);
|
20 | this._data = new ObservableJSON({ values: data });
|
21 | this._rawData = data;
|
22 | this._metadata = new ObservableJSON({ values: metadata });
|
23 | this._rawMetadata = metadata;
|
24 | this.trusted = trusted;
|
25 |
|
26 | const value = options.value;
|
27 | for (const key in value) {
|
28 |
|
29 | switch (key) {
|
30 | case 'data':
|
31 | case 'metadata':
|
32 | break;
|
33 | default:
|
34 | this._raw[key] = Private.extract(value, key);
|
35 | }
|
36 | }
|
37 | this.type = value.output_type;
|
38 | if (nbformat.isExecuteResult(value)) {
|
39 | this.executionCount = value.execution_count;
|
40 | }
|
41 | else {
|
42 | this.executionCount = null;
|
43 | }
|
44 | }
|
45 | |
46 |
|
47 |
|
48 | get changed() {
|
49 | return this._changed;
|
50 | }
|
51 | |
52 |
|
53 |
|
54 | dispose() {
|
55 | this._data.dispose();
|
56 | this._metadata.dispose();
|
57 | Signal.clearData(this);
|
58 | }
|
59 | |
60 |
|
61 |
|
62 | get data() {
|
63 | return this._rawData;
|
64 | }
|
65 | |
66 |
|
67 |
|
68 | get metadata() {
|
69 | return this._rawMetadata;
|
70 | }
|
71 | |
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | setData(options) {
|
79 | if (options.data) {
|
80 | this._updateObservable(this._data, options.data);
|
81 | this._rawData = options.data;
|
82 | }
|
83 | if (options.metadata) {
|
84 | this._updateObservable(this._metadata, options.metadata);
|
85 | this._rawMetadata = options.metadata;
|
86 | }
|
87 | this._changed.emit(void 0);
|
88 | }
|
89 | |
90 |
|
91 |
|
92 | toJSON() {
|
93 | const output = {};
|
94 | for (const key in this._raw) {
|
95 | output[key] = Private.extract(this._raw, key);
|
96 | }
|
97 | switch (this.type) {
|
98 | case 'display_data':
|
99 | case 'execute_result':
|
100 | case 'update_display_data':
|
101 | output['data'] = this.data;
|
102 | output['metadata'] = this.metadata;
|
103 | break;
|
104 | default:
|
105 | break;
|
106 | }
|
107 |
|
108 | delete output['transient'];
|
109 | return output;
|
110 | }
|
111 | |
112 |
|
113 |
|
114 | _updateObservable(observable, data) {
|
115 | const oldKeys = observable.keys();
|
116 | const newKeys = Object.keys(data);
|
117 |
|
118 | for (const key of oldKeys) {
|
119 | if (newKeys.indexOf(key) === -1) {
|
120 | observable.delete(key);
|
121 | }
|
122 | }
|
123 |
|
124 | for (const key of newKeys) {
|
125 | const oldValue = observable.get(key);
|
126 | const newValue = data[key];
|
127 | if (oldValue !== newValue) {
|
128 | observable.set(key, newValue);
|
129 | }
|
130 | }
|
131 | }
|
132 | }
|
133 |
|
134 |
|
135 |
|
136 | (function (OutputModel) {
|
137 | |
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 | function getData(output) {
|
145 | return Private.getData(output);
|
146 | }
|
147 | OutputModel.getData = getData;
|
148 | |
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 | function getMetadata(output) {
|
156 | return Private.getMetadata(output);
|
157 | }
|
158 | OutputModel.getMetadata = getMetadata;
|
159 | })(OutputModel || (OutputModel = {}));
|
160 |
|
161 |
|
162 |
|
163 | var Private;
|
164 | (function (Private) {
|
165 | |
166 |
|
167 |
|
168 | function getData(output) {
|
169 | let bundle = {};
|
170 | if (nbformat.isExecuteResult(output) ||
|
171 | nbformat.isDisplayData(output) ||
|
172 | nbformat.isDisplayUpdate(output)) {
|
173 | bundle = output.data;
|
174 | }
|
175 | else if (nbformat.isStream(output)) {
|
176 | if (output.name === 'stderr') {
|
177 | bundle['application/vnd.jupyter.stderr'] = output.text;
|
178 | }
|
179 | else {
|
180 | bundle['application/vnd.jupyter.stdout'] = output.text;
|
181 | }
|
182 | }
|
183 | else if (nbformat.isError(output)) {
|
184 | bundle['application/vnd.jupyter.error'] = output;
|
185 | const traceback = output.traceback.join('\n');
|
186 | bundle['application/vnd.jupyter.stderr'] =
|
187 | traceback || `${output.ename}: ${output.evalue}`;
|
188 | }
|
189 | return convertBundle(bundle);
|
190 | }
|
191 | Private.getData = getData;
|
192 | |
193 |
|
194 |
|
195 | function getMetadata(output) {
|
196 | const value = Object.create(null);
|
197 | if (nbformat.isExecuteResult(output) || nbformat.isDisplayData(output)) {
|
198 | for (const key in output.metadata) {
|
199 | value[key] = extract(output.metadata, key);
|
200 | }
|
201 | }
|
202 | return value;
|
203 | }
|
204 | Private.getMetadata = getMetadata;
|
205 | |
206 |
|
207 |
|
208 | function getBundleOptions(options) {
|
209 | const data = getData(options.value);
|
210 | const metadata = getMetadata(options.value);
|
211 | const trusted = !!options.trusted;
|
212 | return { data, metadata, trusted };
|
213 | }
|
214 | Private.getBundleOptions = getBundleOptions;
|
215 | |
216 |
|
217 |
|
218 | function extract(value, key) {
|
219 | const item = value[key];
|
220 | if (item === undefined || JSONExt.isPrimitive(item)) {
|
221 | return item;
|
222 | }
|
223 | return JSON.parse(JSON.stringify(item));
|
224 | }
|
225 | Private.extract = extract;
|
226 | |
227 |
|
228 |
|
229 | function convertBundle(bundle) {
|
230 | const map = Object.create(null);
|
231 | for (const mimeType in bundle) {
|
232 | map[mimeType] = extract(bundle, mimeType);
|
233 | }
|
234 | return map;
|
235 | }
|
236 | })(Private || (Private = {}));
|
237 |
|
\ | No newline at end of file |