diff options
author | Sascha Silbe <sascha-pgp@silbe.org> | 2013-03-04 10:34:08 (GMT) |
---|---|---|
committer | Sascha Silbe <sascha-pgp@silbe.org> | 2013-06-01 09:12:20 (GMT) |
commit | b5e8739ab65e0ea9d903a2a6900ea4277554b4ed (patch) | |
tree | c211a686664770960febf83402c75d453bff2551 | |
parent | 128791e7b7a91d85062d249ed764e78ec9be8eb7 (diff) |
fsemulation: set ctime / mtime on object symlinks according to object
Setting ctime and mtime on object symlinks to the values of the object
itself enables sorting directories of symlinks (e.g. by-title)
by time.
-rw-r--r-- | fsemulation.py | 95 |
1 files changed, 65 insertions, 30 deletions
diff --git a/fsemulation.py b/fsemulation.py index f0bb7d5..5077265 100644 --- a/fsemulation.py +++ b/fsemulation.py @@ -486,7 +486,7 @@ class FSEntry(object): self._ds = file_system.data_store self.mode = mode - def get_properties(self, names=None): + def get_properties(self, names=None, use_cache=False): """Read the given properties (default: all) Returns a dictionary with unicode strings as keys and values. @@ -573,13 +573,64 @@ class Symlink(FSEntry): return 'Symlink(%r, %r)' % (self._fs, self.target) -class DSObject(FSEntry): - def __init__(self, file_system, object_id): - FSEntry.__init__(self, file_system, stat.S_IFREG | 0750) +class DSObjectBase(FSEntry): + def __init__(self, file_system, mode, object_id, metadata=None): + FSEntry.__init__(self, file_system, mode) self.object_id = object_id + self._metadata = metadata + self._have_nonstandard = False + + def get_properties(self, names=None, use_cache=False): + nonstandard_names = bool([True for name in names + if name not in _USEFUL_PROPS]) + if names and not nonstandard_names: + fetch_names = names + else: + fetch_names = None + if ((not use_cache) or (self._metadata is None) or + (nonstandard_names and not self._have_nonstandard)): + self._metadata = self._ds.get_properties(self.object_id, + fetch_names) + self._have_nonstandard = nonstandard_names + + if not names: + return self._metadata + return dict([(name, self._metadata[name]) + for name in names + if name in self._metadata]) + + def get_ctime(self): + props = self.get_properties([u'creation_time', u'timestamp']) + try: + return float(props[u'creation_time']) + except (KeyError, ValueError, TypeError): + pass + + try: + return float(props[u'timestamp']) + except (KeyError, ValueError, TypeError): + return time.time() + + def get_mtime(self): + props = self.get_properties([u'creation_time', u'timestamp']) + try: + return float(props[u'timestamp']) + except (KeyError, ValueError, TypeError): + return time.time() + + +class ObjectSymlink(Symlink, DSObjectBase): + def __init__(self, file_system, target, object_id, metadata=None): + assert isinstance(target, unicode) + DSObjectBase.__init__(self, file_system, stat.S_IFLNK | 0777, + object_id, metadata) + self.target = target + - def get_properties(self, names=None): - return self._ds.get_properties(self.object_id, names) +class DSObject(DSObjectBase): + def __init__(self, file_system, object_id, metadata=None): + DSObjectBase.__init__(self, file_system, stat.S_IFREG | 0750, + object_id, metadata) def list_properties(self): return self._ds.list_properties(self.object_id) @@ -608,25 +659,6 @@ class DSObject(FSEntry): def get_size(self): return self._ds.get_size(self.object_id) - def get_ctime(self): - props = self.get_properties([u'creation_time', u'timestamp']) - try: - return float(props[u'creation_time']) - except (KeyError, ValueError, TypeError): - pass - - try: - return float(props[u'timestamp']) - except (KeyError, ValueError, TypeError): - return time.time() - - def get_mtime(self): - props = self.get_properties([u'creation_time', u'timestamp']) - try: - return float(props[u'timestamp']) - except (KeyError, ValueError, TypeError): - return time.time() - class Directory(FSEntry): def __init__(self, file_system, level, mode, parent=None): @@ -643,15 +675,18 @@ class Directory(FSEntry): if self.parent is not None: yield (u'..', self.parent) - def _get_symlink(self, object_id): + def _get_symlink(self, object_id, metadata=None): directory_path = u'../' * self._level + u'by-id/' if isinstance(object_id, tuple): assert (isinstance(object_id[0], unicode) and isinstance(object_id[1], unicode)) - return Symlink(self._fs, directory_path + u'/'.join(object_id)) + return ObjectSymlink(self._fs, + directory_path + u'/'.join(object_id), + object_id, metadata) else: assert isinstance(object_id, unicode) - return Symlink(self._fs, directory_path + object_id) + return ObjectSymlink(self._fs, directory_path + object_id, + object_id, metadata) class ByTitleDirectory(Directory): @@ -672,7 +707,7 @@ class ByTitleDirectory(Directory): for object_id, metadata in self._ds.list_metadata(): name = self._fs.lookup_title_name(object_id, metadata) - yield (name, self._get_symlink(object_id)) + yield (name, self._get_symlink(object_id, metadata)) def lookup(self, name): object_id = self._fs.resolve_title_name(name) @@ -790,7 +825,7 @@ class ByTagsSubDirectory(ByTitleDirectory): for object_id, metadata in self._find_entries(): name = self._fs.lookup_title_name(object_id, metadata) - yield (name, self._get_symlink(object_id)) + yield (name, self._get_symlink(object_id, metadata)) def _find_entries(self): query = {'query': ' '.join(self._tags)} |