965
def _cicp_canonical_relpath(base, path):
966
"""Return the canonical path relative to base.
968
Like relpath, but on case-insensitive-case-preserving file-systems, this
969
will return the relpath as stored on the file-system rather than in the
970
case specified in the input string, for all existing portions of the path.
972
This will cause O(N) behaviour if called for every path in a tree; if you
973
have a number of paths to convert, you should use canonical_relpaths().
975
# TODO: it should be possible to optimize this for Windows by using the
976
# win32 API FindFiles function to look for the specified name - but using
977
# os.listdir() still gives us the correct, platform agnostic semantics in
980
rel = relpath(base, path)
981
# '.' will have been turned into ''
985
abs_base = abspath(base)
987
_listdir = os.listdir
989
# use an explicit iterator so we can easily consume the rest on early exit.
990
bit_iter = iter(rel.split('/'))
993
for look in _listdir(current):
994
if lbit == look.lower():
995
current = pathjoin(current, look)
998
# got to the end, nothing matched, so we just return the
999
# non-existing bits as they were specified (the filename may be
1000
# the target of a move, for example).
1001
current = pathjoin(current, bit, *list(bit_iter))
1003
return current[len(abs_base)+1:]
1005
# XXX - TODO - we need better detection/integration of case-insensitive
1006
# file-systems; Linux often sees FAT32 devices, for example, so could
1007
# probably benefit from the same basic support there. For now though, only
1008
# Windows gets that support, and it gets it for *all* file-systems!
1009
if sys.platform == "win32":
1010
canonical_relpath = _cicp_canonical_relpath
1012
canonical_relpath = relpath
1014
def canonical_relpaths(base, paths):
1015
"""Create an iterable to canonicalize a sequence of relative paths.
1017
The intent is for this implementation to use a cache, vastly speeding
1018
up multiple transformations in the same directory.
1020
# but for now, we haven't optimized...
1021
return [canonical_relpath(base, p) for p in paths]
965
1023
def safe_unicode(unicode_or_utf8_string):
966
1024
"""Coerce unicode_or_utf8_string into unicode.