Commit f92af63f by willmcgugan

Added getmeta and hasmeta methods

parent bc9437bf
......@@ -59,4 +59,5 @@
the info dict and avoid an additional query to the filesystem.
* Added utility module 'fs.filelike' with some helpers for building and
manipulating file-like objects.
* Added getmeta and hasmeta methods
......@@ -133,6 +133,8 @@ class FS(object):
"""
_meta = {}
def __init__(self, thread_synchronize=False):
"""The base class for Filesystem objects.
......@@ -186,6 +188,33 @@ class FS(object):
else:
self._lock = DummyLock()
def getmeta(self, meta_name, default=Ellipsis):
"""Retrieve a meta value associated with the FS object
:param meta_name: The name of the meta value to retrieve
:param default: An option default to return, if the meta value isn't present
:raises NoMetaError: If specified meta value is not present, and there is no default
"""
if meta_name not in self._meta:
if default is not Ellipsis:
return default
raise NoMetaError(meta_name=meta_name)
return self._meta[meta_name]
def hasmeta(self, meta_name):
"""Check that a meta value is supported
:param meta_name: The name of a meta value to check
:rtype: bool
"""
try:
self.getmeta('meta_name')
except NoMetaError:
return False
return True
def getsyspath(self, path, allow_none=False):
"""Returns the system path (a path recognised by the OS) if present.
......
......@@ -157,6 +157,12 @@ class BigFS(FS):
"""A FileSystem that represents a BIG file."""
_meta = { 'virtual' : False,
'read_only' : True,
'unicode_paths' : True,
'case_insensitive_paths' : False,
}
def __init__(self, filename, mode="r", thread_synchronize=True):
"""Create a FS that maps on to a big file.
......
......@@ -73,6 +73,12 @@ class DAVFS(FS):
"https": httplib.HTTPSConnection,
}
_meta = { 'virtual' : False,
'read_only' : False,
'unicode_paths' : True,
'case_insensitive_paths' : False,
}
def __init__(self,url,credentials=None,get_credentials=None,thread_synchronize=True,connection_classes=None,timeout=None):
"""DAVFS constructor.
......
......@@ -75,6 +75,14 @@ def _fix_path(func):
return wrapper
class TahoeFS(CacheFS):
_meta = { 'virtual' : False,
'read_only' : False,
'unicode_paths' : True,
'case_insensitive_paths' : False,
'may_block' : False
}
def __init__(self, dircap, timeout=60, autorun=True, largefilesize=10*1024*1024, webapi='http://127.0.0.1:3456'):
'''
Creates instance of TahoeFS.
......
......@@ -20,6 +20,7 @@ __all__ = ['FSError',
'OperationTimeoutError',
'ResourceError',
'NoSysPathError',
'NoMetaError',
'NoPathURLError',
'ResourceNotFoundError',
'ResourceInvalidError',
......@@ -131,6 +132,14 @@ class NoSysPathError(ResourceError):
default_message = "No mapping to OS filesystem: %(path)s"
class NoMetaError(FSError):
"""Exception raised when there is no meta value available."""
default_message = "No meta value named '%(meta_name)s' could be retrieved"
def __init__(self, meta_name, msg=None):
self.meta_name = meta_name
super(NoMetaError, self).__init__(msg)
class NoPathURLError(ResourceError):
"""Exception raised when there is no URL form for a given path."""
default_message = "No URL form: %(path)s"
......
......@@ -737,6 +737,13 @@ class FTPFS(FS):
_locals = threading.local()
_meta = { 'virtual': False,
'read_only' : False,
'unicode_paths' : True,
'case_insensitive_paths' : False,
'may_block' : True
}
def __init__(self, host='', user='', passwd='', acct='', timeout=_GLOBAL_DEFAULT_TIMEOUT,
port=21,
dircache=True,
......
......@@ -184,6 +184,12 @@ class MemoryFS(FS):
"""
_meta = { 'virtual': False,
'read_only' : False,
'unicode_paths' : True,
'case_insensitive_paths' : False
}
def _make_dir_entry(self, *args, **kwargs):
return self.dir_entry_factory(*args, **kwargs)
......
......@@ -68,6 +68,13 @@ class FileMount(object):
class MountFS(FS):
"""A filesystem that delegates to other filesystems."""
_meta = { 'virtual': True,
'read_only' : False,
'unicode_paths' : True,
'case_insensitive_paths' : False
}
DirMount = DirMount
FileMount = FileMount
......
......@@ -69,6 +69,12 @@ class MultiFS(FS):
dirs of its children.
"""
_meta = { 'virtual': True,
'read_only' : False,
'unicode_paths' : True,
'case_insensitive_paths' : False
}
def __init__(self):
super(MultiFS, self).__init__(thread_synchronize=_thread_synchronize_default)
......
......@@ -14,6 +14,7 @@ For example, to print all the files and directories in the OS root::
import os
import os.path
import sys
import errno
import datetime
......@@ -72,6 +73,12 @@ class OSFS(OSFSXAttrMixin, OSFSWatchMixin, FS):
methods in the os and os.path modules.
"""
_meta = { 'virtual' : False,
'read_only' : False,
'unicode_paths' : os.path.supports_unicode_filenames,
'case_insensitive_paths' : os.path.normcase('Aa') == 'aa',
}
def __init__(self, root_path, thread_synchronize=_thread_synchronize_default, encoding=None, create=False, dir_mode=0700):
"""
Creates an FS object that represents the OS Filesystem under a given root path
......
......@@ -88,6 +88,13 @@ class RPCFS(FS):
"""
_meta = { 'virtual': False,
'read_only' : False,
'unicode_paths' : True,
'case_insensitive_paths' : False,
'may_block' : True,
}
def __init__(self, uri, transport=None):
"""Constructor for RPCFS objects.
......
......@@ -56,6 +56,13 @@ class S3FS(FS):
or flushed.
"""
_meta = { 'virtual': False,
'read_only' : False,
'unicode_paths' : True,
'case_insensitive_paths' : False,
'may_block' : True,
}
class meta:
PATH_MAX = None
NAME_MAX = None
......
......@@ -43,8 +43,16 @@ class SFTPFS(FS):
This is basically a compatability wrapper for the excellent SFTPClient
class in the paramiko module.
"""
_meta = { 'virtual': False,
'read_only' : False,
'unicode_paths' : True,
'case_insensitive_paths' : False,
'may_block' : True,
}
def __init__(self, connection, root_path="/", encoding=None, **credentials):
"""SFTPFS constructor.
......
......@@ -20,6 +20,12 @@ class TempFS(OSFS):
"""Create a Filesystem in a tempory directory (with tempfile.mkdtemp),
and removes it when the TempFS object is cleaned up."""
_meta = { 'virtual' : False,
'read_only' : False,
'unicode_paths' : os.path.supports_unicode_filenames,
'case_insensitive_paths' : os.path.normcase('Aa') == 'aa',
}
def __init__(self, identifier=None, temp_dir=None, dir_mode=0700, thread_synchronize=_thread_synchronize_default):
"""Creates a temporary Filesystem
......
......@@ -118,6 +118,14 @@ class WrapFS(FS):
return (mode,mode)
@rewrite_errors
def getmeta(self, meta_name, default=Ellipsis):
return self.wrapped_fs.getmeta(meta_name, default)
@rewrite_errors
def hasmeta(self, meta_name):
return self.wrapped_fs.hasmeta(meta_name)
@rewrite_errors
def getsyspath(self, path, allow_none=False):
return self.wrapped_fs.getsyspath(self._encode(path),allow_none)
......
......@@ -20,6 +20,16 @@ class ReadOnlyFS(WrapFS):
"""
def getmeta(self, meta_name, default=Ellipsis):
if meta_name == 'read_only':
return True
return self.wrapped_fs(meta_name, default)
def hasmeta(self, meta_name):
if meta_name == 'read_only':
return True
return self.wrapped_fs(meta_name)
def getsyspath(self, path, allow_none=False):
""" Doesn't technically modify the filesystem but could be used to work
around read-only restrictions. """
......
......@@ -7,6 +7,7 @@ A FS object that represents the contents of a Zip file
"""
import datetime
import os.path
from fs.base import *
from fs.path import *
......@@ -68,6 +69,12 @@ class ZipFS(FS):
"""A FileSystem that represents a zip file."""
_meta = { 'virtual' : False,
'read_only' : False,
'unicode_paths' : os.path.supports_unicode_filenames,
'case_insensitive_paths' : os.path.normcase('Aa') == 'aa',
}
def __init__(self, zip_file, mode="r", compression="deflated", allow_zip_64=False, encoding="CP437", thread_synchronize=True):
"""Create a FS that maps on to a zip file.
......@@ -116,6 +123,8 @@ class ZipFS(FS):
if mode in 'ra':
self._parse_resource_list()
self._meta['read_only'] = self.zip_mode != 'w'
def __str__(self):
return "<ZipFS: %s>" % self.zip_path
......@@ -138,7 +147,6 @@ class ZipFS(FS):
f = self._path_fs.open(path, 'w')
f.close()
def close(self):
"""Finalizes the zip file so that it can be read.
No further operations will work after this method is called."""
......
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