summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrfkelly0 <rfkelly0@67cdc799-7952-0410-af00-57a81ceafa0f>2009-05-05 06:02:48 +0000
committerrfkelly0 <rfkelly0@67cdc799-7952-0410-af00-57a81ceafa0f>2009-05-05 06:02:48 +0000
commite3e5919d40cf9a5f145dc2e3d5cf6e6d8f3e3ed5 (patch)
tree4c51dffe4edf26ebb94a1dc9832483371de2764d
parent51a81b318719b480c0211f9dbba33859a120dd49 (diff)
downloadpyfilesystem-e3e5919d40cf9a5f145dc2e3d5cf6e6d8f3e3ed5.tar.gz
Condense and cleanup helpers.py/utils.py
git-svn-id: http://pyfilesystem.googlecode.com/svn/branches/rfk-ideas@126 67cdc799-7952-0410-af00-57a81ceafa0f
-rw-r--r--fs/helpers.py144
-rw-r--r--fs/utils.py9
2 files changed, 96 insertions, 57 deletions
diff --git a/fs/helpers.py b/fs/helpers.py
index 23e0ef4..7d86ba2 100644
--- a/fs/helpers.py
+++ b/fs/helpers.py
@@ -1,47 +1,91 @@
-"""Contains a number of standalone functions for path manipulation."""
+"""
+
+ fs.helpers: useful standalone functions for FS path manipulation.
+
+"""
from itertools import chain
-def _iteratepath(path, numsplits=None):
- path = resolvepath(path)
+def iteratepath(path, numsplits=None):
+ """Iterate over the individual components of a path."""
+ path = normpath(path)
if not path:
return []
-
+ if path[0] == "/":
+ path = path[1:]
if numsplits == None:
- return filter(lambda p:bool(p), path.split('/'))
+ return path.split('/')
else:
- return filter(lambda p:bool(p), path.split('/', numsplits))
+ return path.split('/', numsplits)
+def normpath(path):
+ """Normalizes a path to be in the format expected by FS objects.
-def isabsolutepath(path):
- """Returns True if a given path is absolute.
+ This function remove any leading or trailing slashes, collapses
+ duplicate slashes, replaces forward with backward slashes, and generally
+ tries very hard to return a new path string the canonical FS format.
+ If the path is invalid, ValueError will be raised.
- >>> isabsolutepath("a/b/c")
- False
+ >>> normpath(r"foo\\bar\\baz")
+ 'foo/bar/baz'
- >>> isabsolutepath("/foo/bar")
- True
+ >>> normpath("/foo//bar/frob/../baz")
+ '/foo/bar/baz'
+
+ >>> normpath("foo/../../bar")
+ Traceback (most recent call last)
+ ...
+ ValueError: too many backrefs in path 'foo/../../bar'
"""
- if path:
- return path[0] in '\\/'
- return False
+ if not path:
+ return path
-def normpath(path):
- """Normalizes a path to be in the formated expected by FS objects.
- Returns a new path string.
+ components = []
+ for comp in path.replace('\\','/').split("/"):
+ if not comp or comp == ".":
+ pass
+ elif comp == "..":
+ try:
+ components.pop()
+ except IndexError:
+ err = "too many backrefs in path '%s'" % (path,)
+ raise ValueError(err)
+ else:
+ components.append(comp)
- >>> normpath(r"foo\\bar\\baz")
- 'foo/bar/baz'
+ if path[0] in "\\/":
+ components.insert(0,"")
+
+ return "/".join(components)
+
+
+def abspath(path):
+ """Convert the given path to a normalized, absolute path.
+ path -- A FS path
"""
- return path.replace('\\', '/')
+ path = normpath(path)
+ if not path or path[0] != "/":
+ path = "/" + path
+ return path
+
+
+def relpath(path):
+ """Convert the given path to a normalized, relative path.
+
+ path -- A FS path
+ """
+ path = normpath(path)
+ if path and path[0] == "/":
+ path = path[1:]
+ return path
def pathjoin(*paths):
- """Joins any number of paths together. Returns a new path string.
+ """Joins any number of paths together, returning a new path string.
paths -- An iterable of path strings
@@ -51,39 +95,32 @@ def pathjoin(*paths):
>>> pathjoin('foo/bar', '../baz')
'foo/baz'
+ >>> pathjoin('foo/bar', '/baz')
+ '/baz'
+
"""
absolute = False
relpaths = []
for p in paths:
if p:
- if p[0] in '\\/':
- del relpaths[:]
- absolute = True
- relpaths.append(p)
-
- pathstack = []
-
- for component in chain(*(normpath(path).split('/') for path in relpaths)):
- if component == "..":
- if not pathstack:
- raise ValueError("Relative path is invalid")
- sub = pathstack.pop()
- elif component == ".":
- pass
- elif component:
- pathstack.append(component)
+ if p[0] in '\\/':
+ del relpaths[:]
+ absolute = True
+ relpaths.append(p)
+ path = normpath("/".join(relpaths))
if absolute:
- return "/" + "/".join(pathstack)
- else:
- return "/".join(pathstack)
+ path = "/" + path
+ return path
def pathsplit(path):
"""Splits a path on a path separator. Returns a tuple containing the path up
to that last separator and the remaining path component.
+ path -- A FS path
+
>>> pathsplit("foo/bar")
('foo', 'bar')
@@ -91,12 +128,12 @@ def pathsplit(path):
('foo/bar', 'baz')
"""
-
split = normpath(path).rsplit('/', 1)
if len(split) == 1:
return ('', split[0])
return tuple(split)
+
def dirname(path):
"""Returns the parent directory of a path.
@@ -108,6 +145,7 @@ def dirname(path):
"""
return pathsplit(path)[0]
+
def resourcename(path):
"""Returns the resource references by a path.
@@ -119,21 +157,11 @@ def resourcename(path):
"""
return pathsplit(path)[1]
-def resolvepath(path):
- """Normalises the path and removes any relative path components.
-
- path -- A path string
-
- >>> resolvepath(r"foo\\bar\\..\\baz")
- 'foo/baz'
-
- """
- return pathjoin(path)
def makerelative(path):
"""Makes a path relative by removing initial separator.
- path -- A path
+ path -- A FS path
>>> makerelative("/foo/bar")
'foo/bar'
@@ -144,10 +172,11 @@ def makerelative(path):
return path[1:]
return path
+
def makeabsolute(path):
- """Makes a path absolute by adding a separater at the beginning of the path.
+ """Makes a path absolute by adding a separator at the start of the path.
- path -- A path
+ path -- A FS path
>>> makeabsolute("foo/bar/baz")
'/foo/bar/baz'
@@ -158,6 +187,7 @@ def makeabsolute(path):
return '/'+path
return path
+
def issamedir(path1, path2):
"""Return true if two paths reference a resource in the same directory.
@@ -169,4 +199,6 @@ def issamedir(path1, path2):
>>> issamedir("foo/bar/baz/txt", "spam/eggs/spam.txt")
False
"""
- return pathsplit(resolvepath(path1))[0] == pathsplit(resolvepath(path2))[0]
+ return pathsplit(normpath(path1))[0] == pathsplit(normpath(path2))[0]
+
+
diff --git a/fs/utils.py b/fs/utils.py
index dd863eb..85fa464 100644
--- a/fs/utils.py
+++ b/fs/utils.py
@@ -1,4 +1,8 @@
-"""Contains a number of high level utility functions for working with FS objects."""
+"""
+
+ fs.utils: high level utility functions for working with FS objects.
+
+"""
import shutil
from mountfs import MountFS
@@ -82,6 +86,7 @@ def movefile(src_fs, src_path, dst_fs, dst_path, chunk_size=16384):
if dst is not None:
dst.close()
+
def movedir(fs1, fs2, ignore_errors=False, chunk_size=16384):
"""Moves contents of a directory from one filesystem to another.
@@ -103,6 +108,7 @@ def movedir(fs1, fs2, ignore_errors=False, chunk_size=16384):
mount_fs.mount('dir2', fs2)
mount_fs.movedir('dir1', 'dir2', ignore_errors=ignore_errors, chunk_size=chunk_size)
+
def copydir(fs1, fs2, ignore_errors=False, chunk_size=16384):
"""Copies contents of a directory from one filesystem to another.
@@ -124,6 +130,7 @@ def copydir(fs1, fs2, ignore_errors=False, chunk_size=16384):
mount_fs.mount('dir2', fs2)
mount_fs.copydir('dir1', 'dir2', ignore_errors=ignore_errors, chunk_size=chunk_size)
+
def countbytes(count_fs):
"""Returns the total number of bytes contained within files in a filesystem.