Skip to content

Commit 0e38ed2

Browse files
committed
Merge branch 'dev' into dash-3.0
2 parents d0d9540 + 7c03187 commit 0e38ed2

File tree

7 files changed

+91
-26
lines changed

7 files changed

+91
-26
lines changed

.editorconfig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ charset = utf-8
1212
indent_style = space
1313
indent_size = 4
1414

15-
# Matches the exact files either package.json or .travis.yml
15+
# Matches the exact files either package.json or .circleci/config.yml
1616
[{package.json,.circleci/config.yml}]
1717
indent_style = space
1818
indent_size = 2
19+

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
77
## Fixed
88

99
- [#3080](https://github.com/plotly/dash/pull/3080) Fix docstring generation for components using single-line or nonstandard-indent leading comments
10+
- [#3103](https://github.com/plotly/dash/pull/3103) Fix Graph component becomes unresponsive if an invalid figure is passed
1011

1112
## [2.18.2] - 2024-11-04
1213

CITATION.cff

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
cff-version: 1.2.0
2+
message: "If you use this software, please cite it as below."
3+
authors:
4+
- family-names: "Parmer"
5+
given-names: "Chris"
6+
- family-names: "Duval"
7+
given-names: "Philippe"
8+
- family-names: "Johnson"
9+
given-names: "Alex"
10+
orcid: https://orcid.org/0000-0003-4623-4147
11+
title: "A data and analytics web app framework for Python, no JavaScript required."
12+
version: 2.18.2
13+
doi: 10.5281/zenodo.14182630
14+
date-released: 2024-11-04
15+
url: https://github.com/plotly/dash

components/dash-core-components/src/fragments/Graph.react.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,9 @@ class PlotlyGraph extends Component {
175175
configClone.typesetMath = mathjax;
176176

177177
const figureClone = {
178-
data: figure.data,
179-
layout: this.getLayout(figure.layout, responsive),
180-
frames: figure.frames,
178+
data: figure?.data,
179+
layout: this.getLayout(figure?.layout, responsive),
180+
frames: figure?.frames,
181181
config: configClone,
182182
};
183183

components/dash-core-components/tests/integration/graph/test_graph_basics.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,3 +370,44 @@ def handleClick(clickData):
370370
data = json.loads(data)
371371
assert "customdata" in data["points"][0], "graph clickData must contain customdata"
372372
assert data["points"][0]["customdata"][0] == expected_value
373+
374+
375+
def test_grbs008_graph_with_empty_figure(dash_dcc):
376+
app = Dash(__name__)
377+
app.layout = html.Div(
378+
[
379+
html.Button("Toggle graph", id="btn"),
380+
dcc.Graph(
381+
id="graph",
382+
figure=None,
383+
),
384+
]
385+
)
386+
387+
@app.callback(Output("graph", "figure"), [Input("btn", "n_clicks")])
388+
def toggle_figure(n_clicks):
389+
if int(n_clicks or 0) % 2 == 0:
390+
# a valid figure
391+
return go.Figure([], layout=go.Layout(title="Valid Figure"))
392+
else:
393+
# an invalid figure
394+
return None
395+
396+
dash_dcc.start_server(app)
397+
398+
# Click the toggle button a couple of times and expect the graph to change between the
399+
# valid and invalid figures, using the "title" as the indicator.
400+
dash_dcc.wait_for_element("#graph")
401+
wait.until(
402+
lambda: dash_dcc.find_element(".gtitle").text == "Valid Figure", timeout=2
403+
)
404+
405+
dash_dcc.find_element("#btn").click()
406+
wait.until(lambda: len(dash_dcc.find_elements(".gtitle")) == 0, timeout=2)
407+
408+
dash_dcc.find_element("#btn").click()
409+
wait.until(
410+
lambda: dash_dcc.find_element(".gtitle").text == "Valid Figure", timeout=2
411+
)
412+
413+
assert dash_dcc.get_logs() == []

components/dash-html-components/scripts/data/attributes.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"elements": [
2121
"form"
2222
],
23-
"description": "List of supported charsets."
23+
"description": "The character set, which if provided must be \"UTF-8\"."
2424
},
2525
"accessKey": {
2626
"elements": [

dash/dash.py

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,25 +2010,26 @@ def delete_resource(resources):
20102010
# pylint: disable=protected-access
20112011
delete_resource(self.css._resources._resources)
20122012

2013+
# pylint: disable=too-many-branches
20132014
def run(
20142015
self,
2015-
host="127.0.0.1",
2016-
port="8050",
2017-
proxy=None,
2018-
debug=None,
2016+
host: Optional[str] = None,
2017+
port: Optional[Union[str, int]] = None,
2018+
proxy: Optional[str] = None,
2019+
debug: Optional[bool] = None,
20192020
jupyter_mode: Optional[JupyterDisplayMode] = None,
2020-
jupyter_width="100%",
2021-
jupyter_height=650,
2022-
jupyter_server_url=None,
2023-
dev_tools_ui=None,
2024-
dev_tools_props_check=None,
2025-
dev_tools_serve_dev_bundles=None,
2026-
dev_tools_hot_reload=None,
2027-
dev_tools_hot_reload_interval=None,
2028-
dev_tools_hot_reload_watch_interval=None,
2029-
dev_tools_hot_reload_max_retry=None,
2030-
dev_tools_silence_routes_logging=None,
2031-
dev_tools_prune_errors=None,
2021+
jupyter_width: str = "100%",
2022+
jupyter_height: int = 650,
2023+
jupyter_server_url: Optional[str] = None,
2024+
dev_tools_ui: Optional[bool] = None,
2025+
dev_tools_props_check: Optional[bool] = None,
2026+
dev_tools_serve_dev_bundles: Optional[bool] = None,
2027+
dev_tools_hot_reload: Optional[bool] = None,
2028+
dev_tools_hot_reload_interval: Optional[int] = None,
2029+
dev_tools_hot_reload_watch_interval: Optional[int] = None,
2030+
dev_tools_hot_reload_max_retry: Optional[int] = None,
2031+
dev_tools_silence_routes_logging: Optional[bool] = None,
2032+
dev_tools_prune_errors: Optional[bool] = None,
20322033
**flask_run_options,
20332034
):
20342035
"""Start the flask server in local mode, you should not run this on a
@@ -2037,11 +2038,11 @@ def run(
20372038
If a parameter can be set by an environment variable, that is listed
20382039
too. Values provided here take precedence over environment variables.
20392040
2040-
:param host: Host IP used to serve the application
2041+
:param host: Host IP used to serve the application, default to "127.0.0.1"
20412042
env: ``HOST``
20422043
:type host: string
20432044
2044-
:param port: Port used to serve the application
2045+
:param port: Port used to serve the application, default to "8050"
20452046
env: ``PORT``
20462047
:type port: int
20472048
@@ -2142,9 +2143,15 @@ def run(
21422143

21432144
# Evaluate the env variables at runtime
21442145

2145-
host = os.getenv("HOST", host)
2146-
port = os.getenv("PORT", port)
2147-
proxy = os.getenv("DASH_PROXY", proxy)
2146+
if "CONDA_PREFIX" in os.environ:
2147+
# Some conda systems has issue with setting the host environment
2148+
# to an invalid hostname.
2149+
# Related issue: https://github.com/plotly/dash/issues/3069
2150+
host = host or "127.0.0.1"
2151+
else:
2152+
host = host or os.getenv("HOST", "127.0.0.1")
2153+
port = port or os.getenv("PORT", "8050")
2154+
proxy = proxy or os.getenv("DASH_PROXY")
21482155

21492156
# Verify port value
21502157
try:

0 commit comments

Comments
 (0)