Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
894de55
fix(testing): return [] instead of None from get_logs for non-Chrome …
troclaux May 11, 2026
7569c83
Fix `updatemode="bothdates"` not respected when modifying dates
KoolADE85 Jun 9, 2026
ccf1e03
changelog
KoolADE85 Jun 10, 2026
33de18a
Fix no context in catchall route
KoolADE85 Jun 15, 2026
ff49cff
Fix UnboundLocalError in async background callbacks
imurraywano Jun 16, 2026
dbe2b35
Add CHANGELOG entry for async background callback fix (#3822)
imurraywano Jun 16, 2026
ca3561d
Fix Quart ThreadedRunner.stop() teardown hang
joschrag Jun 17, 2026
bab1204
Add regression test + changelog for Quart stop() hang
joschrag Jun 17, 2026
76829ec
Add PR and issue numbers to changelog entry.
joschrag Jun 17, 2026
8a76f8c
Add per-connection threadpool websocket callback executor.
T4rk1n Jun 17, 2026
8ad2f70
Bump the npm-dependencies group across 1 directory with 56 updates
dependabot[bot] Jun 22, 2026
14ae9de
Drop mcp package dependency, inline protocol types
ndrezn Jun 22, 2026
b4b56ae
Fix import order in tool_get_dash_component
ndrezn Jun 22, 2026
234fc33
Fix black formatting in tool_get_dash_component
ndrezn Jun 23, 2026
c916e2e
Revert breaking dependency upgrades and fix CI
T4rk1n Jun 23, 2026
30befc0
Pin dash-table d3-format to 3.1.0
T4rk1n Jun 23, 2026
b4d507e
Mark test_dvcv013_circular_3_step as flaky
T4rk1n Jun 23, 2026
d7c99ec
Merge pull request #3837 from plotly/dependabot/npm_and_yarn/npm-depe…
T4rk1n Jun 23, 2026
2df5852
Bump the pip-dependencies group across 1 directory with 32 updates
dependabot[bot] Jun 23, 2026
c196c0d
fix pip dependabot
T4rk1n Jun 23, 2026
b37fabf
fix pip dependabot
T4rk1n Jun 23, 2026
ba82120
reset pip minimums
T4rk1n Jun 25, 2026
573a87a
reset ci deps
T4rk1n Jun 25, 2026
4fa8764
drop python 3.8 support
T4rk1n Jun 25, 2026
1f0af4c
Merge branch 'dev' into feat/per-websocket-threadpool
T4rk1n Jun 25, 2026
5fac08d
Merge branch 'dev' into fix/async-background-callback-unboundlocalerror
T4rk1n Jun 25, 2026
60b7711
Merge pull request #3822 from i-murray/fix/async-background-callback-…
T4rk1n Jun 25, 2026
cad27cc
Merge branch 'dev' into bugfix/3812-fastapi-catchall-context
T4rk1n Jun 25, 2026
881ae38
Merge pull request #3819 from plotly/bugfix/3812-fastapi-catchall-con…
T4rk1n Jun 25, 2026
356135d
Merge branch 'dev' into drop-mcp-dependency
KoolADE85 Jun 25, 2026
04aedee
Restore `AnyUrl` type since it does not need `mcp` package
KoolADE85 Jun 25, 2026
1678d66
changelog
KoolADE85 Jun 25, 2026
1a778f6
Merge pull request #3838 from plotly/drop-mcp-dependency
KoolADE85 Jun 26, 2026
df0bd10
Bump axios in the npm-dependencies-security group across 1 directory
dependabot[bot] Jun 26, 2026
f474dca
Merge pull request #3839 from plotly/dependabot/npm_and_yarn/npm-depe…
T4rk1n Jun 26, 2026
c4082ff
Drop private variables check and make distinction via backend attr.
joschrag Jun 29, 2026
e7b11a4
Parametrize tests to test threaded runner shutdown against all backends.
joschrag Jun 29, 2026
4f896d0
async callbacks run on the loop, non async get the threadpool
T4rk1n Jun 29, 2026
93db25d
Merge branch 'dev' into drop-py-3.8
T4rk1n Jun 29, 2026
086dec8
include xvals and yvals when hoveranywhere or clickanywhere is enabled
AnnMarieW Jun 29, 2026
83375b8
Merge pull request #3845 from plotly/drop-py-3.8
T4rk1n Jun 29, 2026
fec0d50
Merge branch 'dev' into dependabot/pip/pip-dependencies-327d618383
T4rk1n Jun 29, 2026
5931c51
lint
AnnMarieW Jun 29, 2026
2dd399a
Merge branch 'dev' into add-clickanywhere-and-hoveranywhere-support-t…
AnnMarieW Jun 29, 2026
3ccdeb6
Merge pull request #3836 from plotly/dependabot/pip/pip-dependencies-…
T4rk1n Jun 29, 2026
3b1e863
added changelog
AnnMarieW Jun 29, 2026
053212a
back to global websocket threadpool
T4rk1n Jun 29, 2026
17b097a
Merge branch 'dev' into feat/per-websocket-threadpool
T4rk1n Jun 29, 2026
abbb592
typing fixes
T4rk1n Jun 29, 2026
b8dcfd9
added axes_id
AnnMarieW Jun 29, 2026
4699277
Merge pull request #3826 from plotly/feat/per-websocket-threadpool
T4rk1n Jun 30, 2026
645d2a6
Merge branch 'dev' into fix/quart-threadedrunner-stop-graceful-shutdown
T4rk1n Jun 30, 2026
a28a458
Merge pull request #3824 from joschrag/fix/quart-threadedrunner-stop-…
T4rk1n Jun 30, 2026
5536f6f
fix dependabot root exclude components/renderer
T4rk1n Jun 30, 2026
4756d70
Merge branch 'dev' into bugfix/3425-datepicker-bothdates
KoolADE85 Jun 30, 2026
1dc3c86
Merge branch 'dev' into bugfix/3425-datepicker-bothdates
KoolADE85 Jun 30, 2026
27c7f7f
Merge pull request #3811 from plotly/bugfix/3425-datepicker-bothdates
KoolADE85 Jun 30, 2026
0d55266
Merge branch 'dev' into add-clickanywhere-and-hoveranywhere-support-t…
T4rk1n Jul 2, 2026
e9aa7e1
fix copy_context in ws threadpool
T4rk1n Jul 2, 2026
164579f
Merge pull request #3852 from AnnMarieW/add-clickanywhere-and-hoveran…
T4rk1n Jul 2, 2026
91f880f
Merge branch 'dev' into fix/get-logs-return-empty-list
T4rk1n Jul 2, 2026
c01f740
docs: add CHANGELOG entry for get_logs [] fix (#3779)
T4rk1n Jul 2, 2026
5dea7b8
Merge pull request #3779 from troclaux/fix/get-logs-return-empty-list
T4rk1n Jul 2, 2026
8f38dda
test: fix contextvars ws test for Python 3.9 (janus.Queue needs runni…
T4rk1n Jul 2, 2026
d5ffe05
Merge branch 'dev' into fix/ws-contextvars
T4rk1n Jul 2, 2026
a33d61d
Merge branch 'dev' into fix/dependabot-spam
T4rk1n Jul 2, 2026
7cf426e
Merge pull request #3860 from plotly/fix/dependabot-spam
T4rk1n Jul 3, 2026
c79ebf4
Merge branch 'dev' into fix/ws-contextvars
T4rk1n Jul 3, 2026
9ba8421
Merge pull request #3862 from plotly/fix/ws-contextvars
T4rk1n Jul 3, 2026
826c080
version 4.4.0
T4rk1n Jul 3, 2026
4e0fb90
Merge pull request #3867 from plotly/version-4.4.0
T4rk1n Jul 3, 2026
b7d537b
Merge branch 'dev' into master-4.4.0
T4rk1n Jul 3, 2026
2a59605
version 4.4.0 build artifacts
T4rk1n Jul 3, 2026
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
37 changes: 29 additions & 8 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
version: 2
updates:
# Root package dependencies
# Root package dependencies.
# NOTE: listing more than one entry under `directories` makes Dependabot treat
# "/" as a recursive glob, so it scans every nested package.json. The negated
# globs below keep it out of directories that have their own update entry — the
# components and the renderer carry narrow allow/ignore lists (e.g. react-docgen
# is pinned) that the root entry would otherwise bypass. @plotly/* is internal.
- package-ecosystem: "npm"
directories:
- "/"
- "!/@plotly/*"
- "!/components/*"
- "!/dash/dash-renderer"
schedule:
interval: "weekly"
day: "monday"
Expand Down Expand Up @@ -43,8 +50,6 @@ updates:
- dependency-name: "babel-loader"
- dependency-name: "ts-loader"
- dependency-name: "cookie"
- dependency-name: "eslint*"
- dependency-name: "prettier"
- dependency-name: "webpack*"
- dependency-name: "typescript"

Expand Down Expand Up @@ -75,10 +80,12 @@ updates:
- dependency-name: "@types/*"
- dependency-name: "@babel/*"
- dependency-name: "babel-loader"
- dependency-name: "eslint*"
- dependency-name: "prettier"
- dependency-name: "webpack*"
- dependency-name: "typescript"
# react-docgen is pinned for legacy metadata extraction (extract-meta.js uses
# the react-docgen 5 API) and must never be updated.
ignore:
- dependency-name: "react-docgen"

# Components - dash-html-components
- package-ecosystem: "npm"
Expand All @@ -101,9 +108,12 @@ updates:
- dependency-name: "@types/*"
- dependency-name: "@babel/*"
- dependency-name: "babel-loader"
- dependency-name: "eslint*"
- dependency-name: "webpack*"
- dependency-name: "typescript"
# react-docgen is pinned for legacy metadata extraction (extract-meta.js uses
# the react-docgen 5 API) and must never be updated.
ignore:
- dependency-name: "react-docgen"

# Components - dash-table
- package-ecosystem: "npm"
Expand All @@ -130,10 +140,12 @@ updates:
- dependency-name: "css-loader"
- dependency-name: "less"
- dependency-name: "less-loader"
- dependency-name: "eslint*"
- dependency-name: "prettier"
- dependency-name: "webpack*"
- dependency-name: "typescript"
# react-docgen is pinned for legacy metadata extraction (extract-meta.js uses
# the react-docgen 5 API) and must never be updated.
ignore:
- dependency-name: "react-docgen"

# Python dependencies
- package-ecosystem: "pip"
Expand All @@ -143,6 +155,10 @@ updates:
day: "monday"
cooldown:
default-days: 14
# Keep lower bounds (e.g. Flask>=1.0.4 in install.txt) low: only raise a
# floor when the latest release is incompatible with the current range.
# Exact (==) pins in ci/dev/testing still update as normal.
versioning-strategy: increase-if-necessary
groups:
pip-dependencies:
applies-to: version-updates
Expand All @@ -152,3 +168,8 @@ updates:
applies-to: security-updates
patterns:
- "*"
# jupyterlab is pinned <4.0.0: jupyterlab 4.x ships jlpm as Yarn Berry, which
# cannot consume @plotly/dash-jupyterlab's Yarn 1 lockfile and breaks the build.
ignore:
- dependency-name: "jupyterlab"
versions: [">=4.0.0"]
43 changes: 43 additions & 0 deletions .github/workflows/post-test-status.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,44 @@ jobs:
}
}

- name: Post Percy status for fork/Dependabot PRs
# Percy needs PERCY_TOKEN to run, which is unavailable to fork PRs (and to
# Dependabot unless added to Dependabot secrets). Without a build, the
# Percy GitHub App never posts the required `percy/dash` status and the PR
# is blocked. Post a success status here so the check resolves — but only
# if Percy hasn't already posted one, so a real Percy result is never
# clobbered (e.g. when Dependabot does have the token).
if: >
github.event.workflow_run.head_repository.full_name != github.repository ||
github.event.workflow_run.actor.login == 'dependabot[bot]'
uses: actions/github-script@v7
with:
script: |
const { owner, repo } = context.repo;
const sha = context.payload.workflow_run.head_sha;
const statusContext = 'percy/dash';

const { data: { statuses } } = await github.rest.repos.getCombinedStatus({
owner,
repo,
ref: sha,
});

if (statuses.some(s => s.context === statusContext)) {
console.log(`'${statusContext}' already posted — leaving it untouched.`);
return;
}

await github.rest.repos.createCommitStatus({
owner,
repo,
sha,
state: 'success',
context: statusContext,
description: 'Skipped — Percy unavailable for fork/Dependabot PRs',
});
console.log(`Posted skipped status for ${statusContext}`);

test-report:
name: Consolidated Test Report (Fork PR)
runs-on: ubuntu-latest
Expand All @@ -79,6 +117,11 @@ jobs:
checks: write
actions: read
steps:
# dorny/test-reporter runs `git ls-files` to resolve test paths, so the
# repo must be checked out. This workflow_run job otherwise has no checkout.
- name: Checkout repository
uses: actions/checkout@v4

- name: Download test results artifact
uses: actions/download-artifact@v4
with:
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.12"]
python-version: ["3.9", "3.12"]

steps:
- name: Checkout repository
Expand Down Expand Up @@ -123,7 +123,7 @@ jobs:
- name: Run lint
env:
PYLINT_EXTRA_ARGS: ${{ matrix.python-version == '3.8' && '--ignored-modules=mcp' || '' }}
PYLINT_EXTRA_ARGS: ${{ matrix.python-version == '3.9' && '--ignored-modules=mcp' || '' }}
run: npm run lint

- name: Run unit tests
Expand Down Expand Up @@ -615,7 +615,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.12"]
python-version: ["3.9", "3.12"]
test-group: ["1", "2", "3"]

env:
Expand Down Expand Up @@ -719,7 +719,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.12"]
python-version: ["3.9", "3.12"]

env:
PERCY_TOKEN: ${{ matrix.python-version == '3.12' && secrets.PERCY_TOKEN || '' }}
Expand Down Expand Up @@ -866,7 +866,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.12"]
python-version: ["3.9", "3.12"]

steps:
- name: Checkout repository
Expand Down Expand Up @@ -914,7 +914,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.12"]
python-version: ["3.9", "3.12"]
test-group: ["1", "2", "3"]

env:
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
legacy-peer-deps=true
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,28 @@
All notable changes to `dash` will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).

## [4.4.0] - 2026-07-03

### Added
- [#3826](https://github.com/plotly/dash/pull/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 `ThreadPoolExecutor` whose size is configurable via the new `websocket_max_workers` argument to `Dash` (default `4`). A synchronous persistent (no-output) callback now warns at registration since it would tie up a worker thread.

## Fixed
- [#3861](https://github.com/plotly/dash/issues/3861) Fix synchronous WebSocket callbacks not inheriting `ContextVar` values 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](https://github.com/plotly/dash/pull/3779) Fix `dash.testing` `Browser.get_logs()` returning `None` on non-Chrome webdrivers, which broke assertions like `assert dash_duo.get_logs() == []`. It now returns `[]`, matching the Chrome code path.
- [#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.
- [#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).
- [#3838](https://github.com/plotly/dash/pull/3838) Replace `mcp` dependency with inline types.
- [#3824](https://github.com/plotly/dash/pull/3824) Fix `dash.testing` `ThreadedRunner.stop()` hanging at teardown for Quart apps. Fixes [#3823](https://github.com/plotly/dash/issues/3823).
- [#3425](https://github.com/plotly/dash/issues/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.

## [4.3.0] - 2026-06-18

## Added
- [#3796](https://github.com/plotly/dash/pull/3796) MCP: Add `configure_mcp_server()` to toggle which content the MCP server exposes (`include_layout`, `include_callbacks`, `include_clientside_callbacks`, `include_pages`, `expose_callback_docstrings`). Only the parameters explicitly passed are updated; omitted parameters retain their current value.
- [#3852](https://github.com/plotly/dash/pull/3852) Added support for Plotly hoveranywhere and clickanywhere events in `dcc.Graph` by adding `xvals` and `yvals` to `hoverData` and `clickData`.

## Changed
- [#3796](https://github.com/plotly/dash/pull/3796) MCP: Remove the `mcp_expose_docstrings` `Dash()` constructor argument; callback docstring exposure is now controlled via `configure_mcp_server(expose_callback_docstrings=...)`.
Expand Down
1 change: 1 addition & 0 deletions components/dash-core-components/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
legacy-peer-deps=true
Loading
Loading