diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2012-09-15 03:18:45 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2012-09-15 03:18:45 (GMT) |
commit | e4a9c1b142387c99a9b8d29329a7d56cf4692e48 (patch) | |
tree | 28094c6b6a6a7ec33c722ae20bb121c6d8fd3fee /active_document | |
parent | 9aceaf6c315a05d67390efe2024405d3d505191d (diff) |
Limited support of composite BLOBs
Diffstat (limited to 'active_document')
-rw-r--r-- | active_document/__init__.py | 2 | ||||
-rw-r--r-- | active_document/directory.py | 4 | ||||
-rw-r--r-- | active_document/metadata.py | 8 | ||||
-rw-r--r-- | active_document/storage.py | 40 | ||||
-rw-r--r-- | active_document/volume.py | 24 |
5 files changed, 54 insertions, 24 deletions
diff --git a/active_document/__init__.py b/active_document/__init__.py index 4956342..ebe701f 100644 --- a/active_document/__init__.py +++ b/active_document/__init__.py @@ -27,6 +27,8 @@ from active_document.metadata import Metadata, Property, \ StoredProperty, ActiveProperty, BlobProperty, BrowsableProperty, \ active_property +from active_document.storage import Meta + from active_document.commands import document_command, directory_command, \ volume_command, property_command, to_int, to_list, \ Request, Response, CommandsProcessor, ProxyCommands, CommandNotFound diff --git a/active_document/directory.py b/active_document/directory.py index 91e8d8b..f3afe6a 100644 --- a/active_document/directory.py +++ b/active_document/directory.py @@ -203,9 +203,7 @@ class Directory(object): _logger.debug('Received %r BLOB property from %s[%s]', prop.name, self.metadata.name, guid) - if isinstance(prop, BlobProperty) and \ - prop.mime_type == 'application/json' and \ - not hasattr(data, 'read'): + if prop.mime_type == 'application/json' and not hasattr(data, 'read'): data = json.dumps(data) record.set_blob(prop.name, data, size, seqno=seqno, mime_type=prop.mime_type, **kwargs) diff --git a/active_document/metadata.py b/active_document/metadata.py index 8869873..01b3b60 100644 --- a/active_document/metadata.py +++ b/active_document/metadata.py @@ -278,9 +278,10 @@ class BlobProperty(Property): """ def __init__(self, name, permissions=env.ACCESS_PUBLIC, - mime_type='application/octet-stream'): + mime_type='application/octet-stream', composite=False): Property.__init__(self, name, permissions=permissions) self._mime_type = mime_type + self._composite = composite @property def mime_type(self): @@ -291,6 +292,11 @@ class BlobProperty(Property): """ return self._mime_type + @property + def composite(self): + """Property is a list of BLOBs.""" + return self._composite + def _is_composite(typecast): if type(typecast) in _LIST_TYPES: diff --git a/active_document/storage.py b/active_document/storage.py index d14b2b2..148e3df 100644 --- a/active_document/storage.py +++ b/active_document/storage.py @@ -24,7 +24,7 @@ from os.path import exists, join, isdir, basename, relpath, lexists, isabs from active_document import env from active_document.metadata import BlobProperty from active_toolkit.sockets import BUFFER_SIZE -from active_toolkit import util +from active_toolkit import util, enforce _BLOB_SUFFIX = '.blob' @@ -175,16 +175,8 @@ class Record(object): def get(self, prop): path = join(self._root, prop) - if not exists(path): - return None - - with file(path) as f: - meta = json.load(f) - if exists(path + _BLOB_SUFFIX): - meta['path'] = path + _BLOB_SUFFIX - meta['mtime'] = os.stat(path).st_mtime - - return meta + if exists(path): + return Meta(path) def set(self, prop, mtime=None, **kwargs): if not exists(self._root): @@ -268,3 +260,29 @@ class Record(object): hash_file(path) else: hash_file(dst_path) + + +class Meta(dict): + + def __init__(self, path_=None, **meta): + if path_: + with file(path_) as f: + meta.update(json.load(f)) + if exists(path_ + _BLOB_SUFFIX): + meta['path'] = path_ + _BLOB_SUFFIX + meta['mtime'] = os.stat(path_).st_mtime + dict.__init__(self, meta) + + def url(self, part=None): + url = self.get('url') + if url is None or isinstance(url, basestring): + return url + + if part: + file_meta = url.get(part) + enforce(file_meta and 'url' in file_meta, + env.NotFound, 'No BLOB for %r', part) + return file_meta['url'] + + return sorted(url.values(), + cmp=lambda x, y: cmp(x.get('order'), y.get('order'))) diff --git a/active_document/volume.py b/active_document/volume.py index e12771b..ac4d037 100644 --- a/active_document/volume.py +++ b/active_document/volume.py @@ -257,24 +257,30 @@ class VolumeCommands(CommandsProcessor): return doc.properties(reply, request.accept_language) @property_command(method='GET', arguments={'seqno': to_int}) - def get_prop(self, document, guid, prop, request, response, seqno=None): + def get_prop(self, document, guid, prop, request, response, seqno=None, + part=None): directory = self.volume[document] + prop = directory.metadata[prop] doc = directory.get(guid) - directory.metadata[prop].assert_access(env.ACCESS_READ) + prop.assert_access(env.ACCESS_READ) - if not isinstance(directory.metadata[prop], BlobProperty): - return doc.get(prop, request.accept_language) + if not isinstance(prop, BlobProperty): + return doc.get(prop.name, request.accept_language) - meta = doc.meta(prop) + meta = doc.meta(prop.name) enforce(meta is not None, env.NotFound, 'BLOB does not exist') - if 'url' in meta: - raise env.Redirect(meta['url']) + url = meta.url(part) + if url is not None: + if not isinstance(url, basestring): + response.content_type = 'application/json' + return url + raise env.Redirect(url) if seqno is not None and seqno >= meta['seqno']: response.content_length = 0 - response.content_type = directory.metadata[prop].mime_type + response.content_type = prop.mime_type return None path = meta['path'] @@ -285,7 +291,7 @@ class VolumeCommands(CommandsProcessor): return dir_reader else: response.content_length = os.stat(path).st_size - response.content_type = directory.metadata[prop].mime_type + response.content_type = prop.mime_type return _file_reader(path) def before_create(self, request, props): |