Skip to content

Commit 645d2a6

Browse files
authored
Merge branch 'dev' into fix/quart-threadedrunner-stop-graceful-shutdown
2 parents e7b11a4 + 4699277 commit 645d2a6

129 files changed

Lines changed: 17795 additions & 7674 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.envrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ for venv_dir in .venv .env venv env .venv* env* ENV; do
66
break
77
fi
88
done
9+
10+
# Include optional, local-only environment overrides
11+
if [ -f .env ]; then
12+
dotenv
13+
fi

.github/actions/percy-exec/action.yml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ inputs:
1313
description: 'Working directory for the command'
1414
required: false
1515
default: '.'
16+
browser-executable:
17+
description: 'Path to a Chrome/Chromium binary for Percy to use. Defaults to the one found on PATH.'
18+
required: false
19+
default: ''
1620

1721
runs:
1822
using: 'composite'
@@ -23,7 +27,19 @@ runs:
2327
working-directory: ${{ inputs.working-directory }}
2428
env:
2529
PERCY_TOKEN: ${{ inputs.percy-token }}
26-
run: npx percy exec -- ${{ inputs.command }}
30+
PERCY_BROWSER_EXECUTABLE: ${{ inputs.browser-executable }}
31+
run: |
32+
# Percy otherwise downloads its own Chromium from storage.googleapis.com
33+
# on the first snapshot. That download stalls in CI, which blocks the
34+
# synchronous percy_snapshot() calls (so pytest never finishes and writes
35+
# no JUnit) and leaves an empty Percy build with no snapshots. Point Percy
36+
# at the Chrome already installed in the job so it skips the download.
37+
if [ -z "${PERCY_BROWSER_EXECUTABLE:-}" ]; then
38+
PERCY_BROWSER_EXECUTABLE="$(command -v google-chrome || command -v google-chrome-stable || command -v chrome || command -v chromium || command -v chromium-browser || true)"
39+
export PERCY_BROWSER_EXECUTABLE
40+
fi
41+
echo "PERCY_BROWSER_EXECUTABLE=${PERCY_BROWSER_EXECUTABLE:-<unset: Percy will download Chromium>}"
42+
npx percy exec -- ${{ inputs.command }}
2743
2844
- name: Run without Percy (fork PR)
2945
if: inputs.percy-token == ''

.github/dependabot.yml

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ updates:
4343
- dependency-name: "babel-loader"
4444
- dependency-name: "ts-loader"
4545
- dependency-name: "cookie"
46-
- dependency-name: "eslint*"
47-
- dependency-name: "prettier"
4846
- dependency-name: "webpack*"
4947
- dependency-name: "typescript"
5048

@@ -75,10 +73,12 @@ updates:
7573
- dependency-name: "@types/*"
7674
- dependency-name: "@babel/*"
7775
- dependency-name: "babel-loader"
78-
- dependency-name: "eslint*"
79-
- dependency-name: "prettier"
8076
- dependency-name: "webpack*"
8177
- dependency-name: "typescript"
78+
# react-docgen is pinned for legacy metadata extraction (extract-meta.js uses
79+
# the react-docgen 5 API) and must never be updated.
80+
ignore:
81+
- dependency-name: "react-docgen"
8282

8383
# Components - dash-html-components
8484
- package-ecosystem: "npm"
@@ -101,9 +101,12 @@ updates:
101101
- dependency-name: "@types/*"
102102
- dependency-name: "@babel/*"
103103
- dependency-name: "babel-loader"
104-
- dependency-name: "eslint*"
105104
- dependency-name: "webpack*"
106105
- dependency-name: "typescript"
106+
# react-docgen is pinned for legacy metadata extraction (extract-meta.js uses
107+
# the react-docgen 5 API) and must never be updated.
108+
ignore:
109+
- dependency-name: "react-docgen"
107110

108111
# Components - dash-table
109112
- package-ecosystem: "npm"
@@ -130,10 +133,12 @@ updates:
130133
- dependency-name: "css-loader"
131134
- dependency-name: "less"
132135
- dependency-name: "less-loader"
133-
- dependency-name: "eslint*"
134-
- dependency-name: "prettier"
135136
- dependency-name: "webpack*"
136137
- dependency-name: "typescript"
138+
# react-docgen is pinned for legacy metadata extraction (extract-meta.js uses
139+
# the react-docgen 5 API) and must never be updated.
140+
ignore:
141+
- dependency-name: "react-docgen"
137142

138143
# Python dependencies
139144
- package-ecosystem: "pip"
@@ -143,6 +148,10 @@ updates:
143148
day: "monday"
144149
cooldown:
145150
default-days: 14
151+
# Keep lower bounds (e.g. Flask>=1.0.4 in install.txt) low: only raise a
152+
# floor when the latest release is incompatible with the current range.
153+
# Exact (==) pins in ci/dev/testing still update as normal.
154+
versioning-strategy: increase-if-necessary
146155
groups:
147156
pip-dependencies:
148157
applies-to: version-updates
@@ -152,3 +161,8 @@ updates:
152161
applies-to: security-updates
153162
patterns:
154163
- "*"
164+
# jupyterlab is pinned <4.0.0: jupyterlab 4.x ships jlpm as Yarn Berry, which
165+
# cannot consume @plotly/dash-jupyterlab's Yarn 1 lockfile and breaks the build.
166+
ignore:
167+
- dependency-name: "jupyterlab"
168+
versions: [">=4.0.0"]

.github/workflows/post-test-status.yml

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,63 @@ jobs:
6565
}
6666
}
6767
68+
- name: Post Percy status for fork/Dependabot PRs
69+
# Percy needs PERCY_TOKEN to run, which is unavailable to fork PRs (and to
70+
# Dependabot unless added to Dependabot secrets). Without a build, the
71+
# Percy GitHub App never posts the required `percy/dash` status and the PR
72+
# is blocked. Post a success status here so the check resolves — but only
73+
# if Percy hasn't already posted one, so a real Percy result is never
74+
# clobbered (e.g. when Dependabot does have the token).
75+
if: >
76+
github.event.workflow_run.head_repository.full_name != github.repository ||
77+
github.event.workflow_run.actor.login == 'dependabot[bot]'
78+
uses: actions/github-script@v7
79+
with:
80+
script: |
81+
const { owner, repo } = context.repo;
82+
const sha = context.payload.workflow_run.head_sha;
83+
const statusContext = 'percy/dash';
84+
85+
const { data: { statuses } } = await github.rest.repos.getCombinedStatus({
86+
owner,
87+
repo,
88+
ref: sha,
89+
});
90+
91+
if (statuses.some(s => s.context === statusContext)) {
92+
console.log(`'${statusContext}' already posted — leaving it untouched.`);
93+
return;
94+
}
95+
96+
await github.rest.repos.createCommitStatus({
97+
owner,
98+
repo,
99+
sha,
100+
state: 'success',
101+
context: statusContext,
102+
description: 'Skipped — Percy unavailable for fork/Dependabot PRs',
103+
});
104+
console.log(`Posted skipped status for ${statusContext}`);
105+
68106
test-report:
69107
name: Consolidated Test Report (Fork PR)
70108
runs-on: ubuntu-latest
71-
# Only run for fork PRs (non-fork PRs are handled in the main workflow)
109+
# Run for fork PRs and Dependabot PRs. Both run with a read-only
110+
# GITHUB_TOKEN in the main workflow, so the check run is created here in the
111+
# base-repo context instead. Other same-repo PRs are handled in the main workflow.
72112
if: |
73113
github.event.workflow_run.event == 'pull_request' &&
74-
github.event.workflow_run.head_repository.full_name != github.repository
114+
(github.event.workflow_run.head_repository.full_name != github.repository ||
115+
github.event.workflow_run.actor.login == 'dependabot[bot]')
75116
permissions:
76117
checks: write
77118
actions: read
78119
steps:
120+
# dorny/test-reporter runs `git ls-files` to resolve test paths, so the
121+
# repo must be checked out. This workflow_run job otherwise has no checkout.
122+
- name: Checkout repository
123+
uses: actions/checkout@v4
124+
79125
- name: Download test results artifact
80126
uses: actions/download-artifact@v4
81127
with:

.github/workflows/testing.yml

Lines changed: 52 additions & 9 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
@@ -108,7 +108,7 @@ jobs:
108108
run: |
109109
python -m pip install --upgrade pip wheel
110110
python -m pip install "setuptools<80.0.0"
111-
find packages -name dash-*.whl -print -exec sh -c 'pip install "{}[dev,ci,testing]"' \;
111+
find packages -name dash-*.whl -print -exec sh -c 'pip install "{}[dev,ci,testing,diskcache]"' \;
112112
113113
- name: Install dash-renderer dependencies
114114
working-directory: dash/dash-renderer
@@ -122,6 +122,8 @@ jobs:
122122
echo "DISPLAY=:99" >> $GITHUB_ENV
123123
124124
- name: Run lint
125+
env:
126+
PYLINT_EXTRA_ARGS: ${{ matrix.python-version == '3.9' && '--ignored-modules=mcp' || '' }}
125127
run: npm run lint
126128

127129
- name: Run unit tests
@@ -229,7 +231,7 @@ jobs:
229231
run: |
230232
python -m pip install --upgrade pip wheel
231233
python -m pip install "setuptools<80.0.0"
232-
find packages -name dash-*.whl -print -exec sh -c 'pip install "{}[ci,testing,dev]"' \;
234+
find packages -name dash-*.whl -print -exec sh -c 'pip install "{}[ci,testing,dev,diskcache]"' \;
233235
234236
- name: Build/Setup test components
235237
run: npm run setup-tests.py # TODO build the packages and save them to packages/ in build job
@@ -613,13 +615,21 @@ jobs:
613615
strategy:
614616
fail-fast: false
615617
matrix:
616-
python-version: ["3.8", "3.12"]
618+
python-version: ["3.9", "3.12"]
617619
test-group: ["1", "2", "3"]
618620

619621
env:
620622
PERCY_TOKEN: ${{ matrix.python-version == '3.12' && secrets.PERCY_TOKEN || '' }}
621623
PERCY_ENABLE: ${{ matrix.python-version == '3.12' && '1' || '0' }}
622624
PERCY_PARALLEL_TOTAL: -1
625+
# Pin the build identity so every shard joins the same parallel build and
626+
# Percy links it to the PR. Auto-detection otherwise uses the ephemeral
627+
# merge SHA (refs/pull/N/merge), so the build never shows up on the PR.
628+
PERCY_PARALLEL_NONCE: ${{ github.run_id }}-${{ github.run_attempt }}
629+
PERCY_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
630+
PERCY_BRANCH: ${{ github.head_ref || github.ref_name }}
631+
PERCY_PULL_REQUEST: ${{ github.event.pull_request.number }}
632+
PERCY_TARGET_BRANCH: ${{ github.base_ref }}
623633

624634
steps:
625635
- name: Checkout repository
@@ -654,6 +664,7 @@ jobs:
654664
find packages -name dash-*.whl -print -exec sh -c 'pip install "{}[ci,testing,dev,celery,diskcache]"' \;
655665
656666
- name: Setup Chrome and ChromeDriver
667+
id: setup-chrome
657668
uses: browser-actions/setup-chrome@v1
658669
with:
659670
chrome-version: stable
@@ -678,6 +689,7 @@ jobs:
678689
with:
679690
command: pytest --headless --nopercyfinalize --junitxml=test-reports/junit_intg.xml tests/integration --splits 3 --group ${{ matrix.test-group }}
680691
percy-token: ${{ secrets.PERCY_TOKEN }}
692+
browser-executable: ${{ steps.setup-chrome.outputs.chrome-path }}
681693

682694
- name: Upload test results
683695
if: always()
@@ -707,12 +719,20 @@ jobs:
707719
strategy:
708720
fail-fast: false
709721
matrix:
710-
python-version: ["3.8", "3.12"]
722+
python-version: ["3.9", "3.12"]
711723

712724
env:
713725
PERCY_TOKEN: ${{ matrix.python-version == '3.12' && secrets.PERCY_TOKEN || '' }}
714726
PERCY_ENABLE: ${{ matrix.python-version == '3.12' && '1' || '0' }}
715727
PERCY_PARALLEL_TOTAL: -1
728+
# Pin the build identity so every shard joins the same parallel build and
729+
# Percy links it to the PR. Auto-detection otherwise uses the ephemeral
730+
# merge SHA (refs/pull/N/merge), so the build never shows up on the PR.
731+
PERCY_PARALLEL_NONCE: ${{ github.run_id }}-${{ github.run_attempt }}
732+
PERCY_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
733+
PERCY_BRANCH: ${{ github.head_ref || github.ref_name }}
734+
PERCY_PULL_REQUEST: ${{ github.event.pull_request.number }}
735+
PERCY_TARGET_BRANCH: ${{ github.base_ref }}
716736

717737
steps:
718738
- name: Checkout repository
@@ -747,6 +767,7 @@ jobs:
747767
find packages -name dash-*.whl -print -exec sh -c 'pip install "{}[ci,testing,dev]"' \;
748768
749769
- name: Setup Chrome and ChromeDriver
770+
id: setup-chrome
750771
uses: browser-actions/setup-chrome@v1
751772
with:
752773
chrome-version: stable
@@ -773,6 +794,7 @@ jobs:
773794
with:
774795
command: pytest --headless --nopercyfinalize --junitxml=test-reports/junit_html.xml
775796
percy-token: ${{ secrets.PERCY_TOKEN }}
797+
browser-executable: ${{ steps.setup-chrome.outputs.chrome-path }}
776798
working-directory: components/dash-html-components
777799

778800
- name: Upload test results
@@ -844,7 +866,7 @@ jobs:
844866
strategy:
845867
fail-fast: false
846868
matrix:
847-
python-version: ["3.8", "3.12"]
869+
python-version: ["3.9", "3.12"]
848870

849871
steps:
850872
- name: Checkout repository
@@ -892,13 +914,21 @@ jobs:
892914
strategy:
893915
fail-fast: false
894916
matrix:
895-
python-version: ["3.8", "3.12"]
917+
python-version: ["3.9", "3.12"]
896918
test-group: ["1", "2", "3"]
897919

898920
env:
899921
PERCY_TOKEN: ${{ matrix.python-version == '3.12' && secrets.PERCY_TOKEN || '' }}
900922
PERCY_ENABLE: ${{ matrix.python-version == '3.12' && '1' || '0' }}
901923
PERCY_PARALLEL_TOTAL: -1
924+
# Pin the build identity so every shard joins the same parallel build and
925+
# Percy links it to the PR. Auto-detection otherwise uses the ephemeral
926+
# merge SHA (refs/pull/N/merge), so the build never shows up on the PR.
927+
PERCY_PARALLEL_NONCE: ${{ github.run_id }}-${{ github.run_attempt }}
928+
PERCY_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
929+
PERCY_BRANCH: ${{ github.head_ref || github.ref_name }}
930+
PERCY_PULL_REQUEST: ${{ github.event.pull_request.number }}
931+
PERCY_TARGET_BRANCH: ${{ github.base_ref }}
902932

903933
steps:
904934
- name: Checkout repository
@@ -1016,6 +1046,7 @@ jobs:
10161046
find packages -name dash-*.whl -print -exec sh -c 'pip install "{}[ci,testing,dev]"' \;
10171047
10181048
- name: Setup Chrome and ChromeDriver
1049+
id: setup-chrome
10191050
uses: browser-actions/setup-chrome@v1
10201051
with:
10211052
chrome-version: stable
@@ -1034,6 +1065,10 @@ jobs:
10341065
- name: Run Table visual tests
10351066
if: env.PERCY_TOKEN != ''
10361067
working-directory: components/dash-table
1068+
# percy-storybook bundles an old puppeteer whose Chromium is absent on
1069+
# the runner; point it at the system Chrome installed above.
1070+
env:
1071+
PUPPETEER_EXECUTABLE_PATH: ${{ steps.setup-chrome.outputs.chrome-path }}
10371072
run: npm run test.visual
10381073

10391074
- name: Skip Table visual tests (fork PR)
@@ -1056,6 +1091,13 @@ jobs:
10561091
if: always()
10571092
env:
10581093
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
1094+
# Must match the snapshot jobs so finalize targets the same parallel build
1095+
# and the result is attached to the PR head commit, not the merge SHA.
1096+
PERCY_PARALLEL_NONCE: ${{ github.run_id }}-${{ github.run_attempt }}
1097+
PERCY_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
1098+
PERCY_BRANCH: ${{ github.head_ref || github.ref_name }}
1099+
PERCY_PULL_REQUEST: ${{ github.event.pull_request.number }}
1100+
PERCY_TARGET_BRANCH: ${{ github.base_ref }}
10591101
steps:
10601102
- name: Finalize Main Percy Build
10611103
if: |
@@ -1093,8 +1135,9 @@ jobs:
10931135

10941136
- name: Publish Test Report
10951137
uses: dorny/test-reporter@v1
1096-
# Skip for fork PRs - handled by post-test-status.yml workflow_run
1097-
if: always() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
1138+
# Skip for fork PRs and Dependabot PRs - both run with a read-only
1139+
# GITHUB_TOKEN, so they're handled by post-test-status.yml workflow_run.
1140+
if: always() && (github.event_name != 'pull_request' || (github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]'))
10981141
with:
10991142
name: Test Results Summary
11001143
path: 'test-results/**/*.xml'

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
legacy-peer-deps=true

.pylintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ max-returns=6
431431
max-statements=50
432432

433433
# Minimum number of public methods for a class (see R0903).
434-
min-public-methods=2
434+
min-public-methods=1
435435

436436

437437
[IMPORTS]

0 commit comments

Comments
 (0)