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-25 05:25:13 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2012-09-25 05:25:13 (GMT)
commit82aa41773163b49c82a0b71c02e6f85eea1e352a (patch)
tree82097c94a77d9aea0051944299d7e51ad1b08be1
parent40b9b03232f665d93e42bb72b9c93048413ea075 (diff)
Support sub-calls
-rw-r--r--active_document/commands.py23
-rw-r--r--active_document/document.py3
-rw-r--r--active_document/volume.py10
-rwxr-xr-xtests/units/commands.py23
-rwxr-xr-xtests/units/volume.py33
5 files changed, 90 insertions, 2 deletions
diff --git a/active_document/commands.py b/active_document/commands.py
index 1b303e9..cec88d4 100644
--- a/active_document/commands.py
+++ b/active_document/commands.py
@@ -93,6 +93,7 @@ class Request(dict):
content_length = None
access_level = env.ACCESS_REMOTE
accept_language = None
+ commands = None
def __init__(self, *args, **props):
if args:
@@ -103,6 +104,11 @@ class Request(dict):
dict.__init__(self, props)
self._pos = 0
+ @property
+ def volume(self):
+ enforce(self.commands is not None)
+ return self.commands.volume
+
def __getitem__(self, key):
enforce(key in self, 'Cannot find %r request argument', key)
return self.get(key)
@@ -118,6 +124,21 @@ class Request(dict):
self._pos += len(result)
return result
+ def call(self, method, content=None, content_stream=None,
+ content_length=None, **kwargs):
+ enforce(self.commands is not None)
+
+ kwargs['method'] = method
+ request = type(self)(kwargs)
+ request.access_level = self.access_level
+ request.accept_language = self.accept_language
+ request.commands = self.commands
+ request.content = content
+ request.content_stream = content_stream
+ request.content_length = content_length
+
+ return self.commands.call(request, Response())
+
def __repr__(self):
args = ['content_length=%r' % self.content_length,
'access_level=%r' % self.access_level,
@@ -182,6 +203,8 @@ class CommandsProcessor(object):
enforce(request.access_level & cmd.access_level, env.Forbidden,
'Operation is permitted on requester\'s level')
+ request.commands = self
+
for arg, cast in cmd.arguments.items():
if arg not in request:
continue
diff --git a/active_document/document.py b/active_document/document.py
index 34e1090..9573ad4 100644
--- a/active_document/document.py
+++ b/active_document/document.py
@@ -28,10 +28,11 @@ class Document(dict):
#: `Metadata` object that describes the document
metadata = None
- def __init__(self, guid, record, cached_props=None):
+ def __init__(self, guid, record, cached_props=None, request=None):
dict.__init__(self, cached_props or {})
self.guid = guid
self._record = record
+ self.request = request
@active_property(slot=1000, prefix='IC', typecast=int,
permissions=env.ACCESS_READ, default=0)
diff --git a/active_document/volume.py b/active_document/volume.py
index ebd6775..8583803 100644
--- a/active_document/volume.py
+++ b/active_document/volume.py
@@ -194,6 +194,7 @@ class VolumeCommands(CommandsProcessor):
directory = self.volume[document]
prop = directory.metadata[prop]
doc = directory.get(guid)
+ doc.request = request
prop.assert_access(env.ACCESS_READ)
@@ -239,8 +240,14 @@ class VolumeCommands(CommandsProcessor):
@contextmanager
def _post(self, request, access):
+ enforce(isinstance(request.content, dict), 'Invalid value')
+
directory = self.volume[request['document']]
- doc = directory.document_class(request.get('guid'), {})
+ if 'guid' in request:
+ doc = directory.get(request['guid'])
+ else:
+ doc = directory.document_class(None, {})
+ doc.request = request
blobs = []
for name, value in request.content.items():
@@ -278,6 +285,7 @@ class VolumeCommands(CommandsProcessor):
result = {}
lang = request.accept_language or self._lang
metadata = doc.metadata
+ doc.request = request
for prop in request['reply']:
result[prop] = metadata[prop].on_get(doc, doc.get(prop, lang))
return result
diff --git a/tests/units/commands.py b/tests/units/commands.py
index 0ba4c23..f5f753b 100755
--- a/tests/units/commands.py
+++ b/tests/units/commands.py
@@ -495,6 +495,29 @@ class CommandsTest(tests.Test):
self.assertEqual(['pre', 'cmd', 'post'], request['probe'])
self.assertEqual(['cmd', 'post'], response['probe'])
+ def test_SubCall(self):
+
+ class TestCommandsProcessor(CommandsProcessor):
+
+ @ad.volume_command(method='PROBE')
+ def command1(self, request):
+ return request.call('PROBE', cmd='command2')
+
+ @ad.volume_command(method='PROBE')
+ def command2(self, request):
+ return {'access_level': request.access_level, 'accept_language': request.accept_language}
+
+ cp = TestCommandsProcessor()
+
+ request = ad.Request(method='PROBE')
+ request.access_level = -1
+ request.accept_language = 'foo'
+ self.assertEqual({
+ 'access_level': -1,
+ 'accept_language': 'foo',
+ },
+ cp.call(request, ad.Response()))
+
def call(self, cp, method, document=None, guid=None, prop=None,
access_level=env.ACCESS_REMOTE, **kwargs):
diff --git a/tests/units/volume.py b/tests/units/volume.py
index be706f9..0ef7c72 100755
--- a/tests/units/volume.py
+++ b/tests/units/volume.py
@@ -4,6 +4,7 @@
import os
import sys
import time
+import json
import shutil
import hashlib
from cStringIO import StringIO
@@ -950,6 +951,38 @@ class VolumeTest(tests.Test):
self.call('PUT', document='testdocument', guid=guid, prop='blob2', content='bar')
self.assertEqual(' bar ', ''.join(self.call('GET', document='testdocument', guid=guid, prop='blob2')))
+ def test_SubCall(self):
+
+ class TestDocument(Document):
+
+ @active_property(BlobProperty, mime_type='application/json')
+ def blob(self, value):
+ return value
+
+ @blob.setter
+ def blob(self, value):
+ if type(value) is int:
+ value = [value]
+ meta = self.meta('blob')
+ if meta:
+ with file(meta['path']) as f:
+ value = json.load(f) + value
+ coroutine.spawn(self.post, value)
+ return value
+
+ def post(self, value):
+ self.request.call('PUT', document='testdocument', guid=self.guid, prop='blob', content=value + [-1])
+
+ self.volume = SingleVolume(tests.tmpdir, [TestDocument])
+
+ guid = self.call('POST', document='testdocument', content={'blob': 0})
+ coroutine.dispatch()
+ self.assertEqual('[0, -1]', ''.join(self.call('GET', document='testdocument', guid=guid, prop='blob')))
+
+ self.call('PUT', document='testdocument', guid=guid, prop='blob', content=2)
+ coroutine.dispatch()
+ self.assertEqual('[0, -1, 2, -1]', ''.join(self.call('GET', document='testdocument', guid=guid, prop='blob')))
+
def call(self, method, document=None, guid=None, prop=None,
accept_language=None, **kwargs):