# HG changeset patch # User Franz Glasner # Date 1739952750 -3600 # Node ID c02a57df2a298fe7480b9aa110b9dd8ccd9334a0 # Parent b4137ebd8e795dcdd073a92c5d52d7ab65b906d9 treesum: - WalkDirEntry tests with a FIFO special file - WalkDirEntry.is_reg Also all to be handled special files in the notes document. diff -r b4137ebd8e79 -r c02a57df2a29 cutils/util/walk.py --- a/cutils/util/walk.py Tue Feb 18 19:30:40 2025 +0100 +++ b/cutils/util/walk.py Wed Feb 19 09:12:30 2025 +0100 @@ -21,6 +21,7 @@ from scandir import scandir except ImportError: scandir = None +import stat import sys from . import PY2 @@ -53,8 +54,8 @@ """ __slots__ = ("_name", "_path", # encoded as given in the ctor - "_is_symlink", "_is_dir", "_stat_result", "_stat_errno", - "_stat_errstr", + "_is_symlink", "_is_reg", "_is_dir", "_stat_result", + "_stat_errno", "_stat_errstr", "_alt_fsname", "_alt_u8name") def __init__(self, name, path): @@ -62,7 +63,7 @@ """The name exactly as given in the ctor""" self._path = _unix_path(path) """The path as given in the ctor -- but normalized to have slashes""" - self._is_symlink = self._is_dir = self._stat_result = \ + self._is_symlink = self._is_reg = self._is_dir = self._stat_result = \ self._stat_errno = self._stat_errstr = None self._alt_fsname = self._alt_u8name = _notset @@ -227,6 +228,10 @@ return self._is_symlink @property + def is_reg(self): + return self._is_reg + + @property def is_dir(self): return self._is_dir @@ -278,6 +283,9 @@ w._stat_result = None w._stat_errno = e.errno w._stat_errstr = e.strerror + w._is_reg = False + else: + w._is_reg = stat.S_ISREG(w._stat_result.st_mode) return w @classmethod @@ -307,6 +315,9 @@ w._stat_result = None w._stat_errno = e.errno w._stat_errstr = e.strerror + w._is_reg = False + else: + w._is_reg = stat.S_ISREG(w._stat_result.st_mode) return w @classmethod diff -r b4137ebd8e79 -r c02a57df2a29 docs/notes.rst --- a/docs/notes.rst Tue Feb 18 19:30:40 2025 +0100 +++ b/docs/notes.rst Wed Feb 19 09:12:30 2025 +0100 @@ -19,11 +19,45 @@ Symlink to a directory - ``/./@` + ``/./@`` Symlink to other filesystem object. Also used if the link is broken and the target type cannot determined. + ``/./|``, ``/./@|`` + + FIFO and symlink to FIFO + + ``/./=``, ``/./@=`` + + Socket and symlink to socket + + ``/./>``, ``/./@>`` + + Door (Solaris) and symlink to door + + ``/./%``, ``/./@%`` + + Whiteout and symlink to whiteout (used by union filesystems) (BSD) + +Nonstandard path endings are: + + ``/./:``, ``/./@:`` + + Character special and symlink to character special + + ``/./;``, ``/./@;`` + + Block special and symlink to block special + + ``/./)``, ``/./@)`` + + Event port (Solaris, Illumos) and symlink to event port + + +.. note:: :command:`ls` can also use ``*`` for regular files that are + executable. + Fields: diff -r b4137ebd8e79 -r c02a57df2a29 tests/_test_setup.py --- a/tests/_test_setup.py Tue Feb 18 19:30:40 2025 +0100 +++ b/tests/_test_setup.py Wed Feb 19 09:12:30 2025 +0100 @@ -9,6 +9,7 @@ TESTDIR = os.path.normpath(os.path.abspath(os.path.dirname(__file__))) DATADIR = os.path.join(TESTDIR, "data") +TMPDIR = os.path.join(DATADIR, "_tmp") sys.path.insert(0, os.path.join(TESTDIR, "..")) diff -r b4137ebd8e79 -r c02a57df2a29 tests/test_walk.py --- a/tests/test_walk.py Tue Feb 18 19:30:40 2025 +0100 +++ b/tests/test_walk.py Wed Feb 19 09:12:30 2025 +0100 @@ -6,10 +6,11 @@ from __future__ import absolute_import, print_function import os +import shutil import sys import unittest -from _test_setup import DATADIR +from _test_setup import (DATADIR, TMPDIR) from cutils.util import walk @@ -206,6 +207,7 @@ entry = walk.WalkDirEntry.from_path_name( DATADIR, "tree-1-s") self.assertTrue(entry.is_symlink) + self.assertFalse(entry.is_reg) self.assertTrue(entry.is_dir) self.assertIsNotNone(entry.stat) @@ -213,6 +215,7 @@ entry = walk.WalkDirEntry.from_path_name( DATADIR, "tree-nn-s") self.assertTrue(entry.is_symlink) + self.assertFalse(entry.is_reg) self.assertFalse(entry.is_dir) self.assertIsNone(entry.stat) @@ -220,6 +223,7 @@ entry = walk.WalkDirEntry.from_path_name( DATADIR, "tree-1") self.assertFalse(entry.is_symlink) + self.assertFalse(entry.is_reg) self.assertTrue(entry.is_dir) self.assertIsNotNone(entry.stat) @@ -227,6 +231,7 @@ entry = walk.WalkDirEntry.from_path_name( os.path.join(DATADIR, "tree-1"), "file-1-1-s.txt") self.assertTrue(entry.is_symlink) + self.assertTrue(entry.is_reg) self.assertFalse(entry.is_dir) self.assertIsNotNone(entry.stat) @@ -234,6 +239,7 @@ entry = walk.WalkDirEntry.from_path_name( os.path.join(DATADIR, "tree-1"), "file-1-nn-s.txt") self.assertTrue(entry.is_symlink) + self.assertFalse(entry.is_reg) self.assertFalse(entry.is_dir) self.assertIsNone(entry.stat) @@ -241,6 +247,7 @@ entry = walk.WalkDirEntry.from_path_name( os.path.join(DATADIR, "tree-1"), "file-1-1.txt") self.assertFalse(entry.is_symlink) + self.assertTrue(entry.is_reg) self.assertFalse(entry.is_dir) self.assertIsNotNone(entry.stat) @@ -248,9 +255,54 @@ entry = walk.WalkDirEntry.from_path_name( os.path.join(DATADIR, "tree-1-s"), "file-1-1.txt") self.assertFalse(entry.is_symlink) + self.assertTrue(entry.is_reg) self.assertFalse(entry.is_dir) self.assertIsNotNone(entry.stat) +@unittest.skipIf(not hasattr(os, "mkfifo"), "Needs os.mkfifo()") +class FIFOTests(unittest.TestCase): + + def setUp(self): + if not os.path.isdir(TMPDIR): + os.mkdir(TMPDIR) + + def tearDown(self): + if os.path.isdir(TMPDIR): + shutil.rmtree(TMPDIR) + + def test_real_mkfifo(self): + fifopath = os.path.join(TMPDIR, "test.fifo") + os.mkfifo(fifopath) + entry = walk.WalkDirEntry.from_path_name(TMPDIR, "test.fifo") + self.assertFalse(entry.is_symlink) + self.assertFalse(entry.is_reg) + self.assertFalse(entry.is_dir) + self.assertIsNotNone(entry.stat) + + def test_symlink_to_mkfifo(self): + fifopath = os.path.join(TMPDIR, "test.fifo") + fifo_s_path = os.path.join(TMPDIR, "test-s.fifo") + os.mkfifo(fifopath) + os.symlink(fifopath, fifo_s_path) + entry = walk.WalkDirEntry.from_path_name(TMPDIR, "test-s.fifo") + self.assertTrue(entry.is_symlink) + self.assertFalse(entry.is_reg) + self.assertFalse(entry.is_dir) + self.assertIsNotNone(entry.stat) + + def test_broken_symlink_to_mkfifo(self): + fifopath = os.path.join(TMPDIR, "test.fifo") + fifo_s_path = os.path.join(TMPDIR, "test-s.fifo") + os.mkfifo(fifopath) + os.symlink(fifopath, fifo_s_path) + os.unlink(fifopath) + entry = walk.WalkDirEntry.from_path_name(TMPDIR, "test-s.fifo") + self.assertTrue(entry.is_symlink) + self.assertFalse(entry.is_reg) + self.assertFalse(entry.is_dir) + self.assertIsNone(entry.stat) + + if __name__ == "__main__": sys.exit(unittest.main())