Skip to content

Adds DASH and PORT env vars #1134

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

Merged
merged 2 commits into from
Mar 20, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -3,6 +3,9 @@ All notable changes to `dash` will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- [#1134](https://github.com/plotly/dash/pull/1134) Allow `dash.run_server()` host and port parameters to be set with environment variables HOST & PORT, respectively

### Changed
- [#1145](https://github.com/plotly/dash/pull/1145) Update from React 16.8.6 to 16.13.0

2 changes: 2 additions & 0 deletions dash/_configs.py
Original file line number Diff line number Diff line change
@@ -30,6 +30,8 @@ def load_dash_env_vars():
"DASH_SILENCE_ROUTES_LOGGING",
"DASH_PRUNE_ERRORS",
"DASH_COMPRESS",
"HOST",
"PORT",
)
}
)
21 changes: 18 additions & 3 deletions dash/dash.py
Original file line number Diff line number Diff line change
@@ -1841,7 +1841,8 @@ def delete_resource(resources):

def run_server(
self,
port=8050,
host=os.getenv("HOST", "127.0.0.1"),
port=os.getenv("PORT", "8050"),
debug=False,
dev_tools_ui=None,
dev_tools_props_check=None,
@@ -1860,7 +1861,12 @@ def run_server(
If a parameter can be set by an environment variable, that is listed
too. Values provided here take precedence over environment variables.

:param host: Host IP used to serve the application
env: ``HOST``
:type host: string

:param port: Port used to serve the application
env: ``PORT``
:type port: int
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just mark port here as either an int or a string containing an int, and we should be covered re: data types. Your coercion and try/except below looks great!

Can you please add a couple of tests of the failure cases, and maybe one of setting an integer string port and verifying that an app shows up there? These can probably all go in https://github.com/plotly/dash/blob/dev/tests/unit/test_configs.py

The failures can just be something like:

app = Dash()
app.layout = html.Div()
with pytest.raises(...) as excinfo:
    app.run_server(port="garbage")
assert excinfo.value == ...

And the pass case can be something like:

app = Dash()
app.layout = html.Div("hi", id="out")
dash_duo.run_server(app, port="12345")
assert dash_duo.server_url == "https://127.0.0.1:12345"
dash_duo.wait_for_text_to_equal("out", "hi")


:param debug: Set Flask debug mode and enable dev tools.
@@ -1933,9 +1939,18 @@ def run_server(
dev_tools_prune_errors,
)

# Verify port value
try:
port = int(port)
assert port in range(1, 65536)
except Exception as e:
e.args = [
"Expecting an integer from 1 to 65535, found port={}".format(repr(port))
]
raise

if self._dev_tools.silence_routes_logging:
# Since it's silenced, the address doesn't show anymore.
host = flask_run_options.get("host", "127.0.0.1")
ssl_context = flask_run_options.get("ssl_context")
self.logger.info(
"Running on %s://%s:%s%s",
@@ -1955,4 +1970,4 @@ def run_server(

self.logger.info("Debugger PIN: %s", debugger_pin)

self.server.run(port=port, debug=debug, **flask_run_options)
self.server.run(host=host, port=port, debug=debug, **flask_run_options)
8 changes: 8 additions & 0 deletions tests/integration/test_integration.py
Original file line number Diff line number Diff line change
@@ -974,3 +974,11 @@ def g2(a):
@app.callback(Output("inner-div", "children"), [Input("inner-input", "value")])
def h(a):
return a


def test_inin_024_port_env_success(dash_duo):
app = Dash(__name__)
app.layout = html.Div("hi", "out")
dash_duo.start_server(app, port="12345")
assert dash_duo.server_url == "http://localhost:12345"
dash_duo.wait_for_text_to_equal("#out", "hi")
27 changes: 27 additions & 0 deletions tests/unit/test_configs.py
Original file line number Diff line number Diff line change
@@ -231,3 +231,30 @@ def test_strip_relative_path(prefix, partial_path, expected):
def test_invalid_strip_relative_path(prefix, partial_path):
with pytest.raises(_exc.UnsupportedRelativePath):
strip_relative_path(prefix, partial_path)


def test_port_env_fail_str(empty_environ):
app = Dash()
with pytest.raises(Exception) as excinfo:
app.run_server(port="garbage")
assert (
excinfo.exconly()
== "ValueError: Expecting an integer from 1 to 65535, found port='garbage'"
)


def test_port_env_fail_range(empty_environ):
app = Dash()
with pytest.raises(Exception) as excinfo:
app.run_server(port="0")
assert (
excinfo.exconly()
== "AssertionError: Expecting an integer from 1 to 65535, found port=0"
)

with pytest.raises(Exception) as excinfo:
app.run_server(port="65536")
assert (
excinfo.exconly()
== "AssertionError: Expecting an integer from 1 to 65535, found port=65536"
)