1101
1101
# depending on top and prefix - i.e. ./foo and foo as a pair leads to
1102
1102
# potentially confusing output. We should make this more robust - but
1103
1103
# not at a speed cost. RBC 20060731
1106
1105
_directory = _directory_kind
1107
1106
_listdir = os.listdir
1108
pending = [(prefix, "", _directory, None, top)]
1107
_kind_from_mode = _formats.get
1108
pending = [(safe_unicode(prefix), "", _directory, None, safe_unicode(top))]
1111
currentdir = pending.pop()
1112
1110
# 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1115
relroot = currentdir[0] + '/'
1118
for name in sorted(_listdir(top)):
1119
abspath = top + '/' + name
1120
statvalue = lstat(abspath)
1121
dirblock.append((relroot + name, name,
1122
file_kind_from_stat_mode(statvalue.st_mode),
1123
statvalue, abspath))
1124
yield (currentdir[0], top), dirblock
1125
# push the user specified dirs from dirblock
1126
for dir in reversed(dirblock):
1127
if dir[2] == _directory:
1111
relroot, _, _, _, top = pending.pop()
1113
relprefix = relroot + u'/'
1116
top_slash = top + u'/'
1119
append = dirblock.append
1120
for name in sorted(_listdir(top)):
1121
abspath = top_slash + name
1122
statvalue = _lstat(abspath)
1123
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1124
append((relprefix + name, name, kind, statvalue, abspath))
1125
yield (relroot, top), dirblock
1127
# push the user specified dirs from dirblock
1128
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1131
def _walkdirs_utf8(top, prefix=""):
1132
"""Yield data about all the directories in a tree.
1134
This yields the same information as walkdirs() only each entry is yielded
1135
in utf-8. On platforms which have a filesystem encoding of utf8 the paths
1136
are returned as exact byte-strings.
1138
:return: yields a tuple of (dir_info, [file_info])
1139
dir_info is (utf8_relpath, path-from-top)
1140
file_info is (utf8_relpath, utf8_name, kind, lstat, path-from-top)
1141
if top is an absolute path, path-from-top is also an absolute path.
1142
path-from-top might be unicode or utf8, but it is the correct path to
1143
pass to os functions to affect the file in question. (such as os.lstat)
1145
fs_encoding = sys.getfilesystemencoding()
1146
if (sys.platform == 'win32' or
1147
fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968')): # ascii
1148
return _walkdirs_unicode_to_utf8(top, prefix=prefix)
1150
return _walkdirs_fs_utf8(top, prefix=prefix)
1153
def _walkdirs_fs_utf8(top, prefix=""):
1154
"""See _walkdirs_utf8.
1156
This sub-function is called when we know the filesystem is already in utf8
1157
encoding. So we don't need to transcode filenames.
1160
_directory = _directory_kind
1161
_listdir = os.listdir
1162
_kind_from_mode = _formats.get
1164
# 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1165
# But we don't actually uses 1-3 in pending, so set them to None
1166
pending = [(safe_utf8(prefix), None, None, None, safe_utf8(top))]
1168
relroot, _, _, _, top = pending.pop()
1170
relprefix = relroot + '/'
1173
top_slash = top + '/'
1176
append = dirblock.append
1177
for name in sorted(_listdir(top)):
1178
abspath = top_slash + name
1179
statvalue = _lstat(abspath)
1180
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1181
append((relprefix + name, name, kind, statvalue, abspath))
1182
yield (relroot, top), dirblock
1184
# push the user specified dirs from dirblock
1185
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1188
def _walkdirs_unicode_to_utf8(top, prefix=""):
1189
"""See _walkdirs_utf8
1191
Because Win32 has a Unicode api, all of the 'path-from-top' entries will be
1193
This is currently the fallback code path when the filesystem encoding is
1194
not UTF-8. It may be better to implement an alternative so that we can
1195
safely handle paths that are not properly decodable in the current
1198
_utf8_encode = codecs.getencoder('utf8')
1200
_directory = _directory_kind
1201
_listdir = os.listdir
1202
_kind_from_mode = _formats.get
1204
pending = [(safe_utf8(prefix), None, None, None, safe_unicode(top))]
1206
relroot, _, _, _, top = pending.pop()
1208
relprefix = relroot + '/'
1211
top_slash = top + u'/'
1214
append = dirblock.append
1215
for name in sorted(_listdir(top)):
1216
name_utf8 = _utf8_encode(name)[0]
1217
abspath = top_slash + name
1218
statvalue = _lstat(abspath)
1219
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1220
append((relprefix + name_utf8, name_utf8, kind, statvalue, abspath))
1221
yield (relroot, top), dirblock
1223
# push the user specified dirs from dirblock
1224
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1131
1227
def copy_tree(from_path, to_path, handlers={}):