Skip to content

Commit 3124758

Browse files
ptr727claude
andcommitted
Refuse Anything That Is Not a File or a Directory, Not Merely What Is Absent
Testing for existence covered a typo and nothing else. A FIFO, a socket, and a device all exist and are neither a file nor a directory, and `discover` reads each of them as `.`, so the run still scanned the caller's directory while the rule set anchored on the argument's parent. The invariant held for the case I pictured and not for its siblings. The check now asks what the path is rather than whether it is there, which covers both. Two cases: the missing path, and a real FIFO created in the test, skipped where `os.mkfifo` is unavailable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 8756f3a commit 3124758

2 files changed

Lines changed: 23 additions & 8 deletions

File tree

‎scripts/prose_lint.py‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,14 +1119,15 @@ def main(argv: list[str] | None = None) -> int:
11191119
# Only a repository declares a model, so two of them refuse and anything else resolves to one anchor.
11201120
# TestScanRootDecidesTheRuleSet carries the cases and the reason each one exists.
11211121
scan_paths=a.pathsor ['.']
1122-
# A path that does not exist is refused rather than absorbed.
1123-
# `discover` reads a non-file, non-directory argument as `.`, so a typo scanned the caller's directory while the rule set anchored on the missing path's parent.
1124-
absent= [pforpinscan_pathsifnotPath(p).exists()]
1125-
ifabsent:
1122+
# Anything that is not a file or a directory is refused rather than absorbed.
1123+
# `discover` reads such an argument as `.`, so it scanned the caller's directory while the rule set anchored on the argument's parent.
1124+
# Tested for what it is rather than for whether it exists, since a FIFO, a socket, and a device all exist and are none of the two.
1125+
unusable= [pforpinscan_pathsifnot (Path(p).is_file() orPath(p).is_dir())]
1126+
ifunusable:
11261127
# Quoted, since a path holding a space or a comma is unreadable in a bare comma-joined list.
1127-
print(f"error: requested path(s) do not exist: {quoted(absent)}. Refusing rather than "
1128-
'falling back to the current directory, which would scan one tree and choose the '
1129-
'rule set from another.', file=sys.stderr)
1128+
print(f"error: requested path(s) are not a file or a directory: {quoted(unusable)}. "
1129+
'Refusing rather than falling back to the current directory, which would scan one '
1130+
'tree and choose the rule set from another.', file=sys.stderr)
11301131
return2
11311132
git_roots= {foundforfoundin (repo_root(Path(p)) forpinscan_paths) iffound}
11321133
iflen(git_roots) >1:

‎scripts/test_prose_lint.py‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
importcontextlib
1313
importio
1414
importjson
15+
importos
1516
importre
1617
importsubprocess
1718
importsys
@@ -1866,7 +1867,20 @@ def test_a_path_that_does_not_exist_is_refused_rather_than_absorbed(self) -> Non
18661867
withmock.patch.object(prose_lint, 'repo_root', return_value=''):
18671868
self.assertEqual(2, prose_lint.main(
18681869
[str(self.tmp/'no-such-dir'), '--check', 'home-path']))
1869-
self.assertIn('do not exist', self.err.getvalue())
1870+
self.assertIn('not a file or a directory', self.err.getvalue())
1871+
1872+
@unittest.skipUnless(hasattr(os, 'mkfifo'), 'mkfifo is POSIX only')
1873+
deftest_a_path_that_exists_but_is_neither_a_file_nor_a_directory_is_refused(self) ->None:
1874+
"""A FIFO, a socket, and a device all exist, and `discover` reads each of them as `.`.
1875+
1876+
Testing for existence therefore left the hole open on everything that is not a typo.
1877+
"""
1878+
fifo=self.tmp/'a-fifo'
1879+
os.mkfifo(fifo)
1880+
self.assertTrue(fifo.exists())
1881+
withmock.patch.object(prose_lint, 'repo_root', return_value=''):
1882+
self.assertEqual(2, prose_lint.main([str(fifo), '--check', 'home-path']))
1883+
self.assertIn('not a file or a directory', self.err.getvalue())
18701884

18711885
deftest_a_path_holding_a_space_or_comma_is_quoted_in_the_refusal(self) ->None:
18721886
"""Joined bare, one path with a comma in it reads as two paths and the message misleads."""

0 commit comments

Comments
 (0)