Added
- #3826 WebSocket callback dispatch no longer lets long-lived callbacks limit the number of concurrent users. Async callbacks (including session-persistent ones) run directly on the connection event loop instead of occupying a worker thread, and synchronous callbacks run on a shared
ThreadPoolExecutorwhose size is configurable via the newwebsocket_max_workersargument toDash(default4). A synchronous persistent (no-output) callback now warns at registration since it would tie up a worker thread.
Fixed
- #3861 Fix synchronous WebSocket callbacks not inheriting
ContextVarvalues bound by ASGI middleware.copy_context()is now captured on the event-loop thread before the callback is submitted to the thread pool, instead of inside the worker thread where only default values were visible. - #3779 Fix
dash.testingBrowser.get_logs()returningNoneon non-Chrome webdrivers, which broke assertions likeassert dash_duo.get_logs() == []. It now returns[], matching the Chrome code path. - #3822 Fix
UnboundLocalErrorforuser_callback_outputin async background callbacks (Celery and Diskcache managers) when the callback raisesPreventUpdateor another exception before the variable is assigned. - #3819 Fix
RuntimeError: No active request in contextwhen a non-Dash path falls through to the FastAPI catch-all route. Fixes #3812. - #3838 Replace
mcpdependency with inline types. - #3824 Fix
dash.testingThreadedRunner.stop()hanging at teardown for Quart apps. Fixes #3823. - #3425 dcc.DatePicker: Fix
updatemode="bothdates"not always respected
Changed
- Drop support for Python 3.8 (end-of-life since October 2024). The minimum supported version is now Python 3.9.