From f9b28bb7b3eed0ab7d03b4c4a2ad66550acb81e0 Mon Sep 17 00:00:00 2001 From: Constantine Karos Date: Fri, 15 Jan 2021 13:27:44 -0500 Subject: [PATCH 1/5] update get_asset_url function - use external asset path if defined --- dash/dash.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 54fc4c9be5..b18bef5f35 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -1185,11 +1185,18 @@ def csp_hashes(self, hash_algorithm="sha256"): ] def get_asset_url(self, path): - asset = get_asset_path( - self.config.requests_pathname_prefix, + if self.config.assets_external_path: + asset = get_asset_path( + self.config.assets_external_path, + path, + self.config.assets_url_path.lstrip("/"), + ) + else: + asset = get_asset_path( + self.config.requests_pathname_prefix, path, - self.config.assets_url_path.lstrip("/"), - ) + self.config.assets_url_path.lstrip("/"), + ) return asset From 74af0a3102112d06b51b7fd5dedd1a12ea257467 Mon Sep 17 00:00:00 2001 From: Constantine Karos Date: Fri, 15 Jan 2021 13:52:26 -0500 Subject: [PATCH 2/5] update indent for linting --- dash/dash.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/dash.py b/dash/dash.py index b18bef5f35..596f663a7d 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -1194,7 +1194,7 @@ def get_asset_url(self, path): else: asset = get_asset_path( self.config.requests_pathname_prefix, - path, + path, self.config.assets_url_path.lstrip("/"), ) From 6f54daf1181cae5fc7090fb8779be8c359bf6a7e Mon Sep 17 00:00:00 2001 From: Constantine Karos Date: Fri, 15 Jan 2021 18:25:56 -0500 Subject: [PATCH 3/5] Change get_asset_url to be more DRY - changed assets_external_path doc string to be more descriptive - revised _add_assets_resource to join assets_external_path with assets_url_path so that it is cogruent with how get_asset_path works - added unit test `test_asset_url` - updated changelog --- CHANGELOG.md | 6 ++++++ dash/dash.py | 33 +++++++++++++++++---------------- tests/unit/test_configs.py | 22 ++++++++++++++++++++++ 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3366fd904c..76dae1fed1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -694,3 +694,9 @@ app = dash.Dash(...) ## 0.17.3 - 2017-06-22 ✨ This is the initial open-source release of Dash. + +### Fixed +- [#1527](https://github.com/plotly/dash/issues/1527)🐛 `get_asset_url` now pulls from an external source if `assets_external_path` is set. +- updated `_add_assets_resource` to build asset urls the same way as `get_asset_url`. +- updated doc string for `assets_external_path` Dash argument to be more clear that it will allways be joined with +the `assets_url_path` argument when determining the url to an external asset. \ No newline at end of file diff --git a/dash/dash.py b/dash/dash.py index 596f663a7d..fd548dc89a 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -150,10 +150,12 @@ class Dash(object): :type assets_ignore: string :param assets_external_path: an absolute URL from which to load assets. - Use with ``serve_locally=False``. Dash can still find js and css to - automatically load if you also keep local copies in your assets - folder that Dash can index, but external serving can improve - performance and reduce load on the Dash server. + Use with ``serve_locally=False``. assets_external_path is joined + with assets_url_path to determine the absolute url to the + asset folder. Dash can still find js and css to automatically load + if you also keep local copies in your assets folder that Dash can index, + but external serving can improve performance and reduce load on + the Dash server. env: ``DASH_ASSETS_EXTERNAL_PATH`` :type assets_external_path: string @@ -1098,8 +1100,9 @@ def _setup_server(self): def _add_assets_resource(self, url_path, file_path): res = {"asset_path": url_path, "filepath": file_path} if self.config.assets_external_path: - res["external_url"] = "{}{}".format( - self.config.assets_external_path, url_path + res["external_url"] = "/".join([ + self.config.assets_external_path.rstrip('/'), self.config.assets_url_path.strip('/'), url_path.lstrip('/') + ] ) self._assets_files.append(file_path) return res @@ -1186,17 +1189,15 @@ def csp_hashes(self, hash_algorithm="sha256"): def get_asset_url(self, path): if self.config.assets_external_path: - asset = get_asset_path( - self.config.assets_external_path, - path, - self.config.assets_url_path.lstrip("/"), - ) + prefix = self.config.assets_external_path else: - asset = get_asset_path( - self.config.requests_pathname_prefix, - path, - self.config.assets_url_path.lstrip("/"), - ) + prefix = self.config.requests_pathname_prefix + + asset = get_asset_path( + prefix, + path, + self.config.assets_url_path.lstrip("/") + ) return asset diff --git a/tests/unit/test_configs.py b/tests/unit/test_configs.py index a683c3ddf8..35fab04dbb 100644 --- a/tests/unit/test_configs.py +++ b/tests/unit/test_configs.py @@ -105,6 +105,28 @@ def test_pathname_prefix_assets(empty_environ, req, expected): assert path == expected +@pytest.mark.parametrize( + "requests_pathname_prefix, assets_external_path, assets_url_path, expected", + [ + (None , None , "assets" , "/assets/reset.css"), + ("/app/" , None , "assets" , '/app/assets/reset.css'), + (None , None , "css" , "/css/reset.css"), + ("/app/" , None , "css" , "/app/css/reset.css"), + (None , "http:\\external.com/", "assets" , "http:\\external.com/assets/reset.css"), + ("/app/" , "http:\\external.com/", "css" , "http:\\external.com/css/reset.css"), + + ],) +def test_asset_url(empty_environ, requests_pathname_prefix, assets_external_path, assets_url_path, expected): + app = Dash('Dash', + requests_pathname_prefix=requests_pathname_prefix, + assets_external_path=assets_external_path, + assets_url_path=assets_url_path + ) + + path = app.get_asset_url('reset.css') + assert path == expected + + def test_get_combined_config_dev_tools_ui(empty_environ): val1 = get_combined_config("ui", None, default=False) assert ( From 68042fd463e5e77d9176c4077709e21dccbb3f23 Mon Sep 17 00:00:00 2001 From: Constantine Karos <36245370+karosc@users.noreply.github.com> Date: Sat, 16 Jan 2021 09:10:31 -0500 Subject: [PATCH 4/5] Update tests/unit/test_configs.py Co-authored-by: Alex Johnson --- tests/unit/test_configs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_configs.py b/tests/unit/test_configs.py index 35fab04dbb..9bc6a57c65 100644 --- a/tests/unit/test_configs.py +++ b/tests/unit/test_configs.py @@ -112,8 +112,8 @@ def test_pathname_prefix_assets(empty_environ, req, expected): ("/app/" , None , "assets" , '/app/assets/reset.css'), (None , None , "css" , "/css/reset.css"), ("/app/" , None , "css" , "/app/css/reset.css"), - (None , "http:\\external.com/", "assets" , "http:\\external.com/assets/reset.css"), - ("/app/" , "http:\\external.com/", "css" , "http:\\external.com/css/reset.css"), + (None , "http://external.com/", "assets" , "http://external.com/assets/reset.css"), + ("/app/" , "http://external.com/", "css" , "http://external.com/css/reset.css"), ],) def test_asset_url(empty_environ, requests_pathname_prefix, assets_external_path, assets_url_path, expected): From 449f82a14a619cd51697772af4d09c910208e508 Mon Sep 17 00:00:00 2001 From: karosc Date: Sat, 16 Jan 2021 18:29:49 -0500 Subject: [PATCH 5/5] adjust _add_assts_resource to use get_asset_url --- dash/dash.py | 11 ++-------- tests/unit/test_configs.py | 44 ++++++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index fd548dc89a..34f6652bb7 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -1100,10 +1100,7 @@ def _setup_server(self): def _add_assets_resource(self, url_path, file_path): res = {"asset_path": url_path, "filepath": file_path} if self.config.assets_external_path: - res["external_url"] = "/".join([ - self.config.assets_external_path.rstrip('/'), self.config.assets_url_path.strip('/'), url_path.lstrip('/') - ] - ) + res["external_url"] = self.get_asset_url(url_path.lstrip("/")) self._assets_files.append(file_path) return res @@ -1193,11 +1190,7 @@ def get_asset_url(self, path): else: prefix = self.config.requests_pathname_prefix - asset = get_asset_path( - prefix, - path, - self.config.assets_url_path.lstrip("/") - ) + asset = get_asset_path(prefix, path, self.config.assets_url_path.lstrip("/")) return asset diff --git a/tests/unit/test_configs.py b/tests/unit/test_configs.py index 9bc6a57c65..f85318a584 100644 --- a/tests/unit/test_configs.py +++ b/tests/unit/test_configs.py @@ -108,22 +108,34 @@ def test_pathname_prefix_assets(empty_environ, req, expected): @pytest.mark.parametrize( "requests_pathname_prefix, assets_external_path, assets_url_path, expected", [ - (None , None , "assets" , "/assets/reset.css"), - ("/app/" , None , "assets" , '/app/assets/reset.css'), - (None , None , "css" , "/css/reset.css"), - ("/app/" , None , "css" , "/app/css/reset.css"), - (None , "http://external.com/", "assets" , "http://external.com/assets/reset.css"), - ("/app/" , "http://external.com/", "css" , "http://external.com/css/reset.css"), - - ],) -def test_asset_url(empty_environ, requests_pathname_prefix, assets_external_path, assets_url_path, expected): - app = Dash('Dash', - requests_pathname_prefix=requests_pathname_prefix, - assets_external_path=assets_external_path, - assets_url_path=assets_url_path - ) - - path = app.get_asset_url('reset.css') + (None, None, "assets", "/assets/reset.css"), + ("/app/", None, "assets", "/app/assets/reset.css"), + (None, None, "css", "/css/reset.css"), + ("/app/", None, "css", "/app/css/reset.css"), + ( + None, + "http://external.com/", + "assets", + "http://external.com/assets/reset.css", + ), + ("/app/", "http://external.com/", "css", "http://external.com/css/reset.css"), + ], +) +def test_asset_url( + empty_environ, + requests_pathname_prefix, + assets_external_path, + assets_url_path, + expected, +): + app = Dash( + "Dash", + requests_pathname_prefix=requests_pathname_prefix, + assets_external_path=assets_external_path, + assets_url_path=assets_url_path, + ) + + path = app.get_asset_url("reset.css") assert path == expected