Commit 707f5ba7 by willmcgugan

Some fixes

parent f5dfa021
......@@ -211,7 +211,7 @@ class FS(object):
path -- Pach to check
"""
return self.getsyspath(path, None) is not None
return self.getsyspath(path, allow_none=True) is not None
def open(self, path, mode="r", **kwargs):
......@@ -492,11 +492,26 @@ class FS(object):
depth first search. Use 'depth' if you plan to create or
delete files as you go.
"""
for path, files in self.walk(path, wildcard, dir_wildcard, search):
for path, files in self.walk(path, wildcard=wildcard, dir_widlcard=dir_wildcard, search=search):
for f in files:
yield pathjoin(path, f)
def walkdirs(self, path="/", wildcard=None, search="breadth"):
""" Like the 'walk' method but yields directories.
path -- Root path to start walking
wildcard -- If given, only return dictories that match this wildcard
search -- A string dentifying the method used to walk the directories.
Can be 'breadth' for a breadth first search, or 'depth' for a
depth first search. Use 'depth' if you plan to create or
delete files as you go.
"""
for p, files in self.walk(path, wildcard=wildcard, search=search):
yield p
def getsize(self, path):
"""Returns the size (in bytes) of a resource.
......@@ -565,7 +580,7 @@ class FS(object):
src -- Source path
dst -- Destination path
overwrite -- If True, then an existing file at the destination path
will be silently overwritte; if False then an exception
will be silently overwritten; if False then an exception
will be raised in this case.
"""
......@@ -617,9 +632,9 @@ class FS(object):
except OSError:
pass
def movefile_noerrors(src, dst, overwrite, chunk_size):
def movefile_noerrors(src, dst, **kwargs):
try:
return self.move(src, dst, overwrite, chunk_size)
return self.move(src, dst, **kwargs)
except FSError:
return
if ignore_errors:
......@@ -627,10 +642,15 @@ class FS(object):
else:
movefile = self.move
src = abspath(src)
dst = abspath(dst)
if dst:
self.makedir(dst, allow_recreate=overwrite)
for dirname, filenames in self.walk(src, search="depth"):
dst_dirname = relpath(dirname[len(src):])
dst_dirname = relpath(frombase(src, abspath(dirname)))
dst_dirpath = pathjoin(dst, dst_dirname)
self.makedir(dst_dirpath, allow_recreate=True, recursive=True)
......@@ -657,9 +677,9 @@ class FS(object):
"""
if not self.isdir(src):
raise ResourceInvalidError(src, msg="Source is not a directory: %(path)s")
def copyfile_noerrors(src, dst, overwrite):
def copyfile_noerrors(src, dst, **kwargs):
try:
return self.copy(src, dst, overwrite=overwrite)
return self.copy(src, dst, **kwargs)
except FSError:
return
if ignore_errors:
......@@ -667,14 +687,17 @@ class FS(object):
else:
copyfile = self.copy
copyfile = self.copy
src = abspath(src)
dst = abspath(dst)
if dst:
self.makedir(dst, allow_recreate=overwrite)
for dirname, filenames in self.walk(src):
dst_dirname = relpath(dirname[len(src):])
dst_dirname = relpath(frombase(src, abspath(dirname)))
dst_dirpath = pathjoin(dst, dst_dirname)
self.makedir(dst_dirpath, allow_recreate=True)
self.makedir(dst_dirpath, allow_recreate=True, recursive=True)
for filename in filenames:
......@@ -724,7 +747,7 @@ class SubFS(FS):
def __init__(self, parent, sub_dir):
self.parent = parent
self.sub_dir = abspath(normpath(sub_dir))
FS.__init__(self,thread_synchronize=False)
FS.__init__(self, thread_synchronize=False)
def __str__(self):
return "<SubFS: %s in %s>" % (self.sub_dir, self.parent)
......
......@@ -52,6 +52,15 @@ class MountFS(FS):
return self, head_path, tail_path
def getsyspath(self, path, allow_none=False):
fs, mount_path, delegate_path = self._delegate(path)
if fs is self:
if allow_none:
return None
else:
raise NoSysPathError(path=path)
return fs.getsyspath(delegate_path, allow_none=allow_none)
@synchronize
def desc(self, path):
fs, mount_path, delegate_path = self._delegate(path)
......@@ -309,5 +318,3 @@ class MountFS(FS):
if fs is self:
return []
return fs.listxattrs(delegate_path)
......@@ -178,7 +178,7 @@ def issamedir(path1, path2):
return pathsplit(normpath(path1))[0] == pathsplit(normpath(path2))[0]
def isprefix(path1,path2):
def isprefix(path1, path2):
"""Return true is path1 is a prefix of path2.
>>> isprefix("foo/bar", "foo/bar/spam.txt")
......@@ -203,6 +203,20 @@ def isprefix(path1,path2):
return True
def forcedir(path):
"""Ensure the path ends with a trailing /
>>> forcedir("foo/bar")
'foo/bar/'
>>> forcedir("foo/bar/")
'foo/bar/'
"""
if not path.endswith('/'):
return path + '/'
return path
def frombase(path1, path2):
if not isprefix(path1, path2):
raise ValueError("path1 must be a prefix of path2")
return path2[len(path1):]
......@@ -6,6 +6,7 @@
import shutil
from fs.mountfs import MountFS
from fs.path import pathjoin
def copyfile(src_fs, src_path, dst_fs, dst_path, chunk_size=16384):
"""Copy a file from one filesystem to another. Will use system copyfile, if both files have a syspath.
......@@ -18,11 +19,11 @@ def copyfile(src_fs, src_path, dst_fs, dst_path, chunk_size=16384):
chunk_size -- Size of chunks to move if system copyfile is not available (default 16K)
"""
src_syspath = src_fs.getsyspath(src_path) or ""
dst_syspath = dst_fs.getsyspath(dst_path) or ""
src_syspath = src_fs.getsyspath(src_path, allow_none=True)
dst_syspath = dst_fs.getsyspath(dst_path, allow_none=True)
# System copy if there are two sys paths
if src_syspath and dst_syspath:
if src_syspath is not None and dst_syspath is not None:
shutil.copyfile(src_syspath, dst_syspath)
return
......@@ -57,11 +58,11 @@ def movefile(src_fs, src_path, dst_fs, dst_path, chunk_size=16384):
chunk_size -- Size of chunks to move if system copyfile is not available (default 16K)
"""
src_syspath = src_fs.getsyspath(src_path) or ""
dst_syspath = dst_fs.getsyspath(dst_path) or ""
src_syspath = src_fs.getsyspath(src_path, allow_none=True)
dst_syspath = dst_fs.getsyspath(dst_path, allow_none=True)
# System copy if there are two sys paths
if src_syspath and dst_syspath:
if src_syspath is not None and dst_syspath is not None:
shutil.movefile(src_syspath, dst_syspath)
return
......@@ -87,7 +88,7 @@ def movefile(src_fs, src_path, dst_fs, dst_path, chunk_size=16384):
dst.close()
def movedir(fs1, fs2, ignore_errors=False, chunk_size=16384):
def movedir(fs1, fs2, overwrite=False, ignore_errors=False, chunk_size=16384):
"""Moves contents of a directory from one filesystem to another.
fs1 -- Source filesystem, or a tuple of (<filesystem>, <directory path>)
......@@ -104,12 +105,16 @@ def movedir(fs1, fs2, ignore_errors=False, chunk_size=16384):
fs2 = fs2.opendir(dir2)
mount_fs = MountFS()
mount_fs.mount('dir1', fs1)
mount_fs.mount('dir2', fs2)
mount_fs.movedir('dir1', 'dir2', ignore_errors=ignore_errors, chunk_size=chunk_size)
mount_fs.mount('src', fs1)
mount_fs.mount('dst', fs2)
mount_fs.movedir('src', 'dst',
overwrite=overwrite,
ignore_errors=ignore_errors,
chunk_size=chunk_size)
def copydir(fs1, fs2, ignore_errors=False, chunk_size=16384):
def copydir(fs1, fs2, overwrite=False, ignore_errors=False, chunk_size=16384):
"""Copies contents of a directory from one filesystem to another.
fs1 -- Source filesystem, or a tuple of (<filesystem>, <directory path>)
......@@ -126,9 +131,12 @@ def copydir(fs1, fs2, ignore_errors=False, chunk_size=16384):
fs2 = fs2.opendir(dir2)
mount_fs = MountFS()
mount_fs.mount('dir1', fs1)
mount_fs.mount('dir2', fs2)
mount_fs.copydir('dir1', 'dir2', ignore_errors=ignore_errors, chunk_size=chunk_size)
mount_fs.mount('src', fs1)
mount_fs.mount('dst', fs2)
mount_fs.copydir('src', 'dst',
overwrite=overwrite,
ignore_errors=ignore_errors,
chunk_size=chunk_size)
def countbytes(fs):
......@@ -244,6 +252,40 @@ def find_duplicates(fs, compare_paths=None, quick=False, signature_chunk_size=16
paths = list(set(paths).difference(dups))
def print_fs(fs, path="/", max_levels=5, indent=' '*2):
"""Prints a filesystem listing to stdout (including sub dirs). Useful as a debugging aid.
Be careful about printing a OSFS, or any other large filesystem.
Without max_levels set, this function will traverse the entire directory tree.
fs -- A filesystem object
path -- Path of root to list (default "/")
max_levels -- Maximum levels of dirs to list (default 5), set to None for no maximum
indent -- String to indent each directory level (default two spaces)
"""
def print_dir(fs, path, level):
try:
dir_listing = [(fs.isdir(pathjoin(path,p)), p) for p in fs.listdir(path)]
except Exception, e:
print indent*level + "... unabled to retrieve directory list (reason: %s) ..." % str(e)
return
dir_listing.sort(key = lambda (isdir, p):(not isdir, p.lower()))
for is_dir, item in dir_listing:
if is_dir:
print indent*level + '[%s]' % item
if max_levels is None or level < max_levels:
print_dir(fs, pathjoin(path, item), level+1)
if max_levels is not None:
if level >= max_levels:
print indent*(level+1) + "..."
else:
print indent*level + '%s' % item
print_dir(fs, path, 0)
if __name__ == "__main__":
from osfs import *
fs = OSFS('~/copytest')
......@@ -256,4 +298,3 @@ if __name__ == "__main__":
from browsewin import browse
browse(m)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment