Repository navigation
Description
Describe the bug
Three tests in TestFileCollection create symlinks with no guard, so they fail on Windows for any user who is not elevated and does not have Developer Mode enabled:
FAILED tests/test_black.py::TestFileCollection::test_get_sources_symlink_and_force_exclude
FAILED tests/test_black.py::TestFileCollection::test_get_sources_with_stdin_symlink_outside_root
FAILED tests/test_black.py::TestFileCollection::test_get_sources_with_stdin_filename_and_force_exclude_and_symlink
E OSError: [WinError 1314] A required privilege is not held by the client
Full suite on Windows (excluding test_blackd.py, which needs the d extra): 3 failed, 442 passed, 4 skipped. The three failures are the only ones.
This is the same bug as #287
#287 ("Skip symlink test if can't create one", 2018) reported exactly this for test_broken_symlink, and it was fixed by guarding the call:
try:
symlink.symlink_to("nonexistent.py")
except (OSError, NotImplementedError) as e:
self.skipTest(f"Can't create symlinks: {e}")
That guard is still there and still works. The three tests above were added later without it, so the same failure came back for the same reason.
Why CI doesn't catch it
The Windows job's runner can create symlinks, so these pass in CI. The failure only appears on an ordinary Windows contributor's machine — green in CI, red locally, permanently. That asymmetry is why a bug fixed in 2018 could silently return.
To Reproduce
On Windows, as a normal user with Developer Mode off:
git clone https://github.com/psf/black && cd black
pip install -e . pytest
pytest tests/test_black.py -k symlink
Expected behavior
The tests skip with a clear reason, as test_broken_symlink already does.
Environment
Windows-11-10.0.26200-SP0
Python 3.13.15
black at HEAD
Suggested fix (implemented and verified)
Add a small module-level helper beside the other test utilities and use it at all five symlink_to call sites, matching the existing skip behaviour:
def symlink_or_skip(link: Path, target: Path | str) -> None:
"""Create a symlink, or skip the test where the platform forbids one.
Windows refuses symlink creation unless the process is elevated or Developer
Mode is enabled, so these tests cannot run for an ordinary Windows
contributor. Same treatment as test_broken_symlink, which has guarded this
since #287.
"""
try:
link.symlink_to(target)
except (OSError, NotImplementedError) as e:
pytest.skip(f"Can't create symlinks: {e}")
pytest.skip rather than self.skipTest because TestFileCollection is a plain pytest class, not a unittest.TestCase. Path | str rather than Union[...] because the file does not import Union and requires-python is >=3.10.
Result on Windows: 3 failed / 442 passed → 0 failed / 442 passed, with the three tests reporting a clear skip reason instead of an obscure OSError.
Patch: patches/black/0001-tests-skip-symlink-tests-when-the-platform-forbids-s.patch
Centralising the helper also means the next symlink test added picks up the guard by default, which is what would have prevented this recurrence.
Activity
webdevsamran commentedon Sep 6, 2026
Hi team, I would like to work on this Windows test fix.
In
tests/test_black.py::TestFileCollection, the three symlink tests create symlinks without checking whether the running process has symlink privileges, causingOSError: [WinError 1314]failures on standard unprivileged Windows environments. I can add the standard pytest symlink skip guard (orhas_symlink_privilege()helper) to these test cases so they skip cleanly when unprivileged on Windows while running everywhere else.Could you please assign this to me? Thanks!