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-06-01 09:12:20 (GMT)
commitb5e8739ab65e0ea9d903a2a6900ea4277554b4ed (patch)
treec211a686664770960febf83402c75d453bff2551
parent128791e7b7a91d85062d249ed764e78ec9be8eb7 (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 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)}