Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2012-09-09 09:41:43 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2012-09-09 09:41:43 (GMT)
commit521eb6e45c8115eef0071864b2bbecec878a9166 (patch)
treed3429f4c58984c701915568dc73f349ffe28b030
parent0bd269a12b2c734d58a7a2a4e3dd33173955b702 (diff)
Return urls for blobs in GET requets
-rw-r--r--sugar_network/node/__init__.py5
-rw-r--r--sugar_network/node/commands.py56
-rw-r--r--sugar_network/node/sync_master.py12
-rwxr-xr-xtests/units/node.py42
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)