Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Silbe <sascha-pgp@silbe.org>2013-03-04 10:34:08 (GMT)
committer Sascha Silbe <sascha-pgp@silbe.org>2013-03-04 10:34:08 (GMT)
commita55e209df374f8cceaaf0dab3b6a18d88f080a46 (patch)
tree8e2f45f2d79f58c2ab1b1255c1288ec0c7ff67be
parent76bc3aa0f474cf55d72e60d58e0c512167ca7846 (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.py95
1 files changed, 65 insertions, 30 deletions
diff --git a/fsemulation.py b/fsemulation.py
index 5f35bf7..31f9b47 100644
--- a/fsemulation.py
+++ b/fsemulation.py
@@ -462,7 +462,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.
@@ -549,13 +549,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)
@@ -584,25 +635,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):
@@ -619,15 +651,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):
@@ -648,7 +683,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)
@@ -766,7 +801,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)}