Skip to content

Commit 4ad5c06

Browse files
committed
Add separate init_app function for providing the flask app
1 parent f958d9e commit 4ad5c06

File tree

1 file changed

+74
-57
lines changed

1 file changed

+74
-57
lines changed

dash/dash.py

+74-57
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,13 @@ def __init__(
108108
components_cache_max_age=None,
109109
show_undo_redo=False,
110110
plugins=None,
111+
defer_app=False,
111112
**kwargs):
112113

114+
# Store some flask-related parameters for use in init_app()
115+
self.compress = compress
116+
self.name = name
117+
113118
# pylint-disable: too-many-instance-attributes
114119
if 'csrf_protect' in kwargs:
115120
warnings.warn('''
@@ -154,22 +159,6 @@ def __init__(
154159
'show_undo_redo': show_undo_redo
155160
})
156161

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-
173162
# list of dependencies
174163
self.callback_map = {}
175164

@@ -181,15 +170,6 @@ def __init__(
181170
# default renderer string
182171
self.renderer = 'var renderer = new DashRenderer();'
183172

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-
193173
# static files from the packages
194174
self.css = Css()
195175
self.scripts = Scripts()
@@ -236,8 +216,6 @@ def _handle_error(_):
236216
'{}_favicon.ico'.format(prefix),
237217
self._serve_default_favicon)
238218

239-
self.server.before_first_request(self._setup_server)
240-
241219
self._layout = None
242220
self._cached_layout = None
243221
self._dev_tools = _AttributeDict({
@@ -250,10 +228,6 @@ def _handle_error(_):
250228
'props_check': False,
251229
})
252230

253-
# add a handler for components suites errors to return 404
254-
self.server.errorhandler(exceptions.InvalidResourceError)(
255-
self._invalid_resources_handler)
256-
257231
self._assets_files = []
258232

259233
# hot reload
@@ -270,6 +244,49 @@ def _handle_error(_):
270244
for plugin in plugins:
271245
plugin.plug(self)
272246

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+
273290
def _add_url(self, name, view_func, methods=('GET',)):
274291
self.server.add_url_rule(
275292
name,
@@ -404,7 +421,7 @@ def _relative_url_path(relative_package_path='', namespace=''):
404421
paths = [paths] if isinstance(paths, str) else paths
405422

406423
for rel_path in paths:
407-
self.registered_paths[resource['namespace']]\
424+
self.registered_paths[resource['namespace']] \
408425
.add(rel_path)
409426

410427
if not is_dynamic_resource:
@@ -432,7 +449,7 @@ def _relative_url_path(relative_package_path='', namespace=''):
432449

433450
def _generate_css_dist_html(self):
434451
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())
436453

437454
return '\n'.join([
438455
_format_tag('link', link, opened=True)
@@ -454,12 +471,12 @@ def _generate_scripts_html(self):
454471
dash_renderer._js_dist_dependencies,
455472
dev_bundles=self._dev_tools.serve_dev_bundles
456473
)) + 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+
))
463480

464481
return '\n'.join([
465482
_format_tag('script', src)
@@ -509,14 +526,14 @@ def serve_component_suites(self, package_name, path_in_package_dist):
509526
'Error loading dependency.\n'
510527
'"{}" is not a registered library.\n'
511528
'Registered libraries are: {}'
512-
.format(package_name, list(self.registered_paths.keys())))
529+
.format(package_name, list(self.registered_paths.keys())))
513530

514531
if path_in_package_dist not in self.registered_paths[package_name]:
515532
raise exceptions.DependencyException(
516533
'"{}" is registered but the path requested is not valid.\n'
517534
'The path requested: "{}"\n'
518535
'List of registered paths: {}'
519-
.format(
536+
.format(
520537
package_name,
521538
path_in_package_dist,
522539
self.registered_paths
@@ -775,7 +792,7 @@ def _validate_callback(self, output, inputs, state):
775792
arg.component_property,
776793
arg.component_id,
777794
component.available_properties).replace(
778-
' ', ''))
795+
' ', ''))
779796

780797
if hasattr(arg, 'component_event'):
781798
raise exceptions.NonExistentEventException('''
@@ -871,19 +888,19 @@ def _raise_invalid(bad_val, outer_val, bad_type, path, index=None,
871888
or is in the top level of the returned list,'''
872889
),
873890
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"
879896
) if not toplevel else '',
880897
bad_val=bad_val).replace(' ', ''))
881898

882899
def _value_is_valid(val):
883900
return (
884901
# 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'
887904
)
888905

889906
def _validate_value(val, index=None):
@@ -1140,17 +1157,17 @@ def dispatch(self):
11401157

11411158
for component_registration in self.callback_map[output]['inputs']:
11421159
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])
11471164

11481165
for component_registration in self.callback_map[output]['state']:
11491166
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])
11541171

11551172
response.set_data(self.callback_map[output]['callback'](*args))
11561173
return response

0 commit comments

Comments
 (0)