@@ -34,7 +34,7 @@ def always(self, message, *args, **kwargs):
3434logging .Logger .always = always
3535
3636
37- def handle_non_dir (entry , user_uid ):
37+ def _handle_non_dir_entry (entry , user_uid ):
3838 """
3939 Check if a non-directory entry is owned by the user and should be processed.
4040
@@ -60,6 +60,31 @@ def handle_non_dir(entry, user_uid):
6060 return None
6161
6262
63+ def handle_non_dir (var , user_uid ):
64+ """
65+ Check if a non-directory is owned by the user and should be processed. Passes var to a
66+ helper function depending on its type.
67+
68+ Args:
69+ var (os.DirEntry or str): A directory entry from os.scandir(), or a string path.
70+ user_uid (int): The UID of the user whose files to find.
71+
72+ Returns:
73+ str or None: The absolute path to the file if it's owned by the user
74+ and is a regular file (not a symlink), otherwise None.
75+ """
76+
77+ # Fall back to duck typing: If var has the required DirEntry methods and members, treat it as a
78+ # DirEntry. This is necessary for this conditional to work with the MockDirEntry type used in
79+ # testing. ("If it looks, walks, and quacks like a duck...")
80+ if isinstance (var , os .DirEntry ) or all (
81+ hasattr (var , m ) for m in ["stat" , "is_file" , "is_symlink" , "path" ]
82+ ):
83+ return _handle_non_dir_entry (var , user_uid )
84+
85+ raise TypeError (f"Unsure how to handle non-directory variable of type { type (var )} " )
86+
87+
6388def find_owned_files_scandir (directory , user_uid ):
6489 """
6590 Efficiently find all files owned by a specific user using os.scandir().
0 commit comments