-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #322 from plotly/pathname-prefix
Pathname prefix from environ variables.
- Loading branch information
Showing
7 changed files
with
247 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import os | ||
|
||
# noinspection PyCompatibility | ||
from . import exceptions | ||
from ._utils import AttributeDict | ||
|
||
|
||
def env_configs(): | ||
""" | ||
Configs from the environ. | ||
:return: A dict with the dash environ vars | ||
""" | ||
return AttributeDict({x: os.getenv(x, os.getenv(x.lower())) for x in ( | ||
'DASH_APP_NAME', | ||
'DASH_URL_BASE_PATHNAME', | ||
'DASH_ROUTES_PATHNAME_PREFIX', | ||
'DASH_REQUESTS_PATHNAME_PREFIX', | ||
'DASH_SUPPRESS_CALLBACK_EXCEPTIONS', | ||
'DASH_ASSETS_EXTERNAL_PATH', | ||
'DASH_INCLUDE_ASSETS_FILES' | ||
)}) | ||
|
||
|
||
def get_config(config_name, init, env, default=None): | ||
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 | ||
|
||
|
||
def pathname_configs(url_base_pathname=None, | ||
routes_pathname_prefix=None, | ||
requests_pathname_prefix=None, | ||
environ_configs=None): | ||
_pathname_config_error_message = ''' | ||
{} 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. | ||
If you need these to be different values then you should set | ||
`requests_pathname_prefix` and `routes_pathname_prefix`, | ||
not `url_base_pathname`. | ||
''' | ||
environ_configs = environ_configs or env_configs() | ||
|
||
url_base_pathname = get_config('url_base_pathname', | ||
url_base_pathname, | ||
environ_configs) | ||
|
||
routes_pathname_prefix = get_config('routes_pathname_prefix', | ||
routes_pathname_prefix, | ||
environ_configs) | ||
|
||
requests_pathname_prefix = get_config('requests_pathname_prefix', | ||
requests_pathname_prefix, | ||
environ_configs) | ||
|
||
if url_base_pathname is not None and requests_pathname_prefix is not None: | ||
raise exceptions.InvalidConfig( | ||
_pathname_config_error_message.format( | ||
'You supplied `url_base_pathname` and ' | ||
'`requests_pathname_prefix`.' | ||
) | ||
) | ||
elif url_base_pathname is not None and routes_pathname_prefix is not None: | ||
raise exceptions.InvalidConfig( | ||
_pathname_config_error_message.format( | ||
'You supplied `url_base_pathname` and ' | ||
'`routes_pathname_prefix`.') | ||
) | ||
elif url_base_pathname is not None and routes_pathname_prefix is None: | ||
routes_pathname_prefix = url_base_pathname | ||
elif routes_pathname_prefix is None: | ||
routes_pathname_prefix = '/' | ||
|
||
if not routes_pathname_prefix.startswith('/'): | ||
raise exceptions.InvalidConfig( | ||
'`routes_pathname_prefix` needs to start with `/`') | ||
if not routes_pathname_prefix.endswith('/'): | ||
raise exceptions.InvalidConfig( | ||
'`routes_pathname_prefix` needs to end with `/`') | ||
|
||
app_name = environ_configs.DASH_APP_NAME | ||
|
||
if not requests_pathname_prefix and app_name: | ||
requests_pathname_prefix = '/' + app_name + routes_pathname_prefix | ||
elif requests_pathname_prefix is None: | ||
requests_pathname_prefix = routes_pathname_prefix | ||
|
||
if not requests_pathname_prefix.endswith(routes_pathname_prefix): | ||
raise exceptions.InvalidConfig( | ||
'`requests_pathname_prefix` needs to ends with ' | ||
'`routes_pathname_prefix`.' | ||
) | ||
|
||
return url_base_pathname, routes_pathname_prefix, requests_pathname_prefix |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
__version__ = '0.24.2' | ||
__version__ = '0.25.0' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import unittest | ||
# noinspection PyProtectedMember | ||
from dash import _configs | ||
from dash import exceptions as _exc | ||
import os | ||
|
||
|
||
class MyTestCase(unittest.TestCase): | ||
|
||
def setUp(self): | ||
environ = _configs.env_configs() | ||
|
||
for k in environ.keys(): | ||
if k in os.environ: | ||
os.environ.pop(k) | ||
|
||
def test_valid_pathname_prefix_init(self): | ||
_, routes, req = _configs.pathname_configs() | ||
|
||
self.assertEqual('/', routes) | ||
self.assertEqual('/', req) | ||
|
||
_, routes, req = _configs.pathname_configs( | ||
routes_pathname_prefix='/dash/') | ||
|
||
self.assertEqual('/dash/', req) | ||
|
||
_, routes, req = _configs.pathname_configs( | ||
requests_pathname_prefix='/my-dash-app/', | ||
) | ||
|
||
self.assertEqual(routes, '/') | ||
self.assertEqual(req, '/my-dash-app/') | ||
|
||
_, routes, req = _configs.pathname_configs( | ||
routes_pathname_prefix='/dash/', | ||
requests_pathname_prefix='/my-dash-app/dash/' | ||
) | ||
|
||
self.assertEqual('/dash/', routes) | ||
self.assertEqual('/my-dash-app/dash/', req) | ||
|
||
def test_invalid_pathname_prefix(self): | ||
with self.assertRaises(_exc.InvalidConfig) as context: | ||
_, _, _ = _configs.pathname_configs('/my-path', '/another-path') | ||
|
||
self.assertTrue('url_base_pathname' in str(context.exception)) | ||
|
||
with self.assertRaises(_exc.InvalidConfig) as context: | ||
_, _, _ = _configs.pathname_configs( | ||
url_base_pathname='/invalid', | ||
routes_pathname_prefix='/invalid') | ||
|
||
self.assertTrue(str(context.exception).split('.')[0] | ||
.endswith('`routes_pathname_prefix`')) | ||
|
||
with self.assertRaises(_exc.InvalidConfig) as context: | ||
_, _, _ = _configs.pathname_configs( | ||
url_base_pathname='/my-path', | ||
requests_pathname_prefix='/another-path') | ||
|
||
self.assertTrue(str(context.exception).split('.')[0] | ||
.endswith('`requests_pathname_prefix`')) | ||
|
||
with self.assertRaises(_exc.InvalidConfig) as context: | ||
_, _, _ = _configs.pathname_configs('my-path') | ||
|
||
self.assertTrue('start with `/`' in str(context.exception)) | ||
|
||
with self.assertRaises(_exc.InvalidConfig) as context: | ||
_, _, _ = _configs.pathname_configs('/my-path') | ||
|
||
self.assertTrue('end with `/`' in str(context.exception)) | ||
|
||
def test_pathname_prefix_from_environ_app_name(self): | ||
os.environ['DASH_APP_NAME'] = 'my-dash-app' | ||
_, routes, req = _configs.pathname_configs() | ||
self.assertEqual('/my-dash-app/', req) | ||
self.assertEqual('/', routes) | ||
|
||
def test_pathname_prefix_environ_routes(self): | ||
os.environ['DASH_ROUTES_PATHNAME_PREFIX'] = '/routes/' | ||
_, routes, req = _configs.pathname_configs() | ||
self.assertEqual('/routes/', routes) | ||
|
||
def test_pathname_prefix_environ_requests(self): | ||
os.environ['DASH_REQUESTS_PATHNAME_PREFIX'] = '/requests/' | ||
_, routes, req = _configs.pathname_configs() | ||
self.assertEqual('/requests/', req) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters