annotate cutils/util/walk.py @ 121:2dc26a2f3d1c

A heavily customized "os.walk()" alike to support the coming treeview implementation
author Franz Glasner <fzglas.hg@dom66.de>
date Wed, 01 Jan 2025 17:52:41 +0100
parents
children 4a0c3c9eead7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
121
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1 # -*- coding: utf-8 -*-
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
2 # :-
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
3 # :Copyright: (c) 2020-2025 Franz Glasner
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
4 # :License: BSD-3-Clause
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
5 # :-
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
6 r"""Utility sub-module to implement a heavily customized :func:`os.walk`.
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
7
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
8 """
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
9
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
10 __all__ = ["walk"]
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
11
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
12
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
13 import os
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
14 try:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
15 from os import scandir
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
16 except ImportError:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
17 try:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
18 from scandir import scandir
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
19 except ImportError:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
20 scandir = None
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
21 from contextlib import closing
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
22
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
23 from .cm import nullcontext
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
24 from .constants import PY2
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
25
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
26
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
27 class WalkDirEntry(object):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
28
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
29 """A :class:`os.DirEntry` alike to be used in :func:`walk` and for
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
30 its results.
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
31
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
32 """
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
33
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
34 __slots__ = ("_name", "_fsname", "_path", "_fspath", "_is_symlink",
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
35 "_is_dir", "_stat_result")
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
36
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
37 def __init__(self, name):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
38 self._name = name
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
39 if PY2:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
40 assert isinstance(name, bytes)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
41 self._fsname = name
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
42 else:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
43 self._fsname = os.fsencode(name)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
44 self._path = None
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
45 self._fspath = None
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
46 self._is_symlink = self._is_dir = self._stat_result = None
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
47
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
48 @property
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
49 def name(self):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
50 return self._name
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
51
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
52 @property
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
53 def fsname(self):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
54 return self._fsname
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
55
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
56 @property
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
57 def path(self):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
58 return self._path
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
59
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
60 @property
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
61 def fspath(self):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
62 if self._path is not None:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
63 if self._fspath is None:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
64 if PY2:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
65 assert isinstance(self._path, bytes)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
66 self._fspath = self._path
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
67 else:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
68 self._fspath = os.fsencode(self._path)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
69 return self._fspath
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
70
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
71 @property
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
72 def is_symlink(self):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
73 return self._is_symlink
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
74
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
75 @property
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
76 def is_dir(self):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
77 return self._is_dir
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
78
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
79 @property
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
80 def stat(self):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
81 return self._stat_result
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
82
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
83 def __repr__(self):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
84 tag = ""
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
85 if self._is_symlink:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
86 tag += "l"
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
87 if self._is_dir:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
88 tag += "d"
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
89 if tag:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
90 return "<WalkDirEntry %r (%s)>" % (self._name, tag)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
91 return "<WalkDirEntry %r>" % (self._name,)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
92
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
93 @classmethod
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
94 def from_direntry(cls_, entry):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
95 w = cls_(entry.name)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
96 w._path = entry.path
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
97 try:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
98 w._is_dir = entry.is_dir(follow_symlinks=True)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
99 except OSError:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
100 #
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
101 # If is_dir() raises an OSError, consider that the entry
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
102 # is not a directory, same behaviour than os.path.isdir().
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
103 #
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
104 w._is_dir = False
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
105 try:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
106 w._is_symlink = entry.is_symlink()
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
107 except OSError:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
108 #
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
109 # If is_symlink() raises an OSError, consider that the entry
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
110 # is not a symbolic link, same behaviour than os.path.islink().
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
111 #
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
112 w._is_symlink = False
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
113 if not w._is_dir:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
114 # Do not supress errors here and (consistently) follow symlinks
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
115 w._stat_result = entry.stat(follow_symlinks=True)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
116 return w
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
117
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
118 @staticmethod
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
119 def sort_key(entry):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
120 return entry._fsname
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
121
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
122
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
123 if scandir:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
124
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
125 def walk(root, follow_symlinks=False):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
126 """A heyvily customized :func:`os.walk` alike that differs from the
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
127 original:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
128
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
129 - optimized for use in :command:`treesum`
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
130 - most errors are not suppressed
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
131 - the `root` is never part of the returned data
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
132 - the returned directory in "top" is not a string form but a list of
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
133 individual path segments
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
134 - all other yielded lists contain WalkDirEntry elements instead of
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
135 strings
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
136 - recurse into sub-directories first ("topdown=False")
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
137 - sort consistently all yielded lists by the filesystem encoding
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
138
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
139 .. note:: The implementation is based on Python 3.11 and needs a
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
140 functional :func:`os.scandir` or :func:`scandir.scandir`
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
141 implementation. It intentionally follows the logic in
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
142 Python 3.11 while it could be simplified because we are not
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
143 implementing some of the original flags (e.g. like
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
144 `topdown`).
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
145
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
146 """
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
147 normed_root = os.path.normpath(root)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
148 yield from _walk(normed_root, tuple(), follow_symlinks=follow_symlinks)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
149
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
150
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
151 def _walk(root, top, follow_symlinks): # noqa: E303 too many empty lines
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
152 """:func:`walk` helper"""
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
153 if top:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
154 path = os.path.join(root, *top)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
155 else:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
156 path = root
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
157
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
158 dirs, nondirs, walk_dirs = [], [], []
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
159
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
160 scandir_it = scandir(path)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
161 if hasattr(scandir_it, "close"):
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
162 scandir_ctx = closing(scandir_it)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
163 else:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
164 scandir_ctx = nullcontext(scandir_it)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
165 with scandir_ctx as scandir_it:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
166 while True:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
167 try:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
168 entry = WalkDirEntry.from_direntry(next(scandir_it))
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
169 except StopIteration:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
170 break
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
171 if entry.is_dir:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
172 dirs.append(entry)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
173 else:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
174 nondirs.append(entry)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
175 #
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
176 # Always bottom-up: recurse into sub-directories, but exclude
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
177 # symlinks to directories if follow_symlinks is False
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
178 #
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
179 if entry.is_dir:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
180 if follow_symlinks:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
181 walk_into = True
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
182 else:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
183 walk_into = not entry.is_symlink
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
184 if walk_into:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
185 walk_dirs.append(entry)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
186
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
187 # Sort by low-level filesystem encoding
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
188 walk_dirs.sort(key=WalkDirEntry.sort_key)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
189 dirs.sort(key=WalkDirEntry.sort_key)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
190 nondirs.sort(key=WalkDirEntry.sort_key)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
191
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
192 # Recurse into sub-directories
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
193 for wd in walk_dirs:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
194 yield from _walk(root, top + (wd.name,), follow_symlinks)
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
195 # Yield after recursion if going bottom up
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
196 yield top, dirs, nondirs
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
197
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
198 else:
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
199
2dc26a2f3d1c A heavily customized "os.walk()" alike to support the coming treeview implementation
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
200 raise ImportError("no `scandir()' module available")