import simplejson
from allmydata.mutable import NotMutableError
from allmydata.interfaces import IMutableFileNode, IDirectoryNode,\
- IURI, IFileNode, IMutableFileURI, IVerifierURI
+ IURI, IFileNode, IMutableFileURI, IVerifierURI, IFilesystemNode
from allmydata.util import hashutil
from allmydata.util.hashutil import netstring
from allmydata.uri import NewDirectoryURI
child, metadata = children[name]
assert (IFileNode.providedBy(child)
or IMutableFileNode.providedBy(child)
- or IDirectoryNode.providedBy(child)), children
+ or IDirectoryNode.providedBy(child)), (name,child)
assert isinstance(metadata, dict)
rwcap = child.get_uri() # might be RO if the child is not writeable
rocap = child.get_readonly_uri()
If this directory node is read-only, the Deferred will errback with a
NotMutableError."""
- return self.set_node(name, self._create_node(child_uri), metadata, wait_for_numpeers=wait_for_numpeers)
+ return self.set_node(name, self._create_node(child_uri), metadata,
+ wait_for_numpeers)
+
+ def set_uris(self, entries, wait_for_numpeers=None):
+ node_entries = []
+ for e in entries:
+ if len(e) == 2:
+ name, child_uri = e
+ metadata = {}
+ else:
+ assert len(e) == 3
+ name, child_uri, metadata = e
+ node_entries.append( (name,self._create_node(child_uri),metadata) )
+ return self.set_nodes(node_entries, wait_for_numpeers)
def set_node(self, name, child, metadata={}, wait_for_numpeers=None):
"""I add a child at the specific name. I return a Deferred that fires
If this directory node is read-only, the Deferred will errback with a
NotMutableError."""
+ assert IFilesystemNode.providedBy(child), child
+ d = self.set_nodes( [(name, child, metadata)], wait_for_numpeers)
+ d.addCallback(lambda res: child)
+ return d
+
+ def set_nodes(self, entries, wait_for_numpeers=None):
if self.is_readonly():
return defer.fail(NotMutableError())
d = self._read()
def _add(children):
- children[name] = (child, metadata)
+ for e in entries:
+ if len(e) == 2:
+ name, child = e
+ metadata = {}
+ else:
+ assert len(e) == 3
+ name, child, metadata = e
+ children[name] = (child, metadata)
new_contents = self._pack_contents(children)
return self._node.replace(new_contents, wait_for_numpeers=wait_for_numpeers)
d.addCallback(_add)
- d.addCallback(lambda res: child)
+ d.addCallback(lambda res: None)
return d
+
def add_file(self, name, uploadable, wait_for_numpeers=None):
"""I upload a file (using the given IUploadable), then attach the
resulting FileNode to the directory at the given name. I return a
If this directory node is read-only, the Deferred will errback with a
NotMutableError."""
+ def set_uris(entries):
+ """Add multiple (name, child_uri) pairs to a directory node. Returns
+ a Deferred that fires (with None) when the operation finishes. This
+ is equivalent to calling set_uri() multiple times, but is much more
+ efficient.
+ """
+
def set_node(name, child):
"""I add a child at the specific name. I return a Deferred that fires
when the operation finishes. This Deferred will fire with the child
If this directory node is read-only, the Deferred will errback with a
NotMutableError."""
+ def set_nodes(entries):
+ """Add multiple (name, child_node) pairs to a directory node. Returns
+ a Deferred that fires (with None) when the operation finishes. This
+ is equivalent to calling set_node() multiple times, but is much more
+ efficient."""
+
+
def add_file(name, uploadable):
"""I upload a file (using the given IUploadable), then attach the
resulting FileNode to the directory at the given name. I return a
return d
+ def test_GET_DIRURL_large(self):
+ # Nevow has a problem showing more than about 192 children of a
+ # directory: it uses defer.success() and d.addCallback in a way that
+ # can make the stack grow very quickly. See ticket #237 for details.
+ # To work around this, I think we'll need to put a 'return
+ # defer.fireEventually' in our render_ method. This test is intended
+ # to trigger the bug (and eventually verify that our workaround
+ # actually works), but it isn't yet failing for me.
+
+ d = self.s.create_empty_dirnode()
+ COUNT = 400
+ def _created(dirnode):
+ entries = [ (str(i), self._foo_uri) for i in range(COUNT) ]
+ d2 = dirnode.set_uris(entries)
+ d2.addCallback(lambda res: dirnode)
+ return d2
+ d.addCallback(_created)
+
+ def _check(dirnode):
+ large_url = "/uri/" + dirnode.get_uri() + "/"
+ return self.GET(large_url)
+ d.addCallback(_check)
+
+ def _done(res):
+ self.failUnless('<a href="%d">%d</a>' % (COUNT-1, COUNT-1) in res)
+ self.failIf("maximum recursion depth exceeded" in res)
+ d.addCallback(_done)
+ return d
+
def test_GET_DIRURL_json(self):
d = self.GET(self.public_url + "/foo?t=json")
d.addCallback(self.failUnlessIsFooJSON)