dirnode: add get_child_and_metadata_at_path

This commit is contained in:
Brian Warner 2008-10-02 17:52:03 -07:00
parent 9c505e49c2
commit d0bdf9a611
3 changed files with 75 additions and 5 deletions

View File

@ -248,6 +248,12 @@ class NewDirectoryNode:
raise KeyError(name)
return child[0]
def _get_with_metadata(self, children, name):
child = children.get(name)
if child is None:
raise KeyError(name)
return child
def get(self, name):
"""I return a Deferred that fires with the named child node,
which is either an IFileNode or an IDirectoryNode."""
@ -256,6 +262,15 @@ class NewDirectoryNode:
d.addCallback(self._get, name)
return d
def get_child_and_metadata(self, name):
"""I return a Deferred that fires with the (node, metadata) pair for
the named child. The node is either an IFileNode or an
IDirectoryNode, and the metadata is a dictionary."""
assert isinstance(name, unicode)
d = self._read()
d.addCallback(self._get_with_metadata, name)
return d
def get_metadata_for(self, name):
assert isinstance(name, unicode)
d = self._read()
@ -282,9 +297,17 @@ class NewDirectoryNode:
The path can be either a single string (slash-separated) or a list of
path-name elements.
"""
d = self.get_child_and_metdadata_at_path(path)
d.addCallback(lambda (node, metadata): node)
return d
def get_child_and_metdadata_at_path(self, path):
"""Transform a child path into an IDirectoryNode or IFileNode and
a metadata dictionary from the last edge that was traversed.
"""
if not path:
return defer.succeed(self)
return defer.succeed((self, {}))
if isinstance(path, (list, tuple)):
pass
else:
@ -293,11 +316,12 @@ class NewDirectoryNode:
assert isinstance(p, unicode)
childname = path[0]
remaining_path = path[1:]
d = self.get(childname)
if remaining_path:
def _got(node):
return node.get_child_at_path(remaining_path)
d.addCallback(_got)
d = self.get(childname)
d.addCallback(lambda node:
node.get_child_and_metdadata_at_path(remaining_path))
return d
d = self.get_child_and_metadata(childname)
return d
def set_uri(self, name, child_uri, metadata=None, overwrite=True):

View File

@ -703,6 +703,15 @@ class IDirectoryNode(IMutableFilesystemNode):
path-name elements. All elements must be unicode strings.
"""
def get_child_and_metadata_at_path(path):
"""Transform a child path into an IDirectoryNode/IFileNode and
metadata.
I am like get_child_at_path(), but my Deferred fires with a tuple of
(node, metadata). The metadata comes from the last edge. If the path
is empty, the metadata will be an empty dictionary.
"""
def set_uri(name, child_uri, metadata=None, overwrite=True):
"""I add a child (by URI) at the specific name. I return a Deferred
that fires when the operation finishes. If overwrite= is True, I will

View File

@ -361,6 +361,10 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin, testutil.StallMixin):
def _add_subsubdir(res):
return self.subdir.create_empty_directory(u"subsubdir")
d.addCallback(_add_subsubdir)
# /
# /child = mutable
# /subdir = directory
# /subdir/subsubdir = directory
d.addCallback(lambda res: n.get_child_at_path(u"subdir/subsubdir"))
d.addCallback(lambda subsubdir:
self.failUnless(isinstance(subsubdir,
@ -374,6 +378,39 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin, testutil.StallMixin):
self.failUnlessEqual(sorted(metadata.keys()),
["ctime", "mtime"]))
d.addCallback(lambda res:
self.shouldFail(KeyError, "gcamap-no",
"'nope'",
n.get_child_and_metdadata_at_path,
u"subdir/nope"))
d.addCallback(lambda res:
n.get_child_and_metdadata_at_path(u""))
def _check_child_and_metadata1(res):
child, metadata = res
self.failUnless(isinstance(child, FakeDirectoryNode))
# edge-metadata needs at least one path segment
self.failUnlessEqual(sorted(metadata.keys()), [])
d.addCallback(_check_child_and_metadata1)
d.addCallback(lambda res:
n.get_child_and_metdadata_at_path(u"child"))
def _check_child_and_metadata2(res):
child, metadata = res
self.failUnlessEqual(child.get_uri(),
fake_file_uri.to_string())
self.failUnlessEqual(sorted(metadata.keys()),
["ctime", "mtime"])
d.addCallback(_check_child_and_metadata2)
d.addCallback(lambda res:
n.get_child_and_metdadata_at_path(u"subdir/subsubdir"))
def _check_child_and_metadata3(res):
child, metadata = res
self.failUnless(isinstance(child, FakeDirectoryNode))
self.failUnlessEqual(sorted(metadata.keys()),
["ctime", "mtime"])
d.addCallback(_check_child_and_metadata3)
# set_uri + metadata
# it should be possible to add a child without any metadata
d.addCallback(lambda res: n.set_uri(u"c2", fake_file_uri, {}))