Pin secure test dependency floors and drop EOL Python 3.9/3.8#2045
Conversation
pytest>=9.0.3, requests>=2.33.0 and urllib3>=2.7.0 all require Python >=3.10, so they have no installable candidate on Python 3.9. Since Python 3.9 and 3.8 are EOL, drop them from the test matrix and bump the minimum supported version to 3.10, and add the CVE-driven dependency floors (supersedes microsoft#2043). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
GitHub cannot anchor PR review comments to unchanged lines in the diff. Falling back to a general PR comment for azure-pipelines/pipelines.yaml:L219. Removing |
heejaechang
left a comment
There was a problem hiding this comment.
Approved via Review Center.
|
Fixed in 804b463 — restored a 32-bit Windows CI leg on a supported interpreter (`py310_32: { python.version: 3.10, architecture: x86 }`) in the `Test_Windows` matrix. |
|
Approving — the security floors and EOL-interpreter removal are correct. Two follow-ups worth checking before merge: (1) verify the dep set actually installs/collects on the re-added win32 CPython 3.10 leg, and (2) the PR description says "32-bit Windows testing is dropped," but the diff actually re-adds it as |
|
Change looks sound. Main residual risk is install-time fragility on the newly-added 32-bit 3.10 leg and the major pytest 8→9 bump with unpinned plugins — worth a quick smoke-install/collect before merge, but not blocking. |
heejaechang
left a comment
There was a problem hiding this comment.
Approved via Review Center.
The previously re-added py310_32 (32-bit Windows) leg runs `pip install -r tests/requirements.txt` on win32 CPython 3.10. gevent publishes no cp310-win32 wheel (only win_amd64), so pip would fall back to a source build of gevent/greenlet/libev/c-ares and risk failing the leg at install -- the same install-failure class this PR removes. numpy and Cython do ship cp310-win32 wheels, but there is no reliable PEP 508 marker to drop only gevent for a 32-bit interpreter on 64-bit Windows, so the leg is removed to keep CI green and consistent with the PR intent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| architecture: x86 | ||
| py310: | ||
| python.version: 3.10 | ||
| py311: |
There was a problem hiding this comment.
📍 azure-pipelines/pipelines.yaml:211
This revision removes py39 and py39_32 and adds nothing in their place, so the Windows matrix is now py310–py314 with zero 32-bit legs — yet setup.py:is_applicable still packages win32 artifacts (return plat in ("win32", "win-amd64")). debugpy continues to ship a win32 wheel surface with no x86 CI signal. Either restore a single py310_32 (architecture: x86) leg — and smoke-install tests/requirements.txt on win32 cp310 to confirm the unpinned C-extension deps resolve — or remove win32 from setup.py:is_applicable so packaging and CI agree. Do not merge with a shipped-but-untested architecture.
There was a problem hiding this comment.
Thanks — this is a real tension, but I don't think either literal option is the right change to make inside this PR, so I'm flagging it for a maintainer call rather than forcing it here. Reasoning, with evidence:
Option A — restore a py310_32 (x86) leg: This re-introduces the exact failure class this PR exists to remove. As established in the (now-resolved) thread above, gevent ships no cp310-win32 wheel (only ...-cp310-cp310-win_amd64.whl), so pip install -r tests/requirements.txt on win32 cp310 falls back to a source build of gevent (greenlet/libev/c-ares) and risks failing the leg at install. There's no PEP 508 marker that reliably distinguishes a 32-bit interpreter on 64-bit Windows (platform_machine reflects the OS, not the interpreter), so gevent can't be cleanly gated off only the x86 leg without either still source-building or silently dropping gevent coverage. Adding the leg back is therefore a coverage/risk tradeoff that you flagged yourself — a maintainer decision, not something I should force in autonomously.
Option B — remove win32 from setup.py:is_applicable: This doesn't actually stop debugpy from shipping a win32 wheel — is_applicable only filters which vendored pydevd native binaries (.exe/.dll/.pdb/.pyd) get copied into the wheel. Dropping win32 there would still build a win32 wheel, just a broken one missing the attach-to-process binaries. Genuinely retiring the win32 wheel surface means changing the build/packaging matrix and would break existing 32-bit Windows users — clearly out of scope for "drop EOL 3.9/3.8 + pin secure dep floors."
Note this PR didn't newly create the gap: the only prior 32-bit leg was py39_32, removed here solely because Python 3.9 is EOL. The win32 packaging surface is unchanged.
My recommendation: keep win32 packaging as-is in this PR and track "restore an x86 test signal (wheel-only deps, gevent excluded on x86)" or "retire the win32 wheel" as a separate, deliberate follow-up. Happy to implement whichever direction you choose — leaving this thread open for your call.
|
Solid security-floor + EOL-cleanup change overall. One blocking item: reconcile dropping the only 32-bit Windows test leg with still shipping win32 wheels (restore a 32-bit leg on a supported Python, or stop packaging win32). Also align the remaining py38 static-analysis declarations with the new >=3.10 floor. |
Bump [tool.pyright] pythonVersion and [tool.ruff] target-version from 3.8/py38 to 3.10/py310 (and update the comment) so the Lint stage and pyright validate against the supported floor this PR converges on. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| architecture: x86 | ||
| py310: | ||
| python.version: 3.10 | ||
| py311: |
There was a problem hiding this comment.
This revision removes both py39 and py39_32 — the base branch's only architecture: x86 leg — leaving the Windows matrix at py310–py314 under the global architecture: x64. Meanwhile setup.py (is_applicable) still ships win32 wheels (plat in ("win32", "win-amd64")), so debugpy continues to package an x86 surface with zero x86 CI signal: a win32-only regression in the attach binaries could ship undetected. Consider either restoring one py310 architecture: x86 leg (at minimum smoke-installing tests/requirements.txt on win32 cp310), or narrowing setup.py:is_applicable to drop win32 so packaging and CI coverage agree.
There was a problem hiding this comment.
Thanks — this is the same x86-CI vs. win32-packaging tension raised (and discussed in depth) in the thread above, so I'll consolidate here and keep it open for a maintainer call rather than force a change in this PR.
Both options you list have been evaluated, with evidence:
-
Restore a
py310x86 leg. I actually tried this in this PR (804b4639"ci: restore x86 Windows leg on Python 3.10") and had to revert it (d2c3ac40"ci: drop x86 Windows leg (gevent has no cp310-win32 wheel)").geventpublishes no cp310-win32 wheel, sopip install -r tests/requirements.txton win32 cp310 falls back to a source build (greenlet/libev/c-ares) and risks failing the leg at install — the exact failure class this PR exists to remove. There's also no PEP 508 marker that reliably distinguishes a 32-bit interpreter on 64-bit Windows (platform_machinereflects the OS, not the interpreter), so gevent can't be cleanly excluded on just the x86 leg. -
Drop
win32fromsetup.py:is_applicable.is_applicableonly filters which vendored pydevd native binaries get copied into the wheel; it does not stop a win32 wheel from being built. Removingwin32there would still ship a win32 wheel — just a broken one missing the attach-to-process binaries. Genuinely retiring the win32 wheel surface is a packaging-matrix change that would break existing 32-bit users, which is out of scope for "drop EOL 3.9/3.8 + pin secure dep floors."
For context, this PR didn't create the gap: the only prior x86 leg was py39_32, removed here solely because Python 3.9 is EOL; the win32 packaging surface is unchanged.
Recommendation: keep win32 packaging as-is in this PR (which you've approved) and track "restore an x86 test signal with wheel-only deps (gevent excluded on x86)" or "retire the win32 wheel surface" as a separate, deliberate follow-up. Happy to implement whichever direction you choose — leaving this open for your call.
There was a problem hiding this comment.
Thanks — this is the same x86-CI vs. win32-packaging tension raised (and discussed in depth) in the thread above, so I'll consolidate here and keep it open for a maintainer call rather than force a change in this PR.
Both options you list have been evaluated, with evidence:
-
Restore a
py310x86 leg. I actually tried this in this PR (804b4639"ci: restore x86 Windows leg on Python 3.10") and had to revert it (d2c3ac40"ci: drop x86 Windows leg (gevent has no cp310-win32 wheel)").geventpublishes no cp310-win32 wheel, sopip install -r tests/requirements.txton win32 cp310 falls back to a source build (greenlet/libev/c-ares) and risks failing the leg at install — the exact failure class this PR exists to remove. There's also no PEP 508 marker that reliably distinguishes a 32-bit interpreter on 64-bit Windows (platform_machinereflects the OS, not the interpreter), so gevent can't be cleanly excluded on just the x86 leg. -
Drop
win32fromsetup.py:is_applicable.is_applicableonly filters which vendored pydevd native binaries get copied into the wheel; it does not stop a win32 wheel from being built. Removingwin32there would still ship a win32 wheel — just a broken one missing the attach-to-process binaries. Genuinely retiring the win32 wheel surface is a packaging-matrix change that would break existing 32-bit users, which is out of scope for "drop EOL 3.9/3.8 + pin secure dep floors."
For context, this PR didn't create the gap: the only prior x86 leg was py39_32, removed here solely because Python 3.9 is EOL; the win32 packaging surface is unchanged.
Recommendation: keep win32 packaging as-is in this PR (which you've approved) and track "restore an x86 test signal with wheel-only deps (gevent excluded on x86)" or "retire the win32 wheel surface" as a separate, deliberate follow-up. Happy to implement whichever direction you choose — leaving this open for your call.
|
Security floors and the 3.8/3.9 removal look consistent across setup.py, pyproject.toml, tox.ini, and the CI matrices. Two non-blocking things worth a look before merge: (1) dropping the only x86 leg while still shipping win32 wheels leaves that surface without CI signal, and (2) the pytest 8→9 major bump with floor-less plugins — a quick |
heejaechang
left a comment
There was a problem hiding this comment.
Approved via Review Center.
Summary
Supersedes #2043. Adds the secure minimum-version floors for test dependencies that Component Governance flags as vulnerable, and drops Python 3.9/3.8 (both EOL) so those floors are installable.
The pinned versions in #2043 —
pytest>=9.0.3,requests>=2.33.0,urllib3>=2.7.0— all require Python >=3.10, so on the 3.9 CI legspip install -r tests/requirements.txtfailed withNo matching distribution found for pytest>=9.0.3(every 9.x release isRequires-Python >=3.10). Since Python 3.9 (and 3.8) are past end-of-life, the right fix is to stop testing/claiming support for them rather than weaken the security floors.CVEs addressed
Changes
tests/requirements.txt:pytest>=9.0.3,requests>=2.33.0,urllib3>=2.7.0(explicit floor since it's pulled in transitively byrequests).azure-pipelines/pipelines.yaml: removepy39from the Linux/macOS/Windows test matrices, remove thepy39_32(32-bit) leg, and bump the Lint stage to Python 3.10.tox.ini: droppy38/py39fromenvlistand the per-env commands.setup.py:python_requires=">=3.10"and remove the 3.8/3.9 classifiers.Notes
src/debugpy/_vendored/pydevd/are out of scope here.