]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
wapi: add POST /uri/$DIRECTORY?t=set_children
authorZooko O'Whielacronx <zooko@zooko.com>
Sat, 1 Mar 2008 01:40:27 +0000 (18:40 -0700)
committerZooko O'Whielacronx <zooko@zooko.com>
Sat, 1 Mar 2008 01:40:27 +0000 (18:40 -0700)
Unfinished bits: doc in webapi.txt, test handling of badly formed JSON, return reasonable HTTP response, examination of the effect of this patch on code coverage -- but I'm committing it anyway because MikeB can use it and I'm being called to dinner...

src/allmydata/dirnode.py
src/allmydata/interfaces.py
src/allmydata/test/common.py
src/allmydata/test/test_dirnode.py
src/allmydata/test/test_web.py
src/allmydata/webish.py

index fc6debc902b4765585d51be3e2bef51c8295c3da..f80e71b7ad7db5f9b660324f2279dd142b7b3131 100644 (file)
@@ -250,7 +250,7 @@ class NewDirectoryNode:
         assert isinstance(name, unicode)
         return self.set_node(name, self._create_node(child_uri), metadata)
 
-    def set_uris(self, entries):
+    def set_children(self, entries):
         node_entries = []
         for e in entries:
             if len(e) == 2:
index 07d1cc7903445f83aa299d56f60ad11519447b7a..d4e6cc7cc082f8ca47d7a8720ec119b4ff6b4916 100644 (file)
@@ -669,7 +669,7 @@ class IDirectoryNode(IMutableFilesystemNode):
         If this directory node is read-only, the Deferred will errback with a
         NotMutableError."""
 
-    def set_uris(entries):
+    def set_children(entries):
         """Add multiple (name, child_uri) pairs (or (name, child_uri,
         metadata) triples) to a directory node. Returns a Deferred that fires
         (with None) when the operation finishes. This is equivalent to
index c88e7f1a6550c3117ea5d2e05270bafb33fe5451..d0f32ceb75480090036ac74dd8c9f758520183d2 100644 (file)
@@ -110,7 +110,7 @@ def make_verifier_uri():
     return uri.SSKVerifierURI(storage_index=os.urandom(16),
                               fingerprint=os.urandom(32))
 
-class NonGridDirectoryNode(dirnode.NewDirectoryNode):
+class FakeDirectoryNode(dirnode.NewDirectoryNode):
     """This offers IDirectoryNode, but uses a FakeMutableFileNode for the
     backing store, so it doesn't go to the grid. The child data is still
     encrypted and serialized, so this isn't useful for tests that want to
index c97d8dd2171681e76e33ea79b5ab0d57b9094f88..9d053dc89f4e269bb8b08a7c387cd97342672f09 100644 (file)
@@ -7,15 +7,13 @@ from allmydata.interfaces import IURI, IClient, IMutableFileNode, \
      INewDirectoryURI, IReadonlyNewDirectoryURI, IFileNode
 from allmydata.util import hashutil, testutil
 from allmydata.test.common import make_chk_file_uri, make_mutable_file_uri, \
-     NonGridDirectoryNode, create_chk_filenode
+     FakeDirectoryNode, create_chk_filenode
 from twisted.internet import defer, reactor
 
 # to test dirnode.py, we want to construct a tree of real DirectoryNodes that
 # contain pointers to fake files. We start with a fake MutableFileNode that
 # stores all of its data in a static table.
 
-FakeDirectoryNode = NonGridDirectoryNode
-
 class Marker:
     implements(IFileNode, IMutableFileNode) # sure, why not
     def __init__(self, nodeuri):
@@ -281,8 +279,8 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin):
             d.addCallback(lambda res: n.delete(u"d3"))
             d.addCallback(lambda res: n.delete(u"d4"))
 
-            # metadata through set_uris()
-            d.addCallback(lambda res: n.set_uris([ (u"e1", fake_file_uri),
+            # metadata through set_children()
+            d.addCallback(lambda res: n.set_children([ (u"e1", fake_file_uri),
                                                    (u"e2", fake_file_uri, {}),
                                                    (u"e3", fake_file_uri,
                                                     {"key": "value"}),
index c78b0401de4bc1cf5cd3f14559f3ea9cc1019420..122dbacc38cc59f81b7665dce84cf7533610bce3 100644 (file)
@@ -7,7 +7,7 @@ from twisted.web import client, error, http
 from twisted.python import failure, log
 from allmydata import interfaces, provisioning, uri, webish, upload, download
 from allmydata.util import fileutil
-from allmydata.test.common import NonGridDirectoryNode, FakeCHKFileNode, FakeMutableFileNode, create_chk_filenode
+from allmydata.test.common import FakeDirectoryNode, FakeCHKFileNode, FakeMutableFileNode, create_chk_filenode
 from allmydata.interfaces import IURI, INewDirectoryURI, IReadonlyNewDirectoryURI, IFileURI, IMutableFileURI, IMutableFileNode
 
 # create a fake uploader/downloader, and a couple of fake dirnodes, then
@@ -35,18 +35,18 @@ class FakeClient(service.MultiService):
     def connected_to_introducer(self):
         return False
 
-    def create_node_from_uri(self, uri):
-        u = IURI(uri)
+    def create_node_from_uri(self, auri):
+        u = uri.from_string(auri)
         if (INewDirectoryURI.providedBy(u)
             or IReadonlyNewDirectoryURI.providedBy(u)):
-            return NonGridDirectoryNode(self).init_from_uri(u)
+            return FakeDirectoryNode(self).init_from_uri(u)
         if IFileURI.providedBy(u):
             return FakeCHKFileNode(u, self)
         assert IMutableFileURI.providedBy(u), u
         return FakeMutableFileNode(self).init_from_uri(u)
 
     def create_empty_dirnode(self):
-        n = NonGridDirectoryNode(self)
+        n = FakeDirectoryNode(self)
         d = n.create()
         d.addCallback(lambda res: n)
         return d
@@ -1299,6 +1299,46 @@ class Web(WebMixin, unittest.TestCase):
         d.addCallback(self.failUnlessNodeKeysAre, [])
         return d
 
+    def test_POST_set_children(self):
+        contents9, n9, newuri9 = self.makefile(9)
+        contents10, n10, newuri10 = self.makefile(10)
+        contents11, n11, newuri11 = self.makefile(11)
+
+        reqbody = """{
+                     "atomic_added_1": [ "filenode", { "rw_uri": "%s",
+                                                "size": 0,
+                                                "metadata": {
+                                                  "ctime": 1002777696.7564139,
+                                                  "mtime": 1002777696.7564139
+                                                 }
+                                               } ], 
+                     "atomic_added_2": [ "filenode", { "rw_uri": "%s",
+                                                "size": 1,
+                                                "metadata": {
+                                                  "ctime": 1002777696.7564139,
+                                                  "mtime": 1002777696.7564139
+                                                 }
+                                               } ],
+                     "atomic_added_3": [ "filenode", { "rw_uri": "%s",
+                                                "size": 2,
+                                                "metadata": {
+                                                  "ctime": 1002777696.7564139,
+                                                  "mtime": 1002777696.7564139
+                                                 }
+                                               } ]
+                    }""" % (newuri9, newuri10, newuri11)
+
+        url = self.webish_url + self.public_url + "/foo" + "?t=set_children"
+
+        d = client.getPage(url, method="POST", postdata=reqbody)
+        def _then(res):
+            self.failUnlessURIMatchesChild(newuri9, self._foo_node, u"atomic_added_1")
+            self.failUnlessURIMatchesChild(newuri10, self._foo_node, u"atomic_added_2")
+            self.failUnlessURIMatchesChild(newuri11, self._foo_node, u"atomic_added_3")
+
+        d.addCallback(_then)
+        return d
+
     def test_POST_put_uri(self):
         contents, n, newuri = self.makefile(8)
         d = self.POST(self.public_url + "/foo", t="uri", name="new.txt", uri=newuri)
index 7a8e954f42aa01ad9eb56672fe5590371ada5231..f8da62717bf8e3d30b3d1d7877b3fa43048db9e0 100644 (file)
@@ -899,6 +899,16 @@ class POSTHandler(rend.Page):
         d.addCallback(_got_child_check)
         return d
 
+    def _POST_set_children(self, children):
+        cs = []
+        for name, (file_or_dir, mddict) in children.iteritems():
+            cap = str(mddict.get('rw_uri') or mddict.get('ro_uri'))
+            cs.append((name, cap, mddict.get('metadata')))
+
+        d = self._node.set_children(cs)
+        d.addCallback(lambda res: "Okay so I did it.")
+        return d
+
     def renderHTTP(self, ctx):
         req = inevow.IRequest(ctx)
 
@@ -973,16 +983,16 @@ class POSTHandler(rend.Page):
             d = self._POST_overwrite(contents)
         elif t == "check":
             d = self._POST_check(name)
-        elif t == "set_children":
-        #     d = self._POST_set_(name)
-        #     if not name:
-        #         raise RuntimeError("set-uri requires a name")
-        #     newuri = get_arg(req, "uri")
-        #     assert newuri is not None
-        #     d = self._check_replacement(name)
-        #     d.addCallback(lambda res: self._node.set_uri(name, newuri))
-        #     d.addCallback(lambda res: newuri)
-
+        elif t == "set_children":
+            req.content.seek(0)
+            body = req.content.read()
+            try:
+                children = simplejson.loads(body)
+            except ValueError, le:
+                le.args = tuple(le.args + (body,))
+                # TODO test handling of bad JSON
+                raise
+            d = self._POST_set_children(children)
         else:
             print "BAD t=%s" % t
             return "BAD t=%s" % t
@@ -1346,9 +1356,8 @@ class UnlinkedPUTSSKUploader(rend.Page):
         req = inevow.IRequest(ctx)
         assert req.method == "PUT"
         # SDMF: files are small, and we can only upload data
-        contents = req.content
-        contents.seek(0)
-        data = contents.read()
+        req.content.seek(0)
+        data = req.content.read()
         d = IClient(ctx).create_mutable_file(data)
         d.addCallback(lambda n: n.get_uri())
         return d