diff --git a/.pylintrc b/.pylintrc index f85cbf3259..fba35186cc 100644 --- a/.pylintrc +++ b/.pylintrc @@ -56,7 +56,8 @@ confidence= # --disable=W" disable=fixme, missing-docstring, - invalid-name + invalid-name, + too-many-lines # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where diff --git a/.pylintrc37 b/.pylintrc37 index ef6ce31186..8ff5bee0db 100644 --- a/.pylintrc37 +++ b/.pylintrc37 @@ -145,7 +145,8 @@ disable=invalid-name, comprehension-escape, no-else-return, useless-object-inheritance, - possibly-unused-variable + possibly-unused-variable, + too-many-lines # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/CHANGELOG.md b/CHANGELOG.md index 68e6c0c493..cdaebbeac2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.27.0 - 2018-09-20 +## Added +- Added support for serving dev bundles from the components suite, enable with `app.run_server(dev_tools_serve_dev_bundles=True)` [#369](https://github.com/plotly/dash/pull/369) + +## Fixed +- Use HTML5 syntax for the meta tag [#350](https://github.com/plotly/dash/pull/350) + ## 0.26.6 - 2018-09-19 ## Fixed - Added `Cache-Control` headers to files served by `Dash.serve_component_suites`. [#387](https://github.com/plotly/dash/pull/387) diff --git a/dash/_configs.py b/dash/_configs.py index 6b46b5cdd4..e5087bd534 100644 --- a/dash/_configs.py +++ b/dash/_configs.py @@ -19,18 +19,21 @@ def env_configs(): 'DASH_SUPPRESS_CALLBACK_EXCEPTIONS', 'DASH_ASSETS_EXTERNAL_PATH', 'DASH_INCLUDE_ASSETS_FILES', - 'DASH_COMPONENTS_CACHE_MAX_AGE' + 'DASH_COMPONENTS_CACHE_MAX_AGE', + 'DASH_INCLUDE_ASSETS_FILES', + 'DASH_SERVE_DEV_BUNDLES', + 'DASH_DEBUG' )}) -def get_config(config_name, init, env, default=None): +def get_config(config_name, init, env, default=None, is_bool=False): if init is not None: return init env_value = env.get('DASH_{}'.format(config_name.upper())) if env_value is None: return default - return env_value + return env_value if not is_bool else env_value.lower() == 'true' def pathname_configs(url_base_pathname=None, diff --git a/dash/dash.py b/dash/dash.py index 9e32383597..1fb94d83ce 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -221,6 +221,9 @@ def add_url(name, view_func, methods=('GET',)): self._layout = None self._cached_layout = None self.routes = [] + self._dev_tools = _AttributeDict({ + 'serve_dev_bundles': False + }) # add a handler for components suites errors to return 404 self.server.errorhandler(exceptions.InvalidResourceError)( @@ -373,11 +376,14 @@ def _generate_scripts_html(self): # pylint: disable=protected-access srcs = self._collect_and_register_resources( self.scripts._resources._filter_resources( - dash_renderer._js_dist_dependencies + dash_renderer._js_dist_dependencies, + dev_bundles=self._dev_tools.serve_dev_bundles )) + self._external_scripts + self._collect_and_register_resources( - self.scripts.get_all_scripts() + + self.scripts.get_all_scripts( + dev_bundles=self._dev_tools.serve_dev_bundles) + self.scripts._resources._filter_resources( - dash_renderer._js_dist + dash_renderer._js_dist, + dev_bundles=self._dev_tools.serve_dev_bundles )) return '\n'.join([ @@ -541,7 +547,7 @@ def dependencies(self): 'inputs': v['inputs'], 'state': v['state'], 'events': v['events'] - } for k, v in list(self.callback_map.items()) + } for k, v in self.callback_map.items() ]) # pylint: disable=unused-argument, no-self-use @@ -979,8 +985,49 @@ def get_asset_url(self, path): return asset + def enable_dev_tools(self, + debug=False, + dev_tools_serve_dev_bundles=None): + """ + Activate the dev tools, called by `run_server`. If your application is + served by wsgi and you want to activate the dev tools, you can call + this method out of `__main__`. + + :param debug: If True, then activate all the tools unless specified. + :type debug: bool + :param dev_tools_serve_dev_bundles: Serve the dev bundles. + :type dev_tools_serve_dev_bundles: bool + :return: + """ + env = _configs.env_configs() + debug = debug or _configs.get_config('debug', None, env, debug, + is_bool=True) + + self._dev_tools['serve_dev_bundles'] = _configs.get_config( + 'serve_dev_bundles', dev_tools_serve_dev_bundles, env, + default=debug, + is_bool=True + ) + return debug + def run_server(self, port=8050, debug=False, + dev_tools_serve_dev_bundles=None, **flask_run_options): - self.server.run(port=port, debug=debug, **flask_run_options) + """ + Start the flask server in local mode, you should not run this on a + production server and use gunicorn/waitress instead. + + :param port: Port the application + :type port: int + :param debug: Set the debug mode of flask and enable the dev tools. + :type debug: bool + :param dev_tools_serve_dev_bundles: Serve the dev bundles of components + :type dev_tools_serve_dev_bundles: bool + :param flask_run_options: Given to `Flask.run` + :return: + """ + debug = self.enable_dev_tools(debug, dev_tools_serve_dev_bundles) + self.server.run(port=port, debug=debug, + **flask_run_options) diff --git a/dash/resources.py b/dash/resources.py index c594864d64..aa1ce871d9 100644 --- a/dash/resources.py +++ b/dash/resources.py @@ -16,7 +16,7 @@ def __init__(self, resource_name, layout): def append_resource(self, resource): self._resources.append(resource) - def _filter_resources(self, all_resources): + def _filter_resources(self, all_resources, dev_bundles=False): filtered_resources = [] for s in all_resources: filtered_resource = {} @@ -24,6 +24,10 @@ def _filter_resources(self, all_resources): filtered_resource['namespace'] = s['namespace'] if 'external_url' in s and not self.config.serve_locally: filtered_resource['external_url'] = s['external_url'] + elif 'dev_package_path' in s and dev_bundles: + filtered_resource['relative_package_path'] = ( + s['dev_package_path'] + ) elif 'relative_package_path' in s: filtered_resource['relative_package_path'] = ( s['relative_package_path'] @@ -54,7 +58,7 @@ def _filter_resources(self, all_resources): return filtered_resources - def get_all_resources(self): + def get_all_resources(self, dev_bundles=False): all_resources = [] if self.config.infer_from_layout: all_resources = ( @@ -63,7 +67,7 @@ def get_all_resources(self): else: all_resources = self._resources - return self._filter_resources(all_resources) + return self._filter_resources(all_resources, dev_bundles) def get_inferred_resources(self): namespaces = [] @@ -127,8 +131,8 @@ def _update_layout(self, layout): def append_script(self, script): self._resources.append_resource(script) - def get_all_scripts(self): - return self._resources.get_all_resources() + def get_all_scripts(self, dev_bundles=False): + return self._resources.get_all_resources(dev_bundles) def get_inferred_scripts(self): return self._resources.get_inferred_resources() diff --git a/dash/version.py b/dash/version.py index 0cfff7a2c6..cf7b6d6589 100644 --- a/dash/version.py +++ b/dash/version.py @@ -1 +1 @@ -__version__ = '0.26.6' +__version__ = '0.27.0'