Skip to content

Commit fec0d50

Browse files
authored
Merge branch 'dev' into dependabot/pip/pip-dependencies-327d618383
2 parents 573a87a + 83375b8 commit fec0d50

36 files changed

Lines changed: 920 additions & 386 deletions

‎.github/workflows/testing.yml‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ jobs:
7070
strategy:
7171
fail-fast: false
7272
matrix:
73-
python-version: ["3.8", "3.12"]
73+
python-version: ["3.9", "3.12"]
7474

7575
steps:
7676
- name: Checkout repository
@@ -123,7 +123,7 @@ jobs:
123123
124124
- name: Run lint
125125
env:
126-
PYLINT_EXTRA_ARGS: ${{ matrix.python-version == '3.8' && '--ignored-modules=mcp' || '' }}
126+
PYLINT_EXTRA_ARGS: ${{ matrix.python-version == '3.9' && '--ignored-modules=mcp' || '' }}
127127
run: npm run lint
128128

129129
- name: Run unit tests
@@ -615,7 +615,7 @@ jobs:
615615
strategy:
616616
fail-fast: false
617617
matrix:
618-
python-version: ["3.8", "3.12"]
618+
python-version: ["3.9", "3.12"]
619619
test-group: ["1", "2", "3"]
620620

621621
env:
@@ -719,7 +719,7 @@ jobs:
719719
strategy:
720720
fail-fast: false
721721
matrix:
722-
python-version: ["3.8", "3.12"]
722+
python-version: ["3.9", "3.12"]
723723

724724
env:
725725
PERCY_TOKEN: ${{ matrix.python-version == '3.12' && secrets.PERCY_TOKEN || '' }}
@@ -866,7 +866,7 @@ jobs:
866866
strategy:
867867
fail-fast: false
868868
matrix:
869-
python-version: ["3.8", "3.12"]
869+
python-version: ["3.9", "3.12"]
870870

871871
steps:
872872
- name: Checkout repository
@@ -914,7 +914,7 @@ jobs:
914914
strategy:
915915
fail-fast: false
916916
matrix:
917-
python-version: ["3.8", "3.12"]
917+
python-version: ["3.9", "3.12"]
918918
test-group: ["1", "2", "3"]
919919

920920
env:

‎CHANGELOG.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
All notable changes to `dash` will be documented in this file.
33
This project adheres to [Semantic Versioning](https://semver.org/).
44

5+
## [UNRELEASED]
6+
7+
## Fixed
8+
- [#3822](https://github.com/plotly/dash/pull/3822) Fix `UnboundLocalError` for `user_callback_output` in async background callbacks (Celery and Diskcache managers) when the callback raises `PreventUpdate` or another exception before the variable is assigned.
9+
- [#3819](https://github.com/plotly/dash/pull/3819) Fix `RuntimeError: No active request in context` when a non-Dash path falls through to the FastAPI catch-all route. Fixes [#3812](https://github.com/plotly/dash/issues/3812).
10+
- [#3838](https://github.com/plotly/dash/pull/3838) Replace `mcp` dependency with inline types
11+
12+
## Changed
13+
- Drop support for Python 3.8 (end-of-life since October 2024). The minimum supported version is now Python 3.9.
14+
515
## [4.3.0] - 2026-06-18
616

717
## Added

‎dash/backends/_fastapi.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,12 @@ def _setup_catchall(self):
334334
try:
335335
dash_app = get_app()
336336

337-
async def catchall(_request: Request):
338-
return Response(content=dash_app.index(), media_type="text/html")
337+
async def catchall(request: Request):
338+
token = set_current_request(request)
339+
try:
340+
return Response(content=dash_app.index(), media_type="text/html")
341+
finally:
342+
reset_current_request(token)
339343

340344
# pylint: disable=protected-access
341345
self.add_url_rule("{path:path}", catchall, methods=["GET"])

‎dash/background_callback/managers/celery_manager.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ async def async_run():
209209
c.updated_props = ProxySetProps(_set_props)
210210
context_value.set(c)
211211
errored = False
212+
user_callback_output = None # to help type checking
212213
try:
213214
if isinstance(user_callback_args, dict):
214215
user_callback_output = await fn(
@@ -243,10 +244,10 @@ async def async_run():
243244
),
244245
)
245246

246-
if asyncio.iscoroutine(user_callback_output):
247-
user_callback_output = await user_callback_output
248-
249247
if not errored:
248+
if asyncio.iscoroutine(user_callback_output):
249+
user_callback_output = await user_callback_output
250+
250251
cache.set(
251252
result_key, json.dumps(user_callback_output, cls=PlotlyJSONEncoder)
252253
)

‎dash/background_callback/managers/diskcache_manager.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ async def async_run():
263263
c.updated_props = ProxySetProps(_set_props)
264264
context_value.set(c)
265265
errored = False
266+
user_callback_output = None # to help type checking
266267
try:
267268
if isinstance(user_callback_args, dict):
268269
user_callback_output = await fn(
@@ -289,9 +290,9 @@ async def async_run():
289290
},
290291
)
291292

292-
if asyncio.iscoroutine(user_callback_output):
293-
user_callback_output = await user_callback_output
294293
if not errored:
294+
if asyncio.iscoroutine(user_callback_output):
295+
user_callback_output = await user_callback_output
295296
try:
296297
cache.set(result_key, user_callback_output)
297298
except Exception as err: # pylint: disable=broad-except

‎dash/mcp/_server.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import os
1414
from typing import TYPE_CHECKING, Any
1515

16-
from mcp.types import (
16+
from dash.mcp.types import (
1717
LATEST_PROTOCOL_VERSION,
1818
ErrorData,
1919
Implementation,

‎dash/mcp/primitives/resources/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from __future__ import annotations
44

5-
from mcp.types import (
5+
from dash.mcp.types import (
66
ListResourcesResult,
77
ListResourceTemplatesResult,
88
ReadResourceResult,

‎dash/mcp/primitives/resources/base.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from __future__ import annotations
44

5-
from mcp.types import ReadResourceResult, Resource, ResourceTemplate
5+
from dash.mcp.types import ReadResourceResult, Resource, ResourceTemplate
66

77

88
class MCPResourceProvider:

‎dash/mcp/primitives/resources/resource_clientside_callbacks.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
import json
66
from typing import Any
77

8-
from mcp.types import (
8+
from pydantic import AnyUrl
9+
10+
from dash.mcp.types import (
911
ReadResourceResult,
1012
Resource,
1113
TextResourceContents,
1214
)
13-
from pydantic import AnyUrl
1415

1516
from dash import get_app
1617
from dash._utils import clean_property_name, split_callback_id

‎dash/mcp/primitives/resources/resource_components.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44

55
import json
66

7-
from mcp.types import (
7+
from pydantic import AnyUrl
8+
9+
from dash.mcp.types import (
810
ReadResourceResult,
911
Resource,
1012
TextResourceContents,
1113
)
12-
from pydantic import AnyUrl
1314

1415
from dash import get_app
1516
from dash._layout_utils import traverse

0 commit comments

Comments
 (0)