Files
graphify/tests/test_non_regular_files.py
T
SoloDrex52andClaude Opus 4.8 f949947003 fix: make the test suite pass on Windows (#4260)
Refuse a read-only destination in _atomic_replace on Windows (nt-only guard;
os.replace there raises PermissionError and the fallback would silently clobber
it), plus test-only guards: utf-8 encoding kwargs, posix-shape path assertions,
FIFO/AF_UNIX/symlink skips, and a replace-retry for AV/indexer locks. No POSIX
behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-09 19:18:06 +01:00

105 lines
3.1 KiB
Python

"""A repository may contain files that are not regular files.
``clone <github-url>`` exists to point the extractor at trees the operator did
not write, and ``watch`` re-runs the scan silently, so the corpus walk has to
survive whatever a repository happens to contain.
The decisive case is a FIFO carrying a source suffix: ``open()`` on a named
pipe with no writer blocks forever and never raises, so the ``try``/``except``
around every reader cannot help — ``graphify update`` simply never returns and
prints nothing. A unix socket fails differently (``ENXIO``) but for the same
reason: it is not a regular file.
"""
import os
import socket
import stat
import tempfile
from pathlib import Path
import pytest
from graphify.detect import _is_regular_file
@pytest.fixture()
def tree():
d = tempfile.mkdtemp(prefix="nonregular-")
src = Path(d, "src")
src.mkdir()
(src / "module.py").write_text("def f():\n return 1\n", encoding="utf-8")
yield Path(d)
def test_regular_source_file_is_accepted(tree):
assert _is_regular_file(tree / "src" / "module.py") is True
needs_fifo = pytest.mark.skipif(not hasattr(os, "mkfifo"), reason="no named pipes on this platform")
def _symlink(link, target):
try:
link.symlink_to(target)
except OSError as exc: # Windows without Developer Mode / admin
pytest.skip(f"cannot create symlinks here: {exc}")
@needs_fifo
def test_fifo_is_rejected(tree):
"""The shape that hangs the whole run."""
fifo = tree / "src" / "pipe.py"
os.mkfifo(fifo)
assert stat.S_ISFIFO(os.stat(fifo).st_mode)
assert _is_regular_file(fifo) is False
@pytest.mark.skipif(not hasattr(socket, "AF_UNIX"), reason="no unix sockets on this platform")
def test_unix_socket_is_rejected(tree):
sock_path = tree / "src" / "sock.py"
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
sock.bind(str(sock_path))
assert _is_regular_file(sock_path) is False
finally:
sock.close()
def test_directory_named_like_a_source_file_is_rejected(tree):
d = tree / "src" / "package.py"
d.mkdir()
assert _is_regular_file(d) is False
def test_symlink_to_a_regular_file_is_accepted(tree):
target = tree / "src" / "module.py"
link = tree / "src" / "alias.py"
_symlink(link, target)
assert _is_regular_file(link) is True
@needs_fifo
def test_symlink_pointing_at_a_fifo_is_rejected(tree):
"""A link to a FIFO blocks exactly like the FIFO, so stat must follow it."""
fifo = tree / "src" / "real.py"
os.mkfifo(fifo)
link = tree / "src" / "link.py"
_symlink(link, fifo)
assert _is_regular_file(link) is False
def test_broken_symlink_is_rejected_without_raising(tree):
link = tree / "src" / "dangling.py"
_symlink(link, tree / "src" / "does-not-exist.py")
assert _is_regular_file(link) is False
def test_missing_path_is_rejected_without_raising(tree):
assert _is_regular_file(tree / "src" / "absent.py") is False
def test_char_device_is_rejected():
dev = Path("/dev/null")
if not dev.exists():
pytest.skip("/dev/null unavailable")
assert _is_regular_file(dev) is False