2
2
// Distributed under the terms of the Modified BSD License.
3
3
4
4
import * as services from '@jupyterlab/services' ;
5
+ import * as widgets from '@jupyter-widgets/base' ;
5
6
6
7
import { JSONObject , PartialJSONObject } from '@lumino/coreutils' ;
7
8
@@ -128,10 +129,12 @@ export abstract class ManagerBase implements IWidgetManager {
128
129
const id = uuid ( ) ;
129
130
const viewPromise = ( model . state_change = model . state_change . then (
130
131
async ( ) => {
132
+ const _view_name = model . get ( '_view_name' ) ;
133
+ const _view_module = model . get ( '_view_module' ) ;
131
134
try {
132
- const ViewType = ( await this . loadClass (
133
- model . get ( ' _view_name' ) ,
134
- model . get ( ' _view_module' ) ,
135
+ const ViewType = ( await this . loadViewClass (
136
+ _view_name ,
137
+ _view_module ,
135
138
model . get ( '_view_module_version' )
136
139
) ) as typeof WidgetView ;
137
140
const view = new ViewType ( {
@@ -153,7 +156,16 @@ export abstract class ManagerBase implements IWidgetManager {
153
156
console . error (
154
157
`Could not create a view for model id ${ model . model_id } `
155
158
) ;
156
- throw e ;
159
+ const msg = `Failed to create view for '${ _view_name } ' from module '${ _view_module } ' with model '${ model . name } ' from module '${ model . module } '` ;
160
+ const ModelCls = widgets . createErrorWidgetModel ( e , msg ) ;
161
+ const errorModel = new ModelCls ( ) ;
162
+ const view = new widgets . ErrorWidgetView ( {
163
+ model : errorModel ,
164
+ options : this . setViewOptions ( options ) ,
165
+ } ) ;
166
+ await view . render ( ) ;
167
+
168
+ return view ;
157
169
}
158
170
}
159
171
) ) ;
@@ -330,35 +342,53 @@ export abstract class ManagerBase implements IWidgetManager {
330
342
serialized_state : any = { }
331
343
) : Promise < WidgetModel > {
332
344
const model_id = options . model_id ;
333
- const model_promise = this . loadClass (
345
+ const model_promise = this . loadModelClass (
334
346
options . model_name ,
335
347
options . model_module ,
336
348
options . model_module_version
337
- ) as Promise < typeof WidgetModel > ;
349
+ ) ;
338
350
let ModelType : typeof WidgetModel ;
351
+
352
+ const makeErrorModel = ( error : any , msg : string ) => {
353
+ const Cls = widgets . createErrorWidgetModel ( error , msg ) ;
354
+ const widget_model = new Cls ( ) ;
355
+ return widget_model ;
356
+ } ;
357
+
339
358
try {
340
359
ModelType = await model_promise ;
341
360
} catch ( error ) {
342
- console . error ( 'Could not instantiate widget' ) ;
343
- throw error ;
361
+ const msg = 'Could not instantiate widget' ;
362
+ console . error ( msg ) ;
363
+ return makeErrorModel ( error , msg ) ;
344
364
}
345
365
346
366
if ( ! ModelType ) {
347
- throw new Error (
367
+ const msg = 'Could not instantiate widget' ;
368
+ console . error ( msg ) ;
369
+ const error = new Error (
348
370
`Cannot find model module ${ options . model_module } @${ options . model_module_version } , ${ options . model_name } `
349
371
) ;
372
+ return makeErrorModel ( error , msg ) ;
350
373
}
374
+ let widget_model : WidgetModel ;
375
+ try {
376
+ const attributes = await ModelType . _deserialize_state (
377
+ serialized_state ,
378
+ this
379
+ ) ;
380
+ const modelOptions : IBackboneModelOptions = {
381
+ widget_manager : this ,
382
+ model_id : model_id ,
383
+ comm : options . comm ,
384
+ } ;
351
385
352
- const attributes = await ModelType . _deserialize_state (
353
- serialized_state ,
354
- this
355
- ) ;
356
- const modelOptions : IBackboneModelOptions = {
357
- widget_manager : this ,
358
- model_id : model_id ,
359
- comm : options . comm ,
360
- } ;
361
- const widget_model = new ModelType ( attributes , modelOptions ) ;
386
+ widget_model = new ModelType ( attributes , modelOptions ) ;
387
+ } catch ( error ) {
388
+ console . error ( error ) ;
389
+ const msg = `Model class '${ options . model_name } ' from module '${ options . model_module } ' is loaded but can not be instantiated` ;
390
+ widget_model = makeErrorModel ( error , msg ) ;
391
+ }
362
392
widget_model . name = options . model_name ;
363
393
widget_model . module = options . model_module ;
364
394
return widget_model ;
@@ -520,6 +550,46 @@ export abstract class ManagerBase implements IWidgetManager {
520
550
moduleVersion : string
521
551
) : Promise < typeof WidgetModel | typeof WidgetView > ;
522
552
553
+ protected async loadModelClass (
554
+ className : string ,
555
+ moduleName : string ,
556
+ moduleVersion : string
557
+ ) : Promise < typeof WidgetModel > {
558
+ try {
559
+ const promise : Promise < typeof WidgetModel > = this . loadClass (
560
+ className ,
561
+ moduleName ,
562
+ moduleVersion
563
+ ) as Promise < typeof WidgetModel > ;
564
+ await promise ;
565
+ return promise ;
566
+ } catch ( error ) {
567
+ console . error ( error ) ;
568
+ const msg = `Failed to load model class '${ className } ' from module '${ moduleName } '` ;
569
+ return widgets . createErrorWidgetModel ( error , msg ) ;
570
+ }
571
+ }
572
+
573
+ protected async loadViewClass (
574
+ className : string ,
575
+ moduleName : string ,
576
+ moduleVersion : string
577
+ ) : Promise < typeof WidgetView > {
578
+ try {
579
+ const promise : Promise < typeof WidgetView > = this . loadClass (
580
+ className ,
581
+ moduleName ,
582
+ moduleVersion
583
+ ) as Promise < typeof WidgetView > ;
584
+ await promise ;
585
+ return promise ;
586
+ } catch ( error ) {
587
+ console . error ( error ) ;
588
+ const msg = `Failed to load view class '${ className } ' from module '${ moduleName } '` ;
589
+ return widgets . createErrorWidgetView ( error , msg ) ;
590
+ }
591
+ }
592
+
523
593
/**
524
594
* Create a comm which can be used for communication for a widget.
525
595
*
0 commit comments