@@ -108,8 +108,13 @@ def __init__(
108
108
components_cache_max_age = None ,
109
109
show_undo_redo = False ,
110
110
plugins = None ,
111
+ defer_app = False ,
111
112
** kwargs ):
112
113
114
+ # Store some flask-related parameters for use in init_app()
115
+ self .compress = compress
116
+ self .name = name
117
+
113
118
# pylint-disable: too-many-instance-attributes
114
119
if 'csrf_protect' in kwargs :
115
120
warnings .warn ('''
@@ -154,22 +159,6 @@ def __init__(
154
159
'show_undo_redo' : show_undo_redo
155
160
})
156
161
157
- assets_blueprint_name = '{}{}' .format (
158
- self .config .routes_pathname_prefix .replace ('/' , '_' ),
159
- 'dash_assets'
160
- )
161
-
162
- self .server .register_blueprint (
163
- flask .Blueprint (
164
- assets_blueprint_name , name ,
165
- static_folder = self ._assets_folder ,
166
- static_url_path = '{}{}' .format (
167
- self .config .routes_pathname_prefix ,
168
- assets_url_path .lstrip ('/' )
169
- )
170
- )
171
- )
172
-
173
162
# list of dependencies
174
163
self .callback_map = {}
175
164
@@ -181,15 +170,6 @@ def __init__(
181
170
# default renderer string
182
171
self .renderer = 'var renderer = new DashRenderer();'
183
172
184
- if compress :
185
- # gzip
186
- Compress (self .server )
187
-
188
- @self .server .errorhandler (exceptions .PreventUpdate )
189
- def _handle_error (_ ):
190
- """Handle a halted callback and return an empty 204 response"""
191
- return '' , 204
192
-
193
173
# static files from the packages
194
174
self .css = Css ()
195
175
self .scripts = Scripts ()
@@ -236,8 +216,6 @@ def _handle_error(_):
236
216
'{}_favicon.ico' .format (prefix ),
237
217
self ._serve_default_favicon )
238
218
239
- self .server .before_first_request (self ._setup_server )
240
-
241
219
self ._layout = None
242
220
self ._cached_layout = None
243
221
self ._dev_tools = _AttributeDict ({
@@ -250,10 +228,6 @@ def _handle_error(_):
250
228
'props_check' : False ,
251
229
})
252
230
253
- # add a handler for components suites errors to return 404
254
- self .server .errorhandler (exceptions .InvalidResourceError )(
255
- self ._invalid_resources_handler )
256
-
257
231
self ._assets_files = []
258
232
259
233
# hot reload
@@ -270,6 +244,49 @@ def _handle_error(_):
270
244
for plugin in plugins :
271
245
plugin .plug (self )
272
246
247
+ if not defer_app :
248
+ self .init_app ()
249
+
250
+ def init_app (self , app = None ):
251
+ """
252
+ Initialize the parts of Dash that require a flask app
253
+ """
254
+
255
+ if app is not None :
256
+ self .server = app
257
+
258
+ assets_blueprint_name = '{}{}' .format (
259
+ self .config .routes_pathname_prefix .replace ('/' , '_' ),
260
+ 'dash_assets'
261
+ )
262
+
263
+ self .server .register_blueprint (
264
+ flask .Blueprint (
265
+ assets_blueprint_name ,
266
+ self .name ,
267
+ static_folder = self ._assets_folder ,
268
+ static_url_path = '{}{}' .format (
269
+ self .config .routes_pathname_prefix ,
270
+ self ._assets_url_path .lstrip ('/' )
271
+ )
272
+ )
273
+ )
274
+
275
+ if self .compress :
276
+ # gzip
277
+ Compress (self .server )
278
+
279
+ @self .server .errorhandler (exceptions .PreventUpdate )
280
+ def _handle_error (_ ):
281
+ """Handle a halted callback and return an empty 204 response"""
282
+ return '' , 204
283
+
284
+ self .server .before_first_request (self ._setup_server )
285
+
286
+ # add a handler for components suites errors to return 404
287
+ self .server .errorhandler (exceptions .InvalidResourceError )(
288
+ self ._invalid_resources_handler )
289
+
273
290
def _add_url (self , name , view_func , methods = ('GET' ,)):
274
291
self .server .add_url_rule (
275
292
name ,
@@ -404,7 +421,7 @@ def _relative_url_path(relative_package_path='', namespace=''):
404
421
paths = [paths ] if isinstance (paths , str ) else paths
405
422
406
423
for rel_path in paths :
407
- self .registered_paths [resource ['namespace' ]]\
424
+ self .registered_paths [resource ['namespace' ]] \
408
425
.add (rel_path )
409
426
410
427
if not is_dynamic_resource :
@@ -432,7 +449,7 @@ def _relative_url_path(relative_package_path='', namespace=''):
432
449
433
450
def _generate_css_dist_html (self ):
434
451
links = self ._external_stylesheets + \
435
- self ._collect_and_register_resources (self .css .get_all_css ())
452
+ self ._collect_and_register_resources (self .css .get_all_css ())
436
453
437
454
return '\n ' .join ([
438
455
_format_tag ('link' , link , opened = True )
@@ -454,12 +471,12 @@ def _generate_scripts_html(self):
454
471
dash_renderer ._js_dist_dependencies ,
455
472
dev_bundles = self ._dev_tools .serve_dev_bundles
456
473
)) + self ._external_scripts + self ._collect_and_register_resources (
457
- self .scripts .get_all_scripts (
458
- dev_bundles = self ._dev_tools .serve_dev_bundles ) +
459
- self .scripts ._resources ._filter_resources (
460
- dash_renderer ._js_dist ,
461
- dev_bundles = self ._dev_tools .serve_dev_bundles
462
- ))
474
+ self .scripts .get_all_scripts (
475
+ dev_bundles = self ._dev_tools .serve_dev_bundles ) +
476
+ self .scripts ._resources ._filter_resources (
477
+ dash_renderer ._js_dist ,
478
+ dev_bundles = self ._dev_tools .serve_dev_bundles
479
+ ))
463
480
464
481
return '\n ' .join ([
465
482
_format_tag ('script' , src )
@@ -509,14 +526,14 @@ def serve_component_suites(self, package_name, path_in_package_dist):
509
526
'Error loading dependency.\n '
510
527
'"{}" is not a registered library.\n '
511
528
'Registered libraries are: {}'
512
- .format (package_name , list (self .registered_paths .keys ())))
529
+ .format (package_name , list (self .registered_paths .keys ())))
513
530
514
531
if path_in_package_dist not in self .registered_paths [package_name ]:
515
532
raise exceptions .DependencyException (
516
533
'"{}" is registered but the path requested is not valid.\n '
517
534
'The path requested: "{}"\n '
518
535
'List of registered paths: {}'
519
- .format (
536
+ .format (
520
537
package_name ,
521
538
path_in_package_dist ,
522
539
self .registered_paths
@@ -775,7 +792,7 @@ def _validate_callback(self, output, inputs, state):
775
792
arg .component_property ,
776
793
arg .component_id ,
777
794
component .available_properties ).replace (
778
- ' ' , '' ))
795
+ ' ' , '' ))
779
796
780
797
if hasattr (arg , 'component_event' ):
781
798
raise exceptions .NonExistentEventException ('''
@@ -871,19 +888,19 @@ def _raise_invalid(bad_val, outer_val, bad_type, path, index=None,
871
888
or is in the top level of the returned list,'''
872
889
),
873
890
location = (
874
- "\n " +
875
- ("[{:d}] {:s} {:s}" .format (index , outer_type , outer_id )
876
- if index is not None
877
- else ('[*] ' + outer_type + ' ' + outer_id ))
878
- + "\n " + path + "\n "
891
+ "\n " +
892
+ ("[{:d}] {:s} {:s}" .format (index , outer_type , outer_id )
893
+ if index is not None
894
+ else ('[*] ' + outer_type + ' ' + outer_id ))
895
+ + "\n " + path + "\n "
879
896
) if not toplevel else '' ,
880
897
bad_val = bad_val ).replace (' ' , '' ))
881
898
882
899
def _value_is_valid (val ):
883
900
return (
884
901
# pylint: disable=unused-variable
885
- any ([isinstance (val , x ) for x in valid ]) or
886
- type (val ).__name__ == 'unicode'
902
+ any ([isinstance (val , x ) for x in valid ]) or
903
+ type (val ).__name__ == 'unicode'
887
904
)
888
905
889
906
def _validate_value (val , index = None ):
@@ -1140,17 +1157,17 @@ def dispatch(self):
1140
1157
1141
1158
for component_registration in self .callback_map [output ]['inputs' ]:
1142
1159
args .append ([
1143
- c .get ('value' , None ) for c in inputs if
1144
- c ['property' ] == component_registration ['property' ] and
1145
- c ['id' ] == component_registration ['id' ]
1146
- ][0 ])
1160
+ c .get ('value' , None ) for c in inputs if
1161
+ c ['property' ] == component_registration ['property' ] and
1162
+ c ['id' ] == component_registration ['id' ]
1163
+ ][0 ])
1147
1164
1148
1165
for component_registration in self .callback_map [output ]['state' ]:
1149
1166
args .append ([
1150
- c .get ('value' , None ) for c in state if
1151
- c ['property' ] == component_registration ['property' ] and
1152
- c ['id' ] == component_registration ['id' ]
1153
- ][0 ])
1167
+ c .get ('value' , None ) for c in state if
1168
+ c ['property' ] == component_registration ['property' ] and
1169
+ c ['id' ] == component_registration ['id' ]
1170
+ ][0 ])
1154
1171
1155
1172
response .set_data (self .callback_map [output ]['callback' ](* args ))
1156
1173
return response
0 commit comments