diff cutils/util/walk.py @ 266:0add8276e6b8

treesum: Handle errors like broken symlinks properly
author Franz Glasner <fzglas.hg@dom66.de>
date Tue, 18 Feb 2025 12:39:04 +0100
parents 188f448ab5e9
children c02a57df2a29
line wrap: on
line diff
--- a/cutils/util/walk.py	Mon Feb 17 00:12:33 2025 +0100
+++ b/cutils/util/walk.py	Tue Feb 18 12:39:04 2025 +0100
@@ -53,7 +53,8 @@
     """
 
     __slots__ = ("_name", "_path",     # encoded as given in the ctor
-                 "_is_symlink", "_is_dir", "_stat_result",
+                 "_is_symlink", "_is_dir", "_stat_result", "_stat_errno",
+                 "_stat_errstr",
                  "_alt_fsname", "_alt_u8name")
 
     def __init__(self, name, path):
@@ -61,7 +62,8 @@
         """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 = None
+        self._is_symlink = self._is_dir = self._stat_result = \
+            self._stat_errno = self._stat_errstr = None
         self._alt_fsname = self._alt_u8name = _notset
 
     @property
@@ -232,6 +234,14 @@
     def stat(self):
         return self._stat_result
 
+    @property
+    def stat_errno(self):
+        return self._stat_errno
+
+    @property
+    def stat_errstr(self):
+        return self._stat_errstr
+
     def __repr__(self):
         tag = ""
         if self._is_symlink:
@@ -261,8 +271,13 @@
             # is not a symbolic link, same behaviour than os.path.islink().
             #
             w._is_symlink = False
-        # Do not supress errors here and (consistently) follow symlinks
-        w._stat_result = entry.stat(follow_symlinks=True)
+        # Consistently follow symlinks
+        try:
+            w._stat_result = entry.stat(follow_symlinks=True)
+        except OSError as e:
+            w._stat_result = None
+            w._stat_errno = e.errno
+            w._stat_errstr = e.strerror
         return w
 
     @classmethod
@@ -286,7 +301,12 @@
             #
             w._is_symlink = False
         if _do_stat:
-            w._stat_result = os.stat(w._path)
+            try:
+                w._stat_result = os.stat(w._path)
+            except OSError as e:
+                w._stat_result = None
+                w._stat_errno = e.errno
+                w._stat_errstr = e.strerror
         return w
 
     @classmethod