-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Support for config-aware relative paths #1073
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
0af759c
249d305
7e620a9
6b3978d
02a4295
868e93a
57cf39b
dd790ab
86b7665
a0b5f1f
20dd95f
0c0af34
685cd69
c11aabe
31854eb
5879961
46af325
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ | |
from . import _watch | ||
from ._utils import get_asset_path as _get_asset_path | ||
from ._utils import create_callback_id as _create_callback_id | ||
from ._utils import get_relative_path as _get_relative_path | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this pattern ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
from ._configs import get_combined_config, pathname_configs | ||
from .version import __version__ | ||
|
||
|
@@ -1565,6 +1566,28 @@ def get_asset_url(self, path): | |
|
||
return asset | ||
|
||
def get_relative_path(self, path): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Naming options:
Notes:
I think I prefer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The other thing I'm wondering is whether we need the reverse operation, stripping off There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For use in @app.callback(...)
def display_content(path):
if (path is None or
app.get_relative_path(path) == app.get_relative_path('/')):
return chapters.home
elif app.get_relative_path(path) == app.get_relative_path('/page-1')
return chapters.page_1
elif app.get_relative_path(path) == app.get_relative_path('/page-2')
return chapters.page_2 Or, rather, the trailing slashes case: @app.callback(...)
def display_content(path):
if path is None or app.get_relative_path(path) == app.get_relative_path("/"):
return chapters.home
elif app.get_relative_path(path) in [
app.get_relative_path("/page-1"),
app.get_relative_path("/page-1/"),
]:
return chapters.page_1
elif app.get_relative_path(path) in [
app.get_relative_path("/page-2"),
app.get_relative_path("/page-2/"),
]:
return chapters.page_2 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That last example actually exposes another missing case, The documented example should actually be @app.callback(...)
def display_content(path):
if path is None or app.get_relative_path(path) in [
app.get_relative_path(""),
app.get_relative_path("/"),
]:
return chapters.home
elif app.get_relative_path(path) in [
app.get_relative_path("/page-1"),
app.get_relative_path("/page-1/"),
]:
return chapters.page_1
elif app.get_relative_path(path) in [
app.get_relative_path("/page-2"),
app.get_relative_path("/page-2/"),
]:
return chapters.page_2 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suppose, but folks may appreciate simplifying it (including stripping the trailing @app.callback(...)
def display_content(path):
page_name = app.trim_path(path)
if not page_name: # None or ''
return chapters.home
elif page_name == 'page-1':
return chapters.page_1
if page_name == "page-2":
return chapters.page_2 At which point you could even avoid having to reference all the pages individually, since @app.callback(...)
def display_content(path):
page_name = app.trim_path(path)
if not page_name: # None or ''
return chapters.home
return getattr(chapters, page_name.replace("-", "_"))
# or make chapters be a dict that maps without the replacement There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's way better! I'll work on a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright, I added |
||
""" | ||
Return a path with `requests_pathname_prefix` prefixed before it. | ||
Use this function when specifying local URL paths that will work | ||
in environments regardless of what `requests_pathname_prefix` is. | ||
In some deployment environments, like Dash Enterprise, | ||
`requests_pathname_prefix` is set to the application name, | ||
e.g. `my-dash-app`. | ||
When working locally, `requests_pathname_prefix` might be unset and | ||
so a relative URL like `/page-2` can just be `/page-2`. | ||
However, when the app is deployed to a URL like `/my-dash-app`, then | ||
`app.get_relative_path('/page-2')` will return `/my-dash-app/page-2`. | ||
This can be used as an alternative to `get_asset_url` as well with | ||
`app.get_relative_path('/assets/logo.png')` | ||
""" | ||
asset = _get_relative_path( | ||
self.config.requests_pathname_prefix, | ||
path, | ||
) | ||
|
||
return asset | ||
|
||
def _setup_dev_tools(self, **kwargs): | ||
debug = kwargs.get("debug", False) | ||
dev_tools = self._dev_tools = _AttributeDict() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,10 @@ | |
get_combined_config, | ||
load_dash_env_vars, | ||
) | ||
from dash._utils import get_asset_path | ||
from dash._utils import ( | ||
get_asset_path, | ||
get_relative_path, | ||
) | ||
|
||
|
||
@pytest.fixture | ||
|
@@ -156,3 +159,28 @@ def test_load_dash_env_vars_refects_to_os_environ(empty_environ): | |
def test_app_name_server(empty_environ, name, server, expected): | ||
app = Dash(name=name, server=server) | ||
assert app.config.name == expected | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"prefix, partial_path, expected", | ||
[ | ||
("/", "/", "/"), | ||
("/my-dash-app", "/", "/my-dash-app/"), | ||
|
||
("/", "/page-1", "/page-1"), | ||
("/my-dash-app", "/page-1", "/my-dash-app/page-1"), | ||
|
||
("/", "/page-1/", "/page-1/"), | ||
("/my-dash-app", "/page-1/", "/my-dash-app/page-1/"), | ||
|
||
("/", "/page-1/sub-page-1", "/page-1/sub-page-1"), | ||
("/my-dash-app", "/page-1/sub-page-1", "/my-dash-app/page-1/sub-page-1"), | ||
|
||
("/", "relative-page-1", "relative-page-1"), | ||
("/my-dash-app", "relative-page-1", "/my-dash-apprelative-page-1"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These relative URLs are ambiguous in this scenario as we don't know what page we're on. For example, if we were on page So, I thought we'd just keep it a simple prefix without any additional logic. Relative URLs aren't documented in Dash nor used very much anyway. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting... I almost wonder if we should prohibit relative paths. It currently has a bug, I believe, if you use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that sounds good. I added an exception in a0b5f1f |
||
] | ||
) | ||
|
||
def test_pathname_prefix_relative_url(prefix, partial_path, expected): | ||
path = get_relative_path(prefix, partial_path) | ||
assert path == expected |
Uh oh!
There was an error while loading. Please reload this page.