-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Pathname prefix from environ variables. #322
Conversation
IMHO, taking config implicitly from environment sounds like not a very good idea, at least for Dash. |
dash/dash.py
Outdated
'requests_pathname_prefix': os.getenv( | ||
'DASH_REQUESTS_PATHNAME_PREFIX', | ||
'/{}/'.format(os.environ['DASH_APP_NAME']) | ||
if 'DASH_APP_NAME' in os.environ else url_base_pathname), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this makes the os.environ parameter take precedence over the value of url_base_pathname
set in the constructor, which might go against @chriddyp's suggestion in #312 of having config values set in the constructor take precedence. (Although the fallback logic here is a bit more subtle than simple parameter shadowing). But then there's the challenge of detecting whether a user specified a value through the constructor or if the value is just the default. I'm not sure what the best of doing that is though.
I wonder if it might make sense to come up with a systematic abstraction for getting config values from the constructor, falling back to os.environ (and handling either upper or lower case DASH_ vars), and then falling back to a final default value? This is probably taking the discussion further afield of this PR (sorry!) but one possibility is to switch to using **kwargs
in the constructor. eg:
some_param = kwargs.get('some_param', os.environ.get('dash_some_param', os.environ.get('DASH_SOME_PARAM', defaults.some_param)))
Although I suppose that breaks IDE autocomplete for Dash.__init__
...
(apologies if I'm missing some additional context to this PR also!)
Why is that? All the variables will be prefixed by For some more context, I laid out the abstraction here: #312 |
dash/dash.py
Outdated
@@ -73,6 +73,7 @@ def __init__( | |||
assets_url_path='/assets', | |||
include_assets_files=True, | |||
url_base_pathname='/', | |||
requests_pathname_prefix='', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency and as per the discussion in #312, I think we should add routes_pathname_prefix
here as well. url_base_pathname
is only there for historical contexts and backwards compatibility, I'd like to move away from it.
Perhaps these arguments should be set to None
as well so that we can distinguish between a user setting them and the default value. Then, we can have code like:
if url_base_pathname is not None and requests_pathname_prefix is not None:
raise Exception('''
You supplied `url_base_pathname` and `requests_pathname_prefix`.
This is ambiguous. To fix this, set `routes_pathname_prefix` instead of `url_base_pathname`.
Note that `requests_pathname_prefix` is the prefix for the AJAX calls that originate from the client (the web browser) and `routes_pathname_prefix` is the prefix for the API routes on the backend (this flask server). `url_base_pathname` will set `requests_pathname_prefix` and `routes_pathname_prefix` to the same value. So, if you need these to be different values then you should set `requests_pathname_prefix` and `routes_pathname_prefix`, not `url_base_pathname`''')
elif url_base_pathname is not None and routes_pathname_prefix is not None:
raise Exception('''
You supplied `url_base_pathname` and `requests_pathname_prefix`.
This is ambiguous. To fix this, set `routes_pathname_prefix` instead of `url_base_pathname`.
Note that `requests_pathname_prefix` is the prefix for the AJAX calls that originate from the client (the web browser) and `routes_pathname_prefix` is the prefix for the API routes on the backend (this flask server). `url_base_pathname` will set `requests_pathname_prefix` and `routes_pathname_prefix` to the same value. So, if you need these to be different values then you should set `requests_pathname_prefix` and `routes_pathname_prefix`, not `url_base_pathname`''')
elif url_base_pathname is not None:
routes_pathname_prefix = url_base_pathname
requests_pathname_prefix = url_base_pathname
elif requests_pathname_prefix is None:
requests_pathname_prefix = ''
elif routes_pathname_prefix is None:
routes_pathname_prefix = ''
And this logic should also incorporate checking from the os.environ
as well.
Since this logic is only going to get bigger, let's also move it to a separate function or file.
Example requests='/dash-app-name' The working url for that app would be The requests thus needs to come from Should we issue a warning and append the routes_pathname if it's not included in the requests_pathname or raises an error in that case ? |
ccec5e5
to
b78262e
Compare
@chriddyp I updated this PR, please review. |
dash/_configs.py
Outdated
''' | ||
environ_configs = environ_configs or env_configs() | ||
|
||
url_base_pathname = choose_config('url_base_pathname', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of "choose_config
", maybe "get_config
"?
app_name = environ_configs.DASH_APP_NAME | ||
|
||
if not requests_pathname_prefix and app_name: | ||
requests_pathname_prefix = '/' + app_name + routes_pathname_prefix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It took me a while to understand this but I think I finally get it. This is the case for users that are deploying on DDS that want a different URL base name. i.e. instead of just /my-app-name
they want it to be /some-base-url/another-app
. I think this will be uncommon but it makes sense and it seems complete 👍
@@ -273,7 +296,7 @@ def _relative_url_path(relative_package_path='', namespace=''): | |||
self.registered_paths[namespace] = [relative_package_path] | |||
|
|||
return '{}_dash-component-suites/{}/{}?v={}'.format( | |||
self.config['routes_pathname_prefix'], | |||
self.config['requests_pathname_prefix'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make sure to note this in the CHANGELOG. It's definitely a bug, so we don't need to bump the major version number, but we should definitely note it as it may break users apps that have modified one value but not the other.
os.environ['DASH_REQUESTS_PATHNAME_PREFIX'] = '/requests/' | ||
_, routes, req = _configs.pathname_configs() | ||
self.assertEqual('/requests/', req) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙇 thanks for the tests!
dash/dash.py
Outdated
env_configs, | ||
True), | ||
'assets_external_path': _configs.choose_config( | ||
'assets_external_path', assets_external_path, env_configs, ''), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 this looks great. Thanks for making these changes!
@ned2 - Check it out now. We're now taking precedence in the constructor with |
Looks good to me @T4rk1n ! 💃 |
173945e
to
614693c
Compare
One thing that bothers me with the None checks is that there is no more checking of the default value in the IDE while you type, but this could be countered with good docstring.
Could put a |
614693c
to
8568403
Compare
Fixes:
requests_pathname_prefix
config when creating scripts tags.Added:
DASH_
(eg:DASH_ROUTES_PATHNAME_PREFIX
)routes/requests_pathname_prefix
evaluation and checks.'/'
routes_pathname_prefix
must start/end with/
.url_base_pathname
androutes/requests_pathname_prefix
.requests_pathname_prefix
must ends withroutes_pathname_prefix
DASH_APP_NAME
is inos.environ
, formatrequests_pathname_prefix
as/{DASH_APP_NAME}{routes_pathname_prefix}