Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/active_document
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2012-09-15 03:18:45 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2012-09-15 03:18:45 (GMT)
commite4a9c1b142387c99a9b8d29329a7d56cf4692e48 (patch)
tree28094c6b6a6a7ec33c722ae20bb121c6d8fd3fee /active_document
parent9aceaf6c315a05d67390efe2024405d3d505191d (diff)
Limited support of composite BLOBs
Diffstat (limited to 'active_document')
-rw-r--r--active_document/__init__.py2
-rw-r--r--active_document/directory.py4
-rw-r--r--active_document/metadata.py8
-rw-r--r--active_document/storage.py40
-rw-r--r--active_document/volume.py24
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):