test(windows): auto-skip symlink tests when filesystem can't symlink#633
Merged
test(windows): auto-skip symlink tests when filesystem can't symlink#633
Conversation
…t symlink On Windows, ``os.symlink`` requires Developer Mode or admin privileges; without them every symlink-touching test raises ``OSError: [WinError 1314] (client does not hold the required privilege)`` during fixture setup, blowing up otherwise-unrelated tests in the same class. CI is Linux-only so this regression is invisible there, but it makes the suite unrunnable for contributors on a stock Windows shell. Add a ``requires_symlinks`` pytest marker. ``conftest.py`` runs a one-shot ``Path.symlink_to`` probe at import time and ``pytest_collection_modifyitems`` auto-skips marked tests when the probe fails (mirrors the existing ``ollama`` skip pattern). Mark the five sites that create real symlinks: - ``tests/test_runtime_paths.py``: ``test_falls_back_when_xdg_is_symlink``, ``test_refuses_existing_symlink`` - ``tests/test_context_settings.py``: ``test_symlink_target_is_treated_as_host_write`` - ``tests/test_context_projects.py``: ``test_discover_symlink_dedup`` - ``tests/test_context_install.py``: ``test_install_skips_symlinks_in_source`` - ``tests/test_web_routes.py``: entire ``TestFsList`` class (the ``fs_tree`` fixture creates symlinks, so all 14 tests in the class inherit the requirement) Verified locally: - macOS (probe=True): 19/19 marked tests PASS — no behavior change on POSIX or on Windows + Developer Mode. - Probe forced to False: 19/19 SKIPPED with a precise reason string — matches the locked-down-Windows experience. Co-Authored-By: Claude <[email protected]>
4 tasks
Review feedback on PR #633: the probe in ``_can_create_symlink`` only created a file-to-file symlink, but ``TestFsList.fs_tree`` uses ``symlink_to(..., target_is_directory=True)``. Historically Windows treated directory symlinks as a separate privilege class from file symlinks (``SeCreateSymbolicLinkPrivilege`` covers both today, but hardened or older configurations could split them). On such a host the file-only probe would pass and the 14-test ``TestFsList`` class would still hard-fail in fixture setup — exactly the regression this PR is meant to prevent. Also documents the ``--basetemp`` caveat: the probe runs in ``tempfile.gettempdir()``, so users with ``--basetemp`` pointed at a filesystem with different symlink semantics (FAT32, some network mounts) may still see marked tests fail despite the probe passing. Co-Authored-By: Claude <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Five tests (and one whole class via its fixture) call
Path.symlink_to/os.symlinkdirectly. On Windows without Developer Mode or adminprivileges, that raises
OSError: [WinError 1314] (client does not hold the required privilege)— and because most failures land in fixturesetup, they take down otherwise-unrelated tests in the same class.
Surfaced when running
uv run pyteston a fresh Windows shell. CI isLinux-only (tracked separately in #634) so the regression is silent
there.
This PR adds a
requires_symlinkspytest marker.conftest.pyruns aone-shot probe at import time (mirrors the existing
ollamaprobe) thatattempts both a file-to-file and a directory symlink, and
pytest_collection_modifyitemsauto-skips marked tests when eitherbranch fails. POSIX runs and Windows-with-Developer-Mode runs have the
probe return
True, so the marker is a no-op there.Both symlink kinds are probed because Windows historically treated them
as separate privilege classes, and
TestFsList.fs_treespecificallyuses
symlink_to(..., target_is_directory=True).Tests marked:
test_runtime_paths.pytest_falls_back_when_xdg_is_symlinkos.symlinktest_runtime_paths.pytest_refuses_existing_symlinkos.symlinktest_context_settings.pytest_symlink_target_is_treated_as_host_writePath.symlink_totest_context_projects.pytest_discover_symlink_dedupPath.symlink_totest_context_install.pytest_install_skips_symlinks_in_sourcePath.symlink_totest_web_routes.pyTestFsListclassfs_treefixture creates 3 symlinks (incl. directory symlinks); all 14 tests in the class inherit the dependencyThe marker is registered in root
pyproject.tomlso unknown-markerwarnings stay quiet.
Test plan
ruff check+ruff format --checkcleanTrue, both file + dir branches): all 19 markedtests PASS — no behavior change on POSIX or on Developer-Mode
Windows
False(simulating locked-down Windows): all 19marked tests SKIPPED with reason
"Filesystem cannot create symlinks (Windows without Developer Mode/admin)"— including thefull 14-test
TestFsListclassverified by the forced-probe simulation
Notes
This is a test-runner ergonomics fix only — production code is
unchanged. The actual root fix (a Windows CI runner that would have
caught this on its own) is out of scope and tracked separately in #634.
Caveat: the probe runs in
tempfile.gettempdir(), which is whattmp_pathdefaults to. Users runningpytest --basetemp=...pointed ata filesystem with different symlink semantics (FAT32, certain network
mounts) may still see marked tests fail despite the probe passing — see
_can_create_symlinkdocstring.🤖 Generated with Claude Code