--rDGr2BijA3 Content-Type: text/plain; charset=us-ascii Content-Description: message body text Content-Transfer-Encoding: 7bit At one point we discussed file system abstractions on this list. Do we want to pursue the idea? I have an implementation that's been tested on Unix: a Filesystem instance refers to either the entire "native" filesystem, or a subset of a filesystem (either a filesystem object or the native filesystem), based on a "root" that's a directory within the parent filesystem. There'd need to be some work done to make sure it works properly on Windows and the Mac, but I don't think that would be a lot of work. I think this should be available as an abstraction in Python. Implementing this on top of a ZIP/JAR file is also useful. If Jim A.'s zipfile.py will be added to the standard library in 1.6, I'd like to add a Filesystem class that operates on a zipfile object. Any thoughts? If you want this, someone needs to check in and document zipfile.py. ;) I'll add filesys.py & it's documentation. -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> Corporation for National Research Initiatives --rDGr2BijA3 Content-Type: text/x-python Content-Description: Filesystem abstraction for Python Content-Disposition: inline; filename="filesys.py" Content-Transfer-Encoding: 7bit """FilesystemAPI.Filesystem implementations. These aren't actually connected to ILU in any way. """ __version__ = '$Revision: 1.7 $' # This probably doesn't work anywhere that doesn't use Unix-style # pathnames. class Filesystem: def __init__(self, fs=None, root=None): if fs: self._fs = fs self._path = fs.path self._open = fs.open else: import os, __builtin__ self._fs = os self._path = os.path self._open = __builtin__.open self._cwd = self._fs.sep self.pardir = self._fs.pardir self.curdir = self._fs.curdir self.sep = self._fs.sep if root: self._root = root = self._path.abspath(root) self.path = SubsettingPath(self, self._path, root) else: self._root = '' self.path = SimplePath(self, self._path) def __getinitargs__(self): return (self._fs, self._root) def chdir(self, path): return self.__pathcall(self._fs.chdir, path) def fstat(self, file): try: return self._fs.fstat(file) except IOError, e: # make sure no filename information leaks out if hasattr(file, "name"): e.filename = file.name else: e.filename = None raise e def getcwd(self): return self._cwd def listdir(self, path): return self.__pathcall(self._fs.listdir, path) def lstat(self, path): return self.__pathcall(self._fs.lstat, path) def mkdir(self, path): self.__pathcall(self._fs.mkdir, path) def fopen(self, path, mode="r"): name = self.path._normpath(path) try: f = self._open(self._root + name, mode) except IOError, e: e.filename = path raise e if self._root: f = SubsettingFile(f, path, mode) return f def remove(self, path): return self.__pathcall(self._fs.remove, path) def rmdir(self, path): return self.__pathcall(self._fs.rmdir, path) def stat(self, path): return self.__pathcall(self._fs.stat, path) def unlink(self, path): return self.__pathcall(self._fs.unlink, path) def __pathcall(self, func, path): name = self.path._normpath(path) try: return func(self._root + name) except IOError, e: e.filename = path raise e class SubsettingFile: """Class used to mask a real file when the origin filesystem is being 'subsetted'. This avoids revealing the real file name without restricting the ability to use the file as a replacement sys.stdout (which needs softspace support). """ def __init__(self, file, path, mode): self.__dict__['_file'] = file self.__dict__['_mode'] = mode self.__dict__['_path'] = path self.__dict__['name'] = path def __getattr__(self, name): v = getattr(self._file, name) if callable(v) and not self.__dict__.has_key(name): v = SubsettingMethod(v, self._path).call self.__dict__[name] = v return v def __setattr__(self, name, value): setattr(self._file, name, value) def __repr__(self): oc = self._file.closed and "closed" or "open" return "<%s file %s, mode %s at %x>" \ % (oc, `self._path`, `self._mode`, id(self)) class SubsettingMethod: def __init__(self, method, path): self.method = method self.path = path def call(self, *args, **kw): try: return apply(self.method, args, kw) except IOError, e: e.filename = self.path raise e class BasePath: def __init__(self, fs, realpath): self._fs = fs self._path = realpath self._prefix = '' try: fs.stat(fs.curdir) self._have_stat = 1 except AttributeError: self._have_stat = 0 def __getattr__(self, name): v = getattr(self._path, name) setattr(self, name, v) return v def abspath(self, path): if not self.isabs(path): path = self._path.join(self._fs.getcwd(), path) return self.normpath(path) def basename(self, path): return self._path.basename(path) def commonprefix(self, list): return self._path.commonprefix(list) def dirname(self, path): return self._path.dirname(path) def exists(self, path): name = self._normpath(path) try: return self._path.exists(self._prefix + name) except IOError, e: e.filename = path raise e def isabs(self, path): return self._path.isabs(path) def isdir(self, path): name = self._normpath(path) try: return self._path.isdir(self._prefix + name) except IOError, e: e.filename = name raise e def isfile(self, path): name = self._normpath(path) try: return self._path.isfile(self._prefix + name) except IOError, e: e.filename = path raise e def join(self, *args): return apply(self._path.join, args) def normcase(self, path): return self._path.normcase(path) def normpath(self, path): return self._path.normpath(path) def samefile(self, path1, path2): """Return true if both pathname arguments refer to the same file or directory. If the underlying filesystem supports stat(), the comparison is made using samestat(), otherwise a simple string comparison is used. """ if self._have_stat: return self.samestat(self._fs.stat(path1), self._fs.stat(path2)) else: p1 = self._normpath(path1) p2 = self._normpath(path2) return p1 == p2 def sameopenfile(self, file1, file2): stat1 = self._fs.fstat(file1) stat2 = self._fs.fstat(file2) return self.samestat(stat1, stat2) def split(self, path): return self._path.split(path) def splitdrive(self, path): return self._path.splitdrive(path) def splitext(self, path): return self._path.splitext(path) def walk(self, root, func, arg): queue = [root] while queue: dir = queue[0] del queue[0] if self.isdir(dir): files = self._fs.listdir(dir) func(arg, dir, files) for file in files: path = self.join(dir, file) if self.isdir(path): queue.append(path) class SimplePath(BasePath): def __getinitargs__(self): return (self._fs, self._path) def _normpath(self, path): return self.abspath(path) class SubsettingPath(BasePath): """os.path equivalent that pretends some directory down in the tree is the root. This class works relative to a filesystem and path-math object that are passed to the constructor. """ def __init__(self, fs, realpath, prefix): BasePath.__init__(self, fs, realpath) self._prefix = prefix self._rootref = "%s%s%s" \ % (self._fs.sep, self._fs.pardir, self._fs.sep) def __getinitargs__(self): return (self._fs, self._path, self._prefix) def _normpath(self, path): """Return the absolute pathname for path, relative to the filesystem object.""" p = self.abspath(path) while p[:len(self._rootref)] == self._rootref: # on Unix, /.. refers to /, on Windows, \.. refers to \ (yech!) p = p[len(self._rootref) - len(self._fs.sep):] if not self.isabs(p): raise IOError(errno.ENOENT, "No such file or directory", path) return p --rDGr2BijA3--
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4