Skip symlink tests when the host cannot create symlinks - #13286
Conversation
Six tests create symlinks unconditionally. On Windows os.symlink() needs SeCreateSymbolicLinkPrivilege, which is only held by an elevated process or when Developer Mode is enabled, so an unprivileged local checkout fails them with `OSError: [WinError 1314] A required privilege is not held by the client` instead of skipping. Add a `symlinks_supported` fixture that probes the capability in a throwaway temporary directory and skips only when the privilege is genuinely missing. CI holds the privilege, so these tests continue to run there and no coverage is lost.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #13286 +/- ##
=======================================
Coverage 98.98% 98.98%
=======================================
Files 132 132
Lines 49023 49030 +7
Branches 2551 2551
=======================================
+ Hits 48526 48533 +7
Misses 373 373
Partials 124 124
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
Merging this PR will not alter performance
Comparing Footnotes
|
The except branch only runs on a host without SeCreateSymbolicLinkPrivilege, so it is never executed on CI and showed up as a patch coverage miss. pragma: no cover is already used for platform-conditional code elsewhere in tests/.
What do these changes do?
Six tests create symlinks unconditionally. On Windows
os.symlink()requiresSeCreateSymbolicLinkPrivilege, which is only held by an elevated process or whenDeveloper Mode is enabled, so on an unprivileged local checkout these tests fail with
OSError: [WinError 1314] A required privilege is not held by the clientrather thanskipping.
This adds a
symlinks_supportedfixture totests/conftest.pythat probes thecapability once in a throwaway temporary directory and skips only when the privilege is
genuinely missing, then requests it from the six affected tests. It follows the existing
unix_socknamepattern, which already skips withpytest.skip("requires UNIX sockets").The probe deliberately tests the capability instead of the platform. A plain
skipif(sys.platform == "win32")would also disable these tests on CI, where theprivilege is held — that would silently drop coverage, which is worse than the
problem being fixed.
Are there changes in behavior for the user?
No. Test-only change; no library code is touched.
Is it a substantial burden for the maintainers to support this?
No — it is one small fixture plus six signature changes, and it removes a
platform-specific failure mode rather than adding a configuration surface. The fixture
has no dependencies beyond
tempfile/pathlib, both already imported inconftest.py.The one judgement call worth reviewing is capability-probing vs. platform-gating; I chose
probing specifically so CI coverage is preserved.
Related issue number
None — found while running the suite on Windows. I did not open a separate issue to avoid
adding tracker noise for a test-only fix; happy to file one if you would prefer that.
Checklist
the new fixture were verified explicitly (see the log block below).
CONTRIBUTORS.txtCHANGES/folderVerification log (Windows 11, Python 3.13,
AIOHTTP_NO_EXTENSIONS=1)Before, full suite — six symlink tests error out:
After — they skip with a reason, and the suite is otherwise unchanged:
test_follow_symlink_directory_traversalstill runs — it does not create a symlink, sothe fixture was deliberately not added to it.
Both fixture branches were checked, since this host cannot exercise the privileged path:
The capable-host branch was exercised by making the probe succeed, which is what happens
on POSIX and on your Windows CI runners.
Lint and types:
Two notes, both outside the scope of this change and left alone:
tests/test_circular_imports.py::test_no_warnings[aiohttp._websocket.reader_c]is theremaining failure above. It fails under
AIOHTTP_NO_EXTENSIONS=1because the Cythonmodule is absent. Say the word and I will open a separate issue.
socket.AF_UNIXmissing, anunused
type: ignoreon the proactor branch).Drafted with Kiro CLI (claude-opus-5); reviewed by @Zuhef.