diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2012-09-09 09:41:43 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2012-09-09 09:41:43 (GMT) |
commit | 521eb6e45c8115eef0071864b2bbecec878a9166 (patch) | |
tree | d3429f4c58984c701915568dc73f349ffe28b030 | |
parent | 0bd269a12b2c734d58a7a2a4e3dd33173955b702 (diff) |
Return urls for blobs in GET requets
-rw-r--r-- | sugar_network/node/__init__.py | 5 | ||||
-rw-r--r-- | sugar_network/node/commands.py | 56 | ||||
-rw-r--r-- | sugar_network/node/sync_master.py | 12 | ||||
-rwxr-xr-x | tests/units/node.py | 42 |
4 files changed, 101 insertions, 14 deletions
diff --git a/sugar_network/node/__init__.py b/sugar_network/node/__init__.py index 72516d1..94499d2 100644 --- a/sugar_network/node/__init__.py +++ b/sugar_network/node/__init__.py @@ -17,8 +17,9 @@ from active_toolkit.options import Option host = Option( - 'hostname to listen incomming connections', - default='0.0.0.0', name='host') + 'hostname to listen for incomming connections and ' + 'using for publicly visible urls', + default='localhost', name='host') port = Option( 'port number to listen incomming connections', diff --git a/sugar_network/node/commands.py b/sugar_network/node/commands.py index 4a34dc7..b9c935e 100644 --- a/sugar_network/node/commands.py +++ b/sugar_network/node/commands.py @@ -55,6 +55,13 @@ class NodeCommands(ad.VolumeCommands): with file(master_path, 'w') as f: f.write(_DEFAULT_MASTER_GUID) + self._blobs = {} + for document, directory in self.volume.items(): + self._blobs.setdefault(document, set()) + for prop in directory.metadata.values(): + if isinstance(prop, ad.BlobProperty): + self._blobs[document].add(prop.name) + @ad.volume_command(method='GET') def hello(self, response): response.content_type = 'text/html' @@ -80,7 +87,9 @@ class NodeCommands(ad.VolumeCommands): directory = self.volume[document] directory.update(guid, {'layer': ['deleted']}) - @ad.directory_command(method='GET') + @ad.directory_command(method='GET', + arguments={'offset': ad.to_int, 'limit': ad.to_int, + 'reply': ad.to_list}) def find(self, document, request, offset=None, limit=None, query=None, reply=None, order_by=None, group_by=None, **kwargs): if limit is None: @@ -89,9 +98,37 @@ class NodeCommands(ad.VolumeCommands): _logger.warning('The find limit is restricted to %s', node.find_limit.value) limit = node.find_limit.value - return ad.VolumeCommands.find(self, document, request, offset, limit, + + blobs = None + if reply: + reply = set(reply) + blobs = reply & self._blobs[document] + reply = list(reply - blobs) + + result = ad.VolumeCommands.find(self, document, request, offset, limit, query, reply, order_by, group_by, **kwargs) + if blobs: + for props in result['result']: + self._mixin_blob(document, blobs, props) + + return result + + @ad.document_command(method='GET', arguments={'reply': ad.to_list}) + def get(self, document, guid, request, reply=None): + blobs = None + if reply: + reply = set(reply) + blobs = reply & self._blobs[document] + reply = list(reply - blobs) + + result = ad.VolumeCommands.get(self, document, guid, request, reply) + + if blobs: + self._mixin_blob(document, blobs, result) + + return result + def resolve(self, request): cmd = ad.VolumeCommands.resolve(self, request) if cmd is None: @@ -135,6 +172,21 @@ class NodeCommands(ad.VolumeCommands): authors.append(user['name']) props['author'] = authors + def _mixin_blob(self, document, blobs, props): + directory = self.volume[document] + doc = directory.get(props['guid']) + + for name in blobs: + meta = doc.meta(name) + if meta is not None and 'url' in meta: + url = meta['url'] + else: + url = '/'.join(['', document, props['guid'], name]) + if url.startswith('/'): + url = 'http://%s:%s%s' % \ + (node.host.value, node.port.value, url) + props[name] = url + class MasterCommands(NodeCommands, SyncCommands): diff --git a/sugar_network/node/sync_master.py b/sugar_network/node/sync_master.py index 86e86a0..cfa2568 100644 --- a/sugar_network/node/sync_master.py +++ b/sugar_network/node/sync_master.py @@ -109,7 +109,8 @@ class SyncCommands(object): return out_packet.pop() @ad.volume_command(method='GET', cmd='pull', - mime_type='application/octet-stream') + mime_type='application/octet-stream', + arguments={'accept_length': ad.to_int}) def pull(self, request, response, accept_length=None, **pulls): cookie = _Cookie(request) for key, seq in pulls.items(): @@ -118,7 +119,6 @@ class SyncCommands(object): _logger.debug('Clone full dump') cookie['sn_pull'].include(1, None) - accept_length = _to_int('accept_length', accept_length) pull_key = hashlib.sha1(json.dumps(cookie)).hexdigest() pull = None content = None @@ -286,11 +286,3 @@ class _Cookie(dict): def _unset_cookie(self, response, name): self._set_cookie(response, name, 'unset_%s' % name, 0) - - -def _to_int(name, value): - if isinstance(value, basestring): - enforce(value.isdigit(), - 'Argument %r should be an integer value', name) - value = int(value) - return value diff --git a/tests/units/node.py b/tests/units/node.py index 6101997..ea3c120 100755 --- a/tests/units/node.py +++ b/tests/units/node.py @@ -258,6 +258,48 @@ class NodeTest(tests.Test): node.find_limit.value = 1 self.assertEqual(1, len(call(cp, method='GET', document='context', limit=1024)['result'])) + def test_GetBlobsByUrls(self): + volume = Volume('db') + cp = NodeCommands(volume) + + guid1 = call(cp, method='POST', document='context', principal='principal', content={ + 'type': 'activity', + 'title': 'title1', + 'summary': 'summary', + 'description': 'description', + }) + guid2 = call(cp, method='POST', document='context', principal='principal', content={ + 'type': 'activity', + 'title': 'title2', + 'summary': 'summary', + 'description': 'description', + }) + volume['context'].set_blob(guid2, 'icon', 'http://foo/bar') + guid3 = call(cp, method='POST', document='context', principal='principal', content={ + 'type': 'activity', + 'title': 'title3', + 'summary': 'summary', + 'description': 'description', + }) + volume['context'].set_blob(guid3, 'icon', '/foo/bar') + + self.assertEqual( + {'guid': guid1, 'icon': 'http://localhost:8000/context/%s/icon' % guid1}, + call(cp, method='GET', document='context', guid=guid1, reply=['guid', 'icon'])) + self.assertEqual( + {'guid': guid2, 'icon': 'http://foo/bar'}, + call(cp, method='GET', document='context', guid=guid2, reply=['guid', 'icon'])) + self.assertEqual( + {'guid': guid3, 'icon': 'http://localhost:8000/foo/bar'}, + call(cp, method='GET', document='context', guid=guid3, reply=['guid', 'icon'])) + + self.assertEqual([ + {'guid': guid1, 'icon': 'http://localhost:8000/context/%s/icon' % guid1}, + {'guid': guid2, 'icon': 'http://foo/bar'}, + {'guid': guid3, 'icon': 'http://localhost:8000/foo/bar'}, + ], + call(cp, method='GET', document='context', reply=['guid', 'icon'])['result']) + def call(cp, principal=None, content=None, **kwargs): request = ad.Request(**kwargs) |