mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-19 13:07:56 +00:00
unicode handling: declare dirnodes to contain unicode child names, update webish to match
This commit is contained in:
parent
61edecd137
commit
7927495cbe
@ -58,6 +58,18 @@ In addition, each directory has a corresponding URL. The Pictures URL is:
|
||||
|
||||
http://localhost:8123/uri/$PRIVATE_VDRIVE_URI/Pictures
|
||||
|
||||
Note that all filenames are assumed to be UTF-8 encoded, so "resume.doc"
|
||||
(with an acute accent on both E's) would be accessed with:
|
||||
|
||||
http://localhost:8123/uri/$PRIVATE_VDRIVE_URI/r%C3%A9sum%C3%A9.doc
|
||||
|
||||
The filenames inside upload POST forms are interpreted using whatever
|
||||
character set was provided in the conventional '_charset' field, and defaults
|
||||
to UTF-8 if not otherwise specified. The JSON representation of each
|
||||
directory contains native unicode strings. Tahoe directories are specified to
|
||||
contain unicode filenames, and cannot contain binary strings that are not
|
||||
representable as such.
|
||||
|
||||
c. URIs
|
||||
|
||||
From the "URIs" chapter in architecture.txt, recall that each file and
|
||||
|
@ -102,8 +102,8 @@ class NewDirectoryNode:
|
||||
# the directory is serialized as a list of netstrings, one per child.
|
||||
# Each child is serialized as a list of four netstrings: (name,
|
||||
# rocap, rwcap, metadata), in which the name,rocap,metadata are in
|
||||
# cleartext. The rwcap is formatted as:
|
||||
# pack("16ss32s", iv, AES(H(writekey+iv), plaintextrwcap), mac)
|
||||
# cleartext. The 'name' is UTF-8 encoded. The rwcap is formatted as:
|
||||
# pack("16ss32s", iv, AES(H(writekey+iv), plaintextrwcap), mac)
|
||||
assert isinstance(data, str)
|
||||
# an empty directory is serialized as an empty string
|
||||
if data == "":
|
||||
@ -113,6 +113,7 @@ class NewDirectoryNode:
|
||||
while len(data) > 0:
|
||||
entry, data = split_netstring(data, 1, True)
|
||||
name, rocap, rwcapdata, metadata_s = split_netstring(entry, 4)
|
||||
name = name.decode("utf-8")
|
||||
if writeable:
|
||||
rwcap = self._decrypt_rwcapdata(rwcapdata)
|
||||
child = self._create_node(rwcap)
|
||||
@ -129,13 +130,14 @@ class NewDirectoryNode:
|
||||
entries = []
|
||||
for name in sorted(children.keys()):
|
||||
child, metadata = children[name]
|
||||
assert isinstance(name, unicode)
|
||||
assert (IFileNode.providedBy(child)
|
||||
or IMutableFileNode.providedBy(child)
|
||||
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()
|
||||
entry = "".join([netstring(name),
|
||||
entry = "".join([netstring(name.encode("utf-8")),
|
||||
netstring(rocap),
|
||||
netstring(self._encrypt_rwcap(rwcap)),
|
||||
netstring(simplejson.dumps(metadata))])
|
||||
@ -168,6 +170,7 @@ class NewDirectoryNode:
|
||||
def has_child(self, name):
|
||||
"""I return a Deferred that fires with a boolean, True if there
|
||||
exists a child of the given name, False if not."""
|
||||
assert isinstance(name, unicode)
|
||||
d = self._read()
|
||||
d.addCallback(lambda children: children.has_key(name))
|
||||
return d
|
||||
@ -181,16 +184,19 @@ class NewDirectoryNode:
|
||||
def get(self, name):
|
||||
"""I return a Deferred that fires with the named child node,
|
||||
which is either an IFileNode or an IDirectoryNode."""
|
||||
assert isinstance(name, unicode)
|
||||
d = self._read()
|
||||
d.addCallback(self._get, name)
|
||||
return d
|
||||
|
||||
def get_metadata_for(self, name):
|
||||
assert isinstance(name, unicode)
|
||||
d = self._read()
|
||||
d.addCallback(lambda children: children[name][1])
|
||||
return d
|
||||
|
||||
def set_metadata_for(self, name, metadata):
|
||||
assert isinstance(name, unicode)
|
||||
if self.is_readonly():
|
||||
return defer.fail(NotMutableError())
|
||||
assert isinstance(metadata, dict)
|
||||
@ -216,8 +222,12 @@ class NewDirectoryNode:
|
||||
|
||||
if not path:
|
||||
return defer.succeed(self)
|
||||
if isinstance(path, (str, unicode)):
|
||||
if isinstance(path, (list, tuple)):
|
||||
pass
|
||||
else:
|
||||
path = path.split("/")
|
||||
for p in path:
|
||||
assert isinstance(p, unicode)
|
||||
childname = path[0]
|
||||
remaining_path = path[1:]
|
||||
d = self.get(childname)
|
||||
@ -237,6 +247,7 @@ class NewDirectoryNode:
|
||||
|
||||
If this directory node is read-only, the Deferred will errback with a
|
||||
NotMutableError."""
|
||||
assert isinstance(name, unicode)
|
||||
return self.set_node(name, self._create_node(child_uri), metadata)
|
||||
|
||||
def set_uris(self, entries):
|
||||
@ -248,6 +259,7 @@ class NewDirectoryNode:
|
||||
else:
|
||||
assert len(e) == 3
|
||||
name, child_uri, metadata = e
|
||||
assert isinstance(name, unicode)
|
||||
node_entries.append( (name,self._create_node(child_uri),metadata) )
|
||||
return self.set_nodes(node_entries)
|
||||
|
||||
@ -259,6 +271,7 @@ class NewDirectoryNode:
|
||||
|
||||
If this directory node is read-only, the Deferred will errback with a
|
||||
NotMutableError."""
|
||||
assert isinstance(name, unicode)
|
||||
assert IFilesystemNode.providedBy(child), child
|
||||
d = self.set_nodes( [(name, child, metadata)])
|
||||
d.addCallback(lambda res: child)
|
||||
@ -277,6 +290,7 @@ class NewDirectoryNode:
|
||||
else:
|
||||
assert len(e) == 3
|
||||
name, child, new_metadata = e
|
||||
assert isinstance(name, unicode)
|
||||
if name in children:
|
||||
metadata = children[name][1].copy()
|
||||
else:
|
||||
@ -303,6 +317,7 @@ class NewDirectoryNode:
|
||||
resulting FileNode to the directory at the given name. I return a
|
||||
Deferred that fires (with the IFileNode of the uploaded file) when
|
||||
the operation completes."""
|
||||
assert isinstance(name, unicode)
|
||||
if self.is_readonly():
|
||||
return defer.fail(NotMutableError())
|
||||
d = self._client.upload(uploadable)
|
||||
@ -314,6 +329,7 @@ class NewDirectoryNode:
|
||||
def delete(self, name):
|
||||
"""I remove the child at the specific name. I return a Deferred that
|
||||
fires (with the node just removed) when the operation finishes."""
|
||||
assert isinstance(name, unicode)
|
||||
if self.is_readonly():
|
||||
return defer.fail(NotMutableError())
|
||||
d = self._read()
|
||||
@ -333,6 +349,7 @@ class NewDirectoryNode:
|
||||
"""I create and attach an empty directory at the given name. I return
|
||||
a Deferred that fires (with the new directory node) when the
|
||||
operation finishes."""
|
||||
assert isinstance(name, unicode)
|
||||
if self.is_readonly():
|
||||
return defer.fail(NotMutableError())
|
||||
d = self._client.create_empty_dirnode()
|
||||
@ -349,10 +366,12 @@ class NewDirectoryNode:
|
||||
is referenced by name. On the new parent, the child will live under
|
||||
'new_child_name', which defaults to 'current_child_name'. I return a
|
||||
Deferred that fires when the operation finishes."""
|
||||
assert isinstance(current_child_name, unicode)
|
||||
if self.is_readonly() or new_parent.is_readonly():
|
||||
return defer.fail(NotMutableError())
|
||||
if new_child_name is None:
|
||||
new_child_name = current_child_name
|
||||
assert isinstance(new_child_name, unicode)
|
||||
d = self.get(current_child_name)
|
||||
def sn(child):
|
||||
return new_parent.set_node(new_child_name, child)
|
||||
|
@ -587,6 +587,11 @@ class IMutableFileNode(IFileNode, IMutableFilesystemNode):
|
||||
"""
|
||||
|
||||
class IDirectoryNode(IMutableFilesystemNode):
|
||||
"""I represent a name-to-child mapping, holding the tahoe equivalent of a
|
||||
directory. All child names are unicode strings, and all children are some
|
||||
sort of IFilesystemNode (either files or subdirectories).
|
||||
"""
|
||||
|
||||
def get_uri():
|
||||
"""
|
||||
The dirnode ('1') URI returned by this method can be used in
|
||||
@ -607,30 +612,33 @@ class IDirectoryNode(IMutableFilesystemNode):
|
||||
|
||||
def list():
|
||||
"""I return a Deferred that fires with a dictionary mapping child
|
||||
name to (node, metadata_dict) tuples, in which 'node' is either an
|
||||
IFileNode or IDirectoryNode, and 'metadata_dict' is a dictionary of
|
||||
metadata."""
|
||||
name (a unicode string) to (node, metadata_dict) tuples, in which
|
||||
'node' is either an IFileNode or IDirectoryNode, and 'metadata_dict'
|
||||
is a dictionary of metadata."""
|
||||
|
||||
def has_child(name):
|
||||
"""I return a Deferred that fires with a boolean, True if there
|
||||
exists a child of the given name, False if not."""
|
||||
exists a child of the given name, False if not. The child name must
|
||||
be a unicode string."""
|
||||
|
||||
def get(name):
|
||||
"""I return a Deferred that fires with a specific named child node,
|
||||
either an IFileNode or an IDirectoryNode."""
|
||||
either an IFileNode or an IDirectoryNode. The child name must be a
|
||||
unicode string."""
|
||||
|
||||
def get_metadata_for(name):
|
||||
"""I return a Deferred that fires with the metadata dictionary for a
|
||||
specific named child node. This metadata is stored in the *edge*, not
|
||||
in the child, so it is attached to the parent dirnode rather than the
|
||||
child dir-or-file-node."""
|
||||
child dir-or-file-node. The child name must be a unicode string."""
|
||||
|
||||
def set_metadata_for(name, metadata):
|
||||
"""I replace any existing metadata for the named child with the new
|
||||
metadata. This metadata is stored in the *edge*, not in the child, so
|
||||
it is attached to the parent dirnode rather than the child
|
||||
dir-or-file-node. I return a Deferred (that fires with this dirnode)
|
||||
when the operation is complete."""
|
||||
metadata. The child name must be a unicode string. This metadata is
|
||||
stored in the *edge*, not in the child, so it is attached to the
|
||||
parent dirnode rather than the child dir-or-file-node. I return a
|
||||
Deferred (that fires with this dirnode) when the operation is
|
||||
complete."""
|
||||
|
||||
def get_child_at_path(path):
|
||||
"""Transform a child path into an IDirectoryNode or IFileNode.
|
||||
@ -640,13 +648,13 @@ class IDirectoryNode(IMutableFilesystemNode):
|
||||
errbacks with IndexError if the node could not be found.
|
||||
|
||||
The path can be either a single string (slash-separated) or a list of
|
||||
path-name elements.
|
||||
path-name elements. All elements must be unicode strings.
|
||||
"""
|
||||
|
||||
def set_uri(name, child_uri, metadata=None):
|
||||
"""I add a child (by URI) at the specific name. I return a Deferred
|
||||
that fires when the operation finishes. I will replace any existing
|
||||
child of the same name.
|
||||
child of the same name. The child name must be a unicode string.
|
||||
|
||||
The child_uri could be for a file, or for a directory (either
|
||||
read-write or read-only, using a URI that came from get_uri() ).
|
||||
@ -665,14 +673,15 @@ class IDirectoryNode(IMutableFilesystemNode):
|
||||
"""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
|
||||
calling set_uri() multiple times, but is much more efficient.
|
||||
calling set_uri() multiple times, but is much more efficient. All
|
||||
child names must be unicode strings.
|
||||
"""
|
||||
|
||||
def set_node(name, child, metadata=None):
|
||||
"""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
|
||||
node that was just added. I will replace any existing child of the
|
||||
same name.
|
||||
same name. The child name must be a unicode string.
|
||||
|
||||
If metadata= is provided, I will use it as the metadata for the named
|
||||
edge. This will replace any existing metadata. If metadata= is left
|
||||
@ -688,31 +697,35 @@ class IDirectoryNode(IMutableFilesystemNode):
|
||||
"""Add multiple (name, child_node) pairs (or (name, child_node,
|
||||
metadata) triples) 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."""
|
||||
calling set_node() multiple times, but is much more efficient. All
|
||||
child names must be unicode strings."""
|
||||
|
||||
|
||||
def add_file(name, uploadable, metadata=None):
|
||||
"""I upload a file (using the given IUploadable), then attach the
|
||||
resulting FileNode to the directory at the given name. I set metadata
|
||||
the same way as set_uri and set_node.
|
||||
the same way as set_uri and set_node. The child name must be a
|
||||
unicode string.
|
||||
|
||||
I return a Deferred that fires (with the IFileNode of the uploaded
|
||||
file) when the operation completes."""
|
||||
|
||||
def delete(name):
|
||||
"""I remove the child at the specific name. I return a Deferred that
|
||||
fires when the operation finishes."""
|
||||
fires when the operation finishes. The child name must be a unicode
|
||||
string."""
|
||||
|
||||
def create_empty_directory(name):
|
||||
"""I create and attach an empty directory at the given name. I return
|
||||
a Deferred that fires when the operation finishes."""
|
||||
"""I create and attach an empty directory at the given name. The
|
||||
child name must be a unicode string. I return a Deferred that fires
|
||||
when the operation finishes."""
|
||||
|
||||
def move_child_to(current_child_name, new_parent, new_child_name=None):
|
||||
"""I take one of my children and move them to a new parent. The child
|
||||
is referenced by name. On the new parent, the child will live under
|
||||
'new_child_name', which defaults to 'current_child_name'. TODO: what
|
||||
should we do about metadata? I return a Deferred that fires when the
|
||||
operation finishes."""
|
||||
operation finishes. The child name must be a unicode string."""
|
||||
|
||||
def build_manifest():
|
||||
"""Return a frozenset of verifier-capability strings for all nodes
|
||||
|
@ -83,14 +83,14 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin):
|
||||
d = self.client.create_empty_dirnode()
|
||||
def _created(dn):
|
||||
u = make_mutable_file_uri()
|
||||
d = dn.set_uri("child", u, {})
|
||||
d = dn.set_uri(u"child", u, {})
|
||||
d.addCallback(lambda res: dn.list())
|
||||
def _check1(children):
|
||||
self.failUnless("child" in children)
|
||||
self.failUnless(u"child" in children)
|
||||
d.addCallback(_check1)
|
||||
d.addCallback(lambda res:
|
||||
self.shouldFail(KeyError, "get bogus", None,
|
||||
dn.get, "bogus"))
|
||||
dn.get, u"bogus"))
|
||||
def _corrupt(res):
|
||||
filenode = dn._node
|
||||
si = IURI(filenode.get_uri()).storage_index
|
||||
@ -126,7 +126,7 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin):
|
||||
|
||||
d = self.client.create_empty_dirnode()
|
||||
def _created(rw_dn):
|
||||
d2 = rw_dn.set_uri("child", fileuri)
|
||||
d2 = rw_dn.set_uri(u"child", fileuri)
|
||||
d2.addCallback(lambda res: rw_dn)
|
||||
return d2
|
||||
d.addCallback(_created)
|
||||
@ -138,23 +138,23 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin):
|
||||
self.failUnless(ro_dn.is_mutable())
|
||||
|
||||
self.shouldFail(dirnode.NotMutableError, "set_uri ro", None,
|
||||
ro_dn.set_uri, "newchild", fileuri)
|
||||
ro_dn.set_uri, u"newchild", fileuri)
|
||||
self.shouldFail(dirnode.NotMutableError, "set_uri ro", None,
|
||||
ro_dn.set_node, "newchild", filenode)
|
||||
ro_dn.set_node, u"newchild", filenode)
|
||||
self.shouldFail(dirnode.NotMutableError, "set_uri ro", None,
|
||||
ro_dn.add_file, "newchild", uploadable)
|
||||
ro_dn.add_file, u"newchild", uploadable)
|
||||
self.shouldFail(dirnode.NotMutableError, "set_uri ro", None,
|
||||
ro_dn.delete, "child")
|
||||
ro_dn.delete, u"child")
|
||||
self.shouldFail(dirnode.NotMutableError, "set_uri ro", None,
|
||||
ro_dn.create_empty_directory, "newchild")
|
||||
ro_dn.create_empty_directory, u"newchild")
|
||||
self.shouldFail(dirnode.NotMutableError, "set_uri ro", None,
|
||||
ro_dn.move_child_to, "child", rw_dn)
|
||||
ro_dn.move_child_to, u"child", rw_dn)
|
||||
self.shouldFail(dirnode.NotMutableError, "set_uri ro", None,
|
||||
rw_dn.move_child_to, "child", ro_dn)
|
||||
rw_dn.move_child_to, u"child", ro_dn)
|
||||
return ro_dn.list()
|
||||
d.addCallback(_ready)
|
||||
def _listed(children):
|
||||
self.failUnless("child" in children)
|
||||
self.failUnless(u"child" in children)
|
||||
d.addCallback(_listed)
|
||||
return d
|
||||
|
||||
@ -186,16 +186,16 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin):
|
||||
|
||||
d = n.list()
|
||||
d.addCallback(lambda res: self.failUnlessEqual(res, {}))
|
||||
d.addCallback(lambda res: n.has_child("missing"))
|
||||
d.addCallback(lambda res: n.has_child(u"missing"))
|
||||
d.addCallback(lambda res: self.failIf(res))
|
||||
fake_file_uri = make_mutable_file_uri()
|
||||
m = Marker(fake_file_uri)
|
||||
ffu_v = m.get_verifier()
|
||||
assert isinstance(ffu_v, str)
|
||||
self.expected_manifest.append(ffu_v)
|
||||
d.addCallback(lambda res: n.set_uri("child", fake_file_uri))
|
||||
d.addCallback(lambda res: n.set_uri(u"child", fake_file_uri))
|
||||
|
||||
d.addCallback(lambda res: n.create_empty_directory("subdir"))
|
||||
d.addCallback(lambda res: n.create_empty_directory(u"subdir"))
|
||||
def _created(subdir):
|
||||
self.failUnless(isinstance(subdir, FakeDirectoryNode))
|
||||
self.subdir = subdir
|
||||
@ -207,7 +207,7 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin):
|
||||
d.addCallback(lambda res: n.list())
|
||||
d.addCallback(lambda children:
|
||||
self.failUnlessEqual(sorted(children.keys()),
|
||||
sorted(["child", "subdir"])))
|
||||
sorted([u"child", u"subdir"])))
|
||||
|
||||
d.addCallback(lambda res: n.build_manifest())
|
||||
def _check_manifest(manifest):
|
||||
@ -216,116 +216,116 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin):
|
||||
d.addCallback(_check_manifest)
|
||||
|
||||
def _add_subsubdir(res):
|
||||
return self.subdir.create_empty_directory("subsubdir")
|
||||
return self.subdir.create_empty_directory(u"subsubdir")
|
||||
d.addCallback(_add_subsubdir)
|
||||
d.addCallback(lambda res: n.get_child_at_path("subdir/subsubdir"))
|
||||
d.addCallback(lambda res: n.get_child_at_path(u"subdir/subsubdir"))
|
||||
d.addCallback(lambda subsubdir:
|
||||
self.failUnless(isinstance(subsubdir,
|
||||
FakeDirectoryNode)))
|
||||
d.addCallback(lambda res: n.get_child_at_path(""))
|
||||
d.addCallback(lambda res: n.get_child_at_path(u""))
|
||||
d.addCallback(lambda res: self.failUnlessEqual(res.get_uri(),
|
||||
n.get_uri()))
|
||||
|
||||
d.addCallback(lambda res: n.get_metadata_for("child"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"child"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(sorted(metadata.keys()),
|
||||
["ctime", "mtime"]))
|
||||
|
||||
# set_uri + metadata
|
||||
# it should be possible to add a child without any metadata
|
||||
d.addCallback(lambda res: n.set_uri("c2", fake_file_uri, {}))
|
||||
d.addCallback(lambda res: n.get_metadata_for("c2"))
|
||||
d.addCallback(lambda res: n.set_uri(u"c2", fake_file_uri, {}))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"c2"))
|
||||
d.addCallback(lambda metadata: self.failUnlessEqual(metadata, {}))
|
||||
|
||||
# if we don't set any defaults, the child should get timestamps
|
||||
d.addCallback(lambda res: n.set_uri("c3", fake_file_uri))
|
||||
d.addCallback(lambda res: n.get_metadata_for("c3"))
|
||||
d.addCallback(lambda res: n.set_uri(u"c3", fake_file_uri))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"c3"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(sorted(metadata.keys()),
|
||||
["ctime", "mtime"]))
|
||||
|
||||
# or we can add specific metadata at set_uri() time, which
|
||||
# overrides the timestamps
|
||||
d.addCallback(lambda res: n.set_uri("c4", fake_file_uri,
|
||||
d.addCallback(lambda res: n.set_uri(u"c4", fake_file_uri,
|
||||
{"key": "value"}))
|
||||
d.addCallback(lambda res: n.get_metadata_for("c4"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"c4"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(metadata, {"key": "value"}))
|
||||
|
||||
d.addCallback(lambda res: n.delete("c2"))
|
||||
d.addCallback(lambda res: n.delete("c3"))
|
||||
d.addCallback(lambda res: n.delete("c4"))
|
||||
d.addCallback(lambda res: n.delete(u"c2"))
|
||||
d.addCallback(lambda res: n.delete(u"c3"))
|
||||
d.addCallback(lambda res: n.delete(u"c4"))
|
||||
|
||||
# set_node + metadata
|
||||
# it should be possible to add a child without any metadata
|
||||
d.addCallback(lambda res: n.set_node("d2", n, {}))
|
||||
d.addCallback(lambda res: n.get_metadata_for("d2"))
|
||||
d.addCallback(lambda res: n.set_node(u"d2", n, {}))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"d2"))
|
||||
d.addCallback(lambda metadata: self.failUnlessEqual(metadata, {}))
|
||||
|
||||
# if we don't set any defaults, the child should get timestamps
|
||||
d.addCallback(lambda res: n.set_node("d3", n))
|
||||
d.addCallback(lambda res: n.get_metadata_for("d3"))
|
||||
d.addCallback(lambda res: n.set_node(u"d3", n))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"d3"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(sorted(metadata.keys()),
|
||||
["ctime", "mtime"]))
|
||||
|
||||
# or we can add specific metadata at set_node() time, which
|
||||
# overrides the timestamps
|
||||
d.addCallback(lambda res: n.set_node("d4", n,
|
||||
d.addCallback(lambda res: n.set_node(u"d4", n,
|
||||
{"key": "value"}))
|
||||
d.addCallback(lambda res: n.get_metadata_for("d4"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"d4"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(metadata, {"key": "value"}))
|
||||
|
||||
d.addCallback(lambda res: n.delete("d2"))
|
||||
d.addCallback(lambda res: n.delete("d3"))
|
||||
d.addCallback(lambda res: n.delete("d4"))
|
||||
d.addCallback(lambda res: n.delete(u"d2"))
|
||||
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([ ("e1", fake_file_uri),
|
||||
("e2", fake_file_uri, {}),
|
||||
("e3", fake_file_uri,
|
||||
d.addCallback(lambda res: n.set_uris([ (u"e1", fake_file_uri),
|
||||
(u"e2", fake_file_uri, {}),
|
||||
(u"e3", fake_file_uri,
|
||||
{"key": "value"}),
|
||||
]))
|
||||
d.addCallback(lambda res: n.get_metadata_for("e1"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"e1"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(sorted(metadata.keys()),
|
||||
["ctime", "mtime"]))
|
||||
d.addCallback(lambda res: n.get_metadata_for("e2"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"e2"))
|
||||
d.addCallback(lambda metadata: self.failUnlessEqual(metadata, {}))
|
||||
d.addCallback(lambda res: n.get_metadata_for("e3"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"e3"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(metadata, {"key": "value"}))
|
||||
|
||||
d.addCallback(lambda res: n.delete("e1"))
|
||||
d.addCallback(lambda res: n.delete("e2"))
|
||||
d.addCallback(lambda res: n.delete("e3"))
|
||||
d.addCallback(lambda res: n.delete(u"e1"))
|
||||
d.addCallback(lambda res: n.delete(u"e2"))
|
||||
d.addCallback(lambda res: n.delete(u"e3"))
|
||||
|
||||
# metadata through set_nodes()
|
||||
d.addCallback(lambda res: n.set_nodes([ ("f1", n),
|
||||
("f2", n, {}),
|
||||
("f3", n,
|
||||
d.addCallback(lambda res: n.set_nodes([ (u"f1", n),
|
||||
(u"f2", n, {}),
|
||||
(u"f3", n,
|
||||
{"key": "value"}),
|
||||
]))
|
||||
d.addCallback(lambda res: n.get_metadata_for("f1"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"f1"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(sorted(metadata.keys()),
|
||||
["ctime", "mtime"]))
|
||||
d.addCallback(lambda res: n.get_metadata_for("f2"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"f2"))
|
||||
d.addCallback(lambda metadata: self.failUnlessEqual(metadata, {}))
|
||||
d.addCallback(lambda res: n.get_metadata_for("f3"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"f3"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(metadata, {"key": "value"}))
|
||||
|
||||
d.addCallback(lambda res: n.delete("f1"))
|
||||
d.addCallback(lambda res: n.delete("f2"))
|
||||
d.addCallback(lambda res: n.delete("f3"))
|
||||
d.addCallback(lambda res: n.delete(u"f1"))
|
||||
d.addCallback(lambda res: n.delete(u"f2"))
|
||||
d.addCallback(lambda res: n.delete(u"f3"))
|
||||
|
||||
|
||||
d.addCallback(lambda res:
|
||||
n.set_metadata_for("child",
|
||||
n.set_metadata_for(u"child",
|
||||
{"tags": ["web2.0-compatible"]}))
|
||||
d.addCallback(lambda n1: n1.get_metadata_for("child"))
|
||||
d.addCallback(lambda n1: n1.get_metadata_for(u"child"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(metadata,
|
||||
{"tags": ["web2.0-compatible"]}))
|
||||
@ -339,14 +339,14 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin):
|
||||
# from causing the test to fail, stall for more than a few
|
||||
# hundrededths of a second.
|
||||
d.addCallback(self.stall, 0.1)
|
||||
d.addCallback(lambda res: n.add_file("timestamps",
|
||||
d.addCallback(lambda res: n.add_file(u"timestamps",
|
||||
upload.Data("stamp me")))
|
||||
d.addCallback(self.stall, 0.1)
|
||||
def _stop(res):
|
||||
self._stop_timestamp = time.time()
|
||||
d.addCallback(_stop)
|
||||
|
||||
d.addCallback(lambda res: n.get_metadata_for("timestamps"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"timestamps"))
|
||||
def _check_timestamp1(metadata):
|
||||
self.failUnless("ctime" in metadata)
|
||||
self.failUnless("mtime" in metadata)
|
||||
@ -364,28 +364,28 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin):
|
||||
self._old_mtime = metadata["mtime"]
|
||||
d.addCallback(_check_timestamp1)
|
||||
d.addCallback(self.stall, 2.0) # accomodate low-res timestamps
|
||||
d.addCallback(lambda res: n.set_node("timestamps", n))
|
||||
d.addCallback(lambda res: n.get_metadata_for("timestamps"))
|
||||
d.addCallback(lambda res: n.set_node(u"timestamps", n))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"timestamps"))
|
||||
def _check_timestamp2(metadata):
|
||||
self.failUnlessEqual(metadata["ctime"], self._old_ctime,
|
||||
"%s != %s" % (metadata["ctime"],
|
||||
self._old_ctime))
|
||||
self.failUnlessGreaterThan(metadata["mtime"], self._old_mtime)
|
||||
return n.delete("timestamps")
|
||||
return n.delete(u"timestamps")
|
||||
d.addCallback(_check_timestamp2)
|
||||
|
||||
# also make sure we can add/update timestamps on a
|
||||
# previously-existing child that didn't have any, since there are
|
||||
# a lot of 0.7.0-generated edges around out there
|
||||
d.addCallback(lambda res: n.set_node("no_timestamps", n, {}))
|
||||
d.addCallback(lambda res: n.set_node("no_timestamps", n))
|
||||
d.addCallback(lambda res: n.get_metadata_for("no_timestamps"))
|
||||
d.addCallback(lambda res: n.set_node(u"no_timestamps", n, {}))
|
||||
d.addCallback(lambda res: n.set_node(u"no_timestamps", n))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"no_timestamps"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(sorted(metadata.keys()),
|
||||
["ctime", "mtime"]))
|
||||
d.addCallback(lambda res: n.delete("no_timestamps"))
|
||||
d.addCallback(lambda res: n.delete(u"no_timestamps"))
|
||||
|
||||
d.addCallback(lambda res: n.delete("subdir"))
|
||||
d.addCallback(lambda res: n.delete(u"subdir"))
|
||||
d.addCallback(lambda old_child:
|
||||
self.failUnlessEqual(old_child.get_uri(),
|
||||
self.subdir.get_uri()))
|
||||
@ -393,47 +393,47 @@ class Dirnode(unittest.TestCase, testutil.ShouldFailMixin):
|
||||
d.addCallback(lambda res: n.list())
|
||||
d.addCallback(lambda children:
|
||||
self.failUnlessEqual(sorted(children.keys()),
|
||||
sorted(["child"])))
|
||||
sorted([u"child"])))
|
||||
|
||||
uploadable = upload.Data("some data")
|
||||
d.addCallback(lambda res: n.add_file("newfile", uploadable))
|
||||
d.addCallback(lambda res: n.add_file(u"newfile", uploadable))
|
||||
d.addCallback(lambda newnode:
|
||||
self.failUnless(IFileNode.providedBy(newnode)))
|
||||
d.addCallback(lambda res: n.list())
|
||||
d.addCallback(lambda children:
|
||||
self.failUnlessEqual(sorted(children.keys()),
|
||||
sorted(["child", "newfile"])))
|
||||
d.addCallback(lambda res: n.get_metadata_for("newfile"))
|
||||
sorted([u"child", u"newfile"])))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"newfile"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(sorted(metadata.keys()),
|
||||
["ctime", "mtime"]))
|
||||
|
||||
uploadable = upload.Data("some data")
|
||||
d.addCallback(lambda res: n.add_file("newfile-metadata",
|
||||
d.addCallback(lambda res: n.add_file(u"newfile-metadata",
|
||||
uploadable,
|
||||
{"key": "value"}))
|
||||
d.addCallback(lambda newnode:
|
||||
self.failUnless(IFileNode.providedBy(newnode)))
|
||||
d.addCallback(lambda res: n.get_metadata_for("newfile-metadata"))
|
||||
d.addCallback(lambda res: n.get_metadata_for(u"newfile-metadata"))
|
||||
d.addCallback(lambda metadata:
|
||||
self.failUnlessEqual(metadata, {"key": "value"}))
|
||||
d.addCallback(lambda res: n.delete("newfile-metadata"))
|
||||
d.addCallback(lambda res: n.delete(u"newfile-metadata"))
|
||||
|
||||
d.addCallback(lambda res: n.create_empty_directory("subdir2"))
|
||||
d.addCallback(lambda res: n.create_empty_directory(u"subdir2"))
|
||||
def _created2(subdir2):
|
||||
self.subdir2 = subdir2
|
||||
d.addCallback(_created2)
|
||||
|
||||
d.addCallback(lambda res:
|
||||
n.move_child_to("child", self.subdir2))
|
||||
n.move_child_to(u"child", self.subdir2))
|
||||
d.addCallback(lambda res: n.list())
|
||||
d.addCallback(lambda children:
|
||||
self.failUnlessEqual(sorted(children.keys()),
|
||||
sorted(["newfile", "subdir2"])))
|
||||
sorted([u"newfile", u"subdir2"])))
|
||||
d.addCallback(lambda res: self.subdir2.list())
|
||||
d.addCallback(lambda children:
|
||||
self.failUnlessEqual(sorted(children.keys()),
|
||||
sorted(["child"])))
|
||||
sorted([u"child"])))
|
||||
|
||||
return d
|
||||
|
||||
|
@ -750,10 +750,10 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
log.msg("_created_dirnode(%s)" % (dnode,))
|
||||
d1 = dnode.list()
|
||||
d1.addCallback(lambda children: self.failUnlessEqual(children, {}))
|
||||
d1.addCallback(lambda res: dnode.has_child("edgar"))
|
||||
d1.addCallback(lambda res: dnode.has_child(u"edgar"))
|
||||
d1.addCallback(lambda answer: self.failUnlessEqual(answer, False))
|
||||
d1.addCallback(lambda res: dnode.set_node("see recursive", dnode))
|
||||
d1.addCallback(lambda res: dnode.has_child("see recursive"))
|
||||
d1.addCallback(lambda res: dnode.set_node(u"see recursive", dnode))
|
||||
d1.addCallback(lambda res: dnode.has_child(u"see recursive"))
|
||||
d1.addCallback(lambda answer: self.failUnlessEqual(answer, True))
|
||||
d1.addCallback(lambda res: dnode.build_manifest())
|
||||
d1.addCallback(lambda manifest:
|
||||
@ -840,10 +840,10 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
self._root_directory_uri = new_dirnode.get_uri()
|
||||
return c0.create_node_from_uri(self._root_directory_uri)
|
||||
d.addCallback(_made_root)
|
||||
d.addCallback(lambda root: root.create_empty_directory("subdir1"))
|
||||
d.addCallback(lambda root: root.create_empty_directory(u"subdir1"))
|
||||
def _made_subdir1(subdir1_node):
|
||||
self._subdir1_node = subdir1_node
|
||||
d1 = subdir1_node.add_file("mydata567", ut)
|
||||
d1 = subdir1_node.add_file(u"mydata567", ut)
|
||||
d1.addCallback(self.log, "publish finished")
|
||||
def _stash_uri(filenode):
|
||||
self.uri = filenode.get_uri()
|
||||
@ -854,8 +854,8 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
|
||||
def _do_publish2(self, res):
|
||||
ut = upload.Data(self.data)
|
||||
d = self._subdir1_node.create_empty_directory("subdir2")
|
||||
d.addCallback(lambda subdir2: subdir2.add_file("mydata992", ut))
|
||||
d = self._subdir1_node.create_empty_directory(u"subdir2")
|
||||
d.addCallback(lambda subdir2: subdir2.add_file(u"mydata992", ut))
|
||||
return d
|
||||
|
||||
def log(self, res, msg, **kwargs):
|
||||
@ -875,14 +875,14 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
d.addCallback(self.log, "GOT private directory")
|
||||
def _got_new_dir(privnode):
|
||||
rootnode = self.clients[0].create_node_from_uri(self._root_directory_uri)
|
||||
d1 = privnode.create_empty_directory("personal")
|
||||
d1 = privnode.create_empty_directory(u"personal")
|
||||
d1.addCallback(self.log, "made P/personal")
|
||||
d1.addCallback(lambda node: node.add_file("sekrit data", ut))
|
||||
d1.addCallback(lambda node: node.add_file(u"sekrit data", ut))
|
||||
d1.addCallback(self.log, "made P/personal/sekrit data")
|
||||
d1.addCallback(lambda res: rootnode.get_child_at_path(["subdir1", "subdir2"]))
|
||||
d1.addCallback(lambda res: rootnode.get_child_at_path([u"subdir1", u"subdir2"]))
|
||||
def _got_s2(s2node):
|
||||
d2 = privnode.set_uri("s2-rw", s2node.get_uri())
|
||||
d2.addCallback(lambda node: privnode.set_uri("s2-ro", s2node.get_readonly_uri()))
|
||||
d2 = privnode.set_uri(u"s2-rw", s2node.get_uri())
|
||||
d2.addCallback(lambda node: privnode.set_uri(u"s2-ro", s2node.get_readonly_uri()))
|
||||
return d2
|
||||
d1.addCallback(_got_s2)
|
||||
d1.addCallback(lambda res: privnode)
|
||||
@ -895,8 +895,8 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
c1 = self.clients[1]
|
||||
d = defer.succeed(c1.create_node_from_uri(self._root_directory_uri))
|
||||
d.addCallback(self.log, "check_publish1 got /")
|
||||
d.addCallback(lambda root: root.get("subdir1"))
|
||||
d.addCallback(lambda subdir1: subdir1.get("mydata567"))
|
||||
d.addCallback(lambda root: root.get(u"subdir1"))
|
||||
d.addCallback(lambda subdir1: subdir1.get(u"mydata567"))
|
||||
d.addCallback(lambda filenode: filenode.download_to_data())
|
||||
d.addCallback(self.log, "get finished")
|
||||
def _get_done(data):
|
||||
@ -907,14 +907,14 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
def _check_publish2(self, res):
|
||||
# this one uses the path-based API
|
||||
rootnode = self.clients[1].create_node_from_uri(self._root_directory_uri)
|
||||
d = rootnode.get_child_at_path("subdir1")
|
||||
d = rootnode.get_child_at_path(u"subdir1")
|
||||
d.addCallback(lambda dirnode:
|
||||
self.failUnless(IDirectoryNode.providedBy(dirnode)))
|
||||
d.addCallback(lambda res: rootnode.get_child_at_path("subdir1/mydata567"))
|
||||
d.addCallback(lambda res: rootnode.get_child_at_path(u"subdir1/mydata567"))
|
||||
d.addCallback(lambda filenode: filenode.download_to_data())
|
||||
d.addCallback(lambda data: self.failUnlessEqual(data, self.data))
|
||||
|
||||
d.addCallback(lambda res: rootnode.get_child_at_path("subdir1/mydata567"))
|
||||
d.addCallback(lambda res: rootnode.get_child_at_path(u"subdir1/mydata567"))
|
||||
def _got_filenode(filenode):
|
||||
fnode = self.clients[1].create_node_from_uri(filenode.get_uri())
|
||||
assert fnode == filenode
|
||||
@ -925,7 +925,7 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
# this one uses the path-based API
|
||||
self._private_node = resnode
|
||||
|
||||
d = self._private_node.get_child_at_path("personal")
|
||||
d = self._private_node.get_child_at_path(u"personal")
|
||||
def _got_personal(personal):
|
||||
self._personal_node = personal
|
||||
return personal
|
||||
@ -936,12 +936,12 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
def get_path(path):
|
||||
return self._private_node.get_child_at_path(path)
|
||||
|
||||
d.addCallback(lambda res: get_path("personal/sekrit data"))
|
||||
d.addCallback(lambda res: get_path(u"personal/sekrit data"))
|
||||
d.addCallback(lambda filenode: filenode.download_to_data())
|
||||
d.addCallback(lambda data: self.failUnlessEqual(data, self.smalldata))
|
||||
d.addCallback(lambda res: get_path("s2-rw"))
|
||||
d.addCallback(lambda res: get_path(u"s2-rw"))
|
||||
d.addCallback(lambda dirnode: self.failUnless(dirnode.is_mutable()))
|
||||
d.addCallback(lambda res: get_path("s2-ro"))
|
||||
d.addCallback(lambda res: get_path(u"s2-ro"))
|
||||
def _got_s2ro(dirnode):
|
||||
self.failUnless(dirnode.is_mutable(), dirnode)
|
||||
self.failUnless(dirnode.is_readonly(), dirnode)
|
||||
@ -949,29 +949,29 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
d1.addCallback(lambda res: dirnode.list())
|
||||
d1.addCallback(self.log, "dirnode.list")
|
||||
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "mkdir(nope)", None, dirnode.create_empty_directory, "nope"))
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "mkdir(nope)", None, dirnode.create_empty_directory, u"nope"))
|
||||
|
||||
d1.addCallback(self.log, "doing add_file(ro)")
|
||||
ut = upload.Data("I will disappear, unrecorded and unobserved. The tragedy of my demise is made more poignant by its silence, but this beauty is not for you to ever know.")
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "add_file(nope)", None, dirnode.add_file, "hope", ut))
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "add_file(nope)", None, dirnode.add_file, u"hope", ut))
|
||||
|
||||
d1.addCallback(self.log, "doing get(ro)")
|
||||
d1.addCallback(lambda res: dirnode.get("mydata992"))
|
||||
d1.addCallback(lambda res: dirnode.get(u"mydata992"))
|
||||
d1.addCallback(lambda filenode:
|
||||
self.failUnless(IFileNode.providedBy(filenode)))
|
||||
|
||||
d1.addCallback(self.log, "doing delete(ro)")
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "delete(nope)", None, dirnode.delete, "mydata992"))
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "delete(nope)", None, dirnode.delete, u"mydata992"))
|
||||
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "set_uri(nope)", None, dirnode.set_uri, "hopeless", self.uri))
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "set_uri(nope)", None, dirnode.set_uri, u"hopeless", self.uri))
|
||||
|
||||
d1.addCallback(lambda res: self.shouldFail2(KeyError, "get(missing)", "'missing'", dirnode.get, "missing"))
|
||||
d1.addCallback(lambda res: self.shouldFail2(KeyError, "get(missing)", "'missing'", dirnode.get, u"missing"))
|
||||
|
||||
personal = self._personal_node
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "mv from readonly", None, dirnode.move_child_to, "mydata992", personal, "nope"))
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "mv from readonly", None, dirnode.move_child_to, u"mydata992", personal, u"nope"))
|
||||
|
||||
d1.addCallback(self.log, "doing move_child_to(ro)2")
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "mv to readonly", None, personal.move_child_to, "sekrit data", dirnode, "nope"))
|
||||
d1.addCallback(lambda res: self.shouldFail2(NotMutableError, "mv to readonly", None, personal.move_child_to, u"sekrit data", dirnode, u"nope"))
|
||||
|
||||
d1.addCallback(self.log, "finished with _got_s2ro")
|
||||
return d1
|
||||
@ -982,15 +982,15 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
d1 = defer.succeed(None)
|
||||
d1.addCallback(self.log, "mv 'P/personal/sekrit data' to P/sekrit")
|
||||
d1.addCallback(lambda res:
|
||||
personal.move_child_to("sekrit data",home,"sekrit"))
|
||||
personal.move_child_to(u"sekrit data",home,u"sekrit"))
|
||||
|
||||
d1.addCallback(self.log, "mv P/sekrit 'P/sekrit data'")
|
||||
d1.addCallback(lambda res:
|
||||
home.move_child_to("sekrit", home, "sekrit data"))
|
||||
home.move_child_to(u"sekrit", home, u"sekrit data"))
|
||||
|
||||
d1.addCallback(self.log, "mv 'P/sekret data' P/personal/")
|
||||
d1.addCallback(lambda res:
|
||||
home.move_child_to("sekrit data", personal))
|
||||
home.move_child_to(u"sekrit data", personal))
|
||||
|
||||
d1.addCallback(lambda res: home.build_manifest())
|
||||
d1.addCallback(self.log, "manifest")
|
||||
@ -1319,7 +1319,7 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
def _check_put((out,err)):
|
||||
self.failUnless("200 OK" in out)
|
||||
self.failUnlessEqual(err, "")
|
||||
d = self._private_node.get_child_at_path("test_put/upload.txt")
|
||||
d = self._private_node.get_child_at_path(u"test_put/upload.txt")
|
||||
d.addCallback(lambda filenode: filenode.download_to_data())
|
||||
def _check_put2(res):
|
||||
self.failUnlessEqual(res, TESTDATA)
|
||||
@ -1358,10 +1358,10 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
def _check_mv((out,err)):
|
||||
self.failUnless("OK" in out)
|
||||
self.failUnlessEqual(err, "")
|
||||
d = self.shouldFail2(KeyError, "test_cli._check_rm", "'upload.txt'", self._private_node.get_child_at_path, "test_put/upload.txt")
|
||||
d = self.shouldFail2(KeyError, "test_cli._check_rm", "'upload.txt'", self._private_node.get_child_at_path, u"test_put/upload.txt")
|
||||
|
||||
d.addCallback(lambda res:
|
||||
self._private_node.get_child_at_path("test_put/moved.txt"))
|
||||
self._private_node.get_child_at_path(u"test_put/moved.txt"))
|
||||
d.addCallback(lambda filenode: filenode.download_to_data())
|
||||
def _check_mv2(res):
|
||||
self.failUnlessEqual(res, TESTDATA)
|
||||
@ -1376,7 +1376,7 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
def _check_rm((out,err)):
|
||||
self.failUnless("200 OK" in out)
|
||||
self.failUnlessEqual(err, "")
|
||||
d = self.shouldFail2(KeyError, "test_cli._check_rm", "'moved.txt'", self._private_node.get_child_at_path, "test_put/moved.txt")
|
||||
d = self.shouldFail2(KeyError, "test_cli._check_rm", "'moved.txt'", self._private_node.get_child_at_path, u"test_put/moved.txt")
|
||||
return d
|
||||
d.addCallback(_check_rm)
|
||||
return d
|
||||
@ -1443,7 +1443,7 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
|
||||
def _test_checker_3(self, res):
|
||||
# check one file, through FileNode.check()
|
||||
d = self._private_node.get_child_at_path("personal/sekrit data")
|
||||
d = self._private_node.get_child_at_path(u"personal/sekrit data")
|
||||
d.addCallback(lambda n: n.check())
|
||||
def _checked(results):
|
||||
# 'sekrit data' is small, and fits in a LiteralFileNode, so
|
||||
@ -1453,7 +1453,7 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
|
||||
|
||||
c0 = self.clients[1]
|
||||
n = c0.create_node_from_uri(self._root_directory_uri)
|
||||
d.addCallback(lambda res: n.get_child_at_path("subdir1/mydata567"))
|
||||
d.addCallback(lambda res: n.get_child_at_path(u"subdir1/mydata567"))
|
||||
d.addCallback(lambda n: n.check())
|
||||
def _checked2(results):
|
||||
# mydata567 is large and lives in a CHK
|
||||
|
@ -97,29 +97,34 @@ class WebMixin(object):
|
||||
self._foo_readonly_uri = foo.get_readonly_uri()
|
||||
# NOTE: we ignore the deferred on all set_uri() calls, because we
|
||||
# know the fake nodes do these synchronously
|
||||
self.public_root.set_uri("foo", foo.get_uri())
|
||||
self.public_root.set_uri(u"foo", foo.get_uri())
|
||||
|
||||
self.BAR_CONTENTS, n, self._bar_txt_uri = self.makefile(0)
|
||||
foo.set_uri("bar.txt", self._bar_txt_uri)
|
||||
foo.set_uri(u"bar.txt", self._bar_txt_uri)
|
||||
|
||||
foo.set_uri("empty", res[3][1].get_uri())
|
||||
foo.set_uri(u"empty", res[3][1].get_uri())
|
||||
sub_uri = res[4][1].get_uri()
|
||||
foo.set_uri("sub", sub_uri)
|
||||
foo.set_uri(u"sub", sub_uri)
|
||||
sub = self.s.create_node_from_uri(sub_uri)
|
||||
|
||||
_ign, n, blocking_uri = self.makefile(1)
|
||||
foo.set_uri("blockingfile", blocking_uri)
|
||||
foo.set_uri(u"blockingfile", blocking_uri)
|
||||
|
||||
unicode_filename = u"n\u00fc.txt" # n u-umlaut . t x t
|
||||
# ok, unicode calls it LATIN SMALL LETTER U WITH DIAERESIS but I
|
||||
# still think of it as an umlaut
|
||||
foo.set_uri(unicode_filename, self._bar_txt_uri)
|
||||
|
||||
_ign, n, baz_file = self.makefile(2)
|
||||
sub.set_uri("baz.txt", baz_file)
|
||||
sub.set_uri(u"baz.txt", baz_file)
|
||||
|
||||
_ign, n, self._bad_file_uri = self.makefile(3)
|
||||
# this uri should not be downloadable
|
||||
del FakeCHKFileNode.all_contents[self._bad_file_uri]
|
||||
|
||||
rodir = res[5][1]
|
||||
self.public_root.set_uri("reedownlee", rodir.get_readonly_uri())
|
||||
rodir.set_uri("nor", baz_file)
|
||||
self.public_root.set_uri(u"reedownlee", rodir.get_readonly_uri())
|
||||
rodir.set_uri(u"nor", baz_file)
|
||||
|
||||
# public/
|
||||
# public/foo/
|
||||
@ -132,7 +137,7 @@ class WebMixin(object):
|
||||
# public/reedownlee/nor
|
||||
self.NEWFILE_CONTENTS = "newfile contents\n"
|
||||
|
||||
return foo.get_metadata_for("bar.txt")
|
||||
return foo.get_metadata_for(u"bar.txt")
|
||||
d.addCallback(_then)
|
||||
def _got_metadata(metadata):
|
||||
self._bar_txt_metadata = metadata
|
||||
@ -148,7 +153,7 @@ class WebMixin(object):
|
||||
return self.s.stopService()
|
||||
|
||||
def failUnlessIsBarDotTxt(self, res):
|
||||
self.failUnlessEqual(res, self.BAR_CONTENTS)
|
||||
self.failUnlessEqual(res, self.BAR_CONTENTS, res)
|
||||
|
||||
def failUnlessIsBarJSON(self, res):
|
||||
data = simplejson.loads(res)
|
||||
@ -170,17 +175,20 @@ class WebMixin(object):
|
||||
|
||||
kidnames = sorted(data[1]["children"])
|
||||
self.failUnlessEqual(kidnames,
|
||||
["bar.txt", "blockingfile", "empty", "sub"])
|
||||
[u"bar.txt", u"blockingfile", u"empty",
|
||||
u"n\u00fc.txt", u"sub"])
|
||||
kids = data[1]["children"]
|
||||
self.failUnlessEqual(kids["sub"][0], "dirnode")
|
||||
self.failUnless("metadata" in kids["sub"][1])
|
||||
self.failUnless("ctime" in kids["sub"][1]["metadata"])
|
||||
self.failUnless("mtime" in kids["sub"][1]["metadata"])
|
||||
self.failUnlessEqual(kids["bar.txt"][0], "filenode")
|
||||
self.failUnlessEqual(kids["bar.txt"][1]["size"], len(self.BAR_CONTENTS))
|
||||
self.failUnlessEqual(kids["bar.txt"][1]["ro_uri"], self._bar_txt_uri)
|
||||
self.failUnlessEqual(kids["bar.txt"][1]["metadata"]["ctime"],
|
||||
self.failUnlessEqual(kids[u"sub"][0], "dirnode")
|
||||
self.failUnless("metadata" in kids[u"sub"][1])
|
||||
self.failUnless("ctime" in kids[u"sub"][1]["metadata"])
|
||||
self.failUnless("mtime" in kids[u"sub"][1]["metadata"])
|
||||
self.failUnlessEqual(kids[u"bar.txt"][0], "filenode")
|
||||
self.failUnlessEqual(kids[u"bar.txt"][1]["size"], len(self.BAR_CONTENTS))
|
||||
self.failUnlessEqual(kids[u"bar.txt"][1]["ro_uri"], self._bar_txt_uri)
|
||||
self.failUnlessEqual(kids[u"bar.txt"][1]["metadata"]["ctime"],
|
||||
self._bar_txt_metadata["ctime"])
|
||||
self.failUnlessEqual(kids[u"n\u00fc.txt"][1]["ro_uri"],
|
||||
self._bar_txt_uri)
|
||||
|
||||
def GET(self, urlpath, followRedirect=False):
|
||||
url = self.webish_url + urlpath
|
||||
@ -208,7 +216,7 @@ class WebMixin(object):
|
||||
if isinstance(value, tuple):
|
||||
filename, value = value
|
||||
form.append('Content-Disposition: form-data; name="%s"; '
|
||||
'filename="%s"' % (name, filename))
|
||||
'filename="%s"' % (name, filename.encode("utf-8")))
|
||||
else:
|
||||
form.append('Content-Disposition: form-data; name="%s"' % name)
|
||||
form.append('')
|
||||
@ -399,9 +407,9 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.PUT(self.public_url + "/foo/new.txt", self.NEWFILE_CONTENTS)
|
||||
# TODO: we lose the response code, so we can't check this
|
||||
#self.failUnlessEqual(responsecode, 201)
|
||||
d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, "new.txt")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"new.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(self._foo_node, "new.txt",
|
||||
self.failUnlessChildContentsAre(self._foo_node, u"new.txt",
|
||||
self.NEWFILE_CONTENTS))
|
||||
return d
|
||||
|
||||
@ -409,9 +417,9 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.PUT(self.public_url + "/foo/bar.txt", self.NEWFILE_CONTENTS)
|
||||
# TODO: we lose the response code, so we can't check this
|
||||
#self.failUnlessEqual(responsecode, 200)
|
||||
d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, "bar.txt")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"bar.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(self._foo_node, "bar.txt",
|
||||
self.failUnlessChildContentsAre(self._foo_node, u"bar.txt",
|
||||
self.NEWFILE_CONTENTS))
|
||||
return d
|
||||
|
||||
@ -427,11 +435,11 @@ class Web(WebMixin, unittest.TestCase):
|
||||
def test_PUT_NEWFILEURL_mkdirs(self):
|
||||
d = self.PUT(self.public_url + "/foo/newdir/new.txt", self.NEWFILE_CONTENTS)
|
||||
fn = self._foo_node
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, "newdir/new.txt")
|
||||
d.addCallback(lambda res: self.failIfNodeHasChild(fn, "new.txt"))
|
||||
d.addCallback(lambda res: self.failUnlessNodeHasChild(fn, "newdir"))
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, u"newdir/new.txt")
|
||||
d.addCallback(lambda res: self.failIfNodeHasChild(fn, u"new.txt"))
|
||||
d.addCallback(lambda res: self.failUnlessNodeHasChild(fn, u"newdir"))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(fn, "newdir/new.txt",
|
||||
self.failUnlessChildContentsAre(fn, u"newdir/new.txt",
|
||||
self.NEWFILE_CONTENTS))
|
||||
return d
|
||||
|
||||
@ -446,7 +454,7 @@ class Web(WebMixin, unittest.TestCase):
|
||||
def test_DELETE_FILEURL(self):
|
||||
d = self.DELETE(self.public_url + "/foo/bar.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failIfNodeHasChild(self._foo_node, "bar.txt"))
|
||||
self.failIfNodeHasChild(self._foo_node, u"bar.txt"))
|
||||
return d
|
||||
|
||||
def test_DELETE_FILEURL_missing(self):
|
||||
@ -546,9 +554,9 @@ class Web(WebMixin, unittest.TestCase):
|
||||
f.write(self.NEWFILE_CONTENTS)
|
||||
f.close()
|
||||
d = self.PUT(url, "")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, "new.txt")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"new.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(self._foo_node, "new.txt",
|
||||
self.failUnlessChildContentsAre(self._foo_node, u"new.txt",
|
||||
self.NEWFILE_CONTENTS))
|
||||
return d
|
||||
|
||||
@ -584,14 +592,14 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.PUT(self.public_url + "/foo/newdir/new.txt?t=upload&localfile=%s"
|
||||
% urllib.quote(localfile), "")
|
||||
d.addCallback(self.failUnlessURIMatchesChild,
|
||||
self._foo_node, "newdir/new.txt")
|
||||
self._foo_node, u"newdir/new.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failIfNodeHasChild(self._foo_node, "new.txt"))
|
||||
self.failIfNodeHasChild(self._foo_node, u"new.txt"))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self._foo_node, "newdir"))
|
||||
self.failUnlessNodeHasChild(self._foo_node, u"newdir"))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(self._foo_node,
|
||||
"newdir/new.txt",
|
||||
u"newdir/new.txt",
|
||||
self.NEWFILE_CONTENTS))
|
||||
return d
|
||||
|
||||
@ -691,16 +699,16 @@ class Web(WebMixin, unittest.TestCase):
|
||||
def test_PUT_NEWDIRURL(self):
|
||||
d = self.PUT(self.public_url + "/foo/newdir?t=mkdir", "")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self._foo_node, "newdir"))
|
||||
d.addCallback(lambda res: self._foo_node.get("newdir"))
|
||||
self.failUnlessNodeHasChild(self._foo_node, u"newdir"))
|
||||
d.addCallback(lambda res: self._foo_node.get(u"newdir"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [])
|
||||
return d
|
||||
|
||||
def test_PUT_NEWDIRURL_replace(self):
|
||||
d = self.PUT(self.public_url + "/foo/sub?t=mkdir", "")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self._foo_node, "sub"))
|
||||
d.addCallback(lambda res: self._foo_node.get("sub"))
|
||||
self.failUnlessNodeHasChild(self._foo_node, u"sub"))
|
||||
d.addCallback(lambda res: self._foo_node.get(u"sub"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [])
|
||||
return d
|
||||
|
||||
@ -711,33 +719,33 @@ class Web(WebMixin, unittest.TestCase):
|
||||
"There was already a child by that name, and you asked me "
|
||||
"to not replace it")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self._foo_node, "sub"))
|
||||
d.addCallback(lambda res: self._foo_node.get("sub"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, ["baz.txt"])
|
||||
self.failUnlessNodeHasChild(self._foo_node, u"sub"))
|
||||
d.addCallback(lambda res: self._foo_node.get(u"sub"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [u"baz.txt"])
|
||||
return d
|
||||
|
||||
def test_PUT_NEWDIRURL_mkdirs(self):
|
||||
d = self.PUT(self.public_url + "/foo/subdir/newdir?t=mkdir", "")
|
||||
d.addCallback(lambda res:
|
||||
self.failIfNodeHasChild(self._foo_node, "newdir"))
|
||||
self.failIfNodeHasChild(self._foo_node, u"newdir"))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self._foo_node, "subdir"))
|
||||
self.failUnlessNodeHasChild(self._foo_node, u"subdir"))
|
||||
d.addCallback(lambda res:
|
||||
self._foo_node.get_child_at_path("subdir/newdir"))
|
||||
self._foo_node.get_child_at_path(u"subdir/newdir"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [])
|
||||
return d
|
||||
|
||||
def test_DELETE_DIRURL(self):
|
||||
d = self.DELETE(self.public_url + "/foo")
|
||||
d.addCallback(lambda res:
|
||||
self.failIfNodeHasChild(self.public_root, "foo"))
|
||||
self.failIfNodeHasChild(self.public_root, u"foo"))
|
||||
return d
|
||||
|
||||
def test_DELETE_DIRURL_missing(self):
|
||||
d = self.DELETE(self.public_url + "/foo/missing")
|
||||
d.addBoth(self.should404, "test_DELETE_DIRURL_missing")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self.public_root, "foo"))
|
||||
self.failUnlessNodeHasChild(self.public_root, u"foo"))
|
||||
return d
|
||||
|
||||
def test_DELETE_DIRURL_missing2(self):
|
||||
@ -755,20 +763,22 @@ class Web(WebMixin, unittest.TestCase):
|
||||
def _check(res):
|
||||
names = [path for (path,node) in out]
|
||||
self.failUnlessEqual(sorted(names),
|
||||
[('foo',),
|
||||
('foo','bar.txt'),
|
||||
('foo','blockingfile'),
|
||||
('foo', 'empty'),
|
||||
('foo', 'sub'),
|
||||
('foo','sub','baz.txt'),
|
||||
('reedownlee',),
|
||||
('reedownlee', 'nor'),
|
||||
[(u'foo',),
|
||||
(u'foo',u'bar.txt'),
|
||||
(u'foo',u'blockingfile'),
|
||||
(u'foo', u'empty'),
|
||||
(u'foo', u"n\u00fc.txt"),
|
||||
(u'foo', u'sub'),
|
||||
(u'foo',u'sub',u'baz.txt'),
|
||||
(u'reedownlee',),
|
||||
(u'reedownlee', u'nor'),
|
||||
])
|
||||
subindex = names.index( ('foo', 'sub') )
|
||||
bazindex = names.index( ('foo', 'sub', 'baz.txt') )
|
||||
subindex = names.index( (u'foo', u'sub') )
|
||||
bazindex = names.index( (u'foo', u'sub', u'baz.txt') )
|
||||
self.failUnless(subindex < bazindex)
|
||||
for path,node in out:
|
||||
if path[-1] in ('bar.txt', 'blockingfile', 'baz.txt', 'nor'):
|
||||
if path[-1] in (u'bar.txt', u"n\u00fc.txt", u'blockingfile',
|
||||
u'baz.txt', u'nor'):
|
||||
self.failUnless(interfaces.IFileNode.providedBy(node))
|
||||
else:
|
||||
self.failUnless(interfaces.IDirectoryNode.providedBy(node))
|
||||
@ -839,18 +849,22 @@ class Web(WebMixin, unittest.TestCase):
|
||||
return d
|
||||
|
||||
def failUnlessNodeKeysAre(self, node, expected_keys):
|
||||
for k in expected_keys:
|
||||
assert isinstance(k, unicode)
|
||||
d = node.list()
|
||||
def _check(children):
|
||||
self.failUnlessEqual(sorted(children.keys()), sorted(expected_keys))
|
||||
d.addCallback(_check)
|
||||
return d
|
||||
def failUnlessNodeHasChild(self, node, name):
|
||||
assert isinstance(name, unicode)
|
||||
d = node.list()
|
||||
def _check(children):
|
||||
self.failUnless(name in children)
|
||||
d.addCallback(_check)
|
||||
return d
|
||||
def failIfNodeHasChild(self, node, name):
|
||||
assert isinstance(name, unicode)
|
||||
d = node.list()
|
||||
def _check(children):
|
||||
self.failIf(name in children)
|
||||
@ -858,6 +872,7 @@ class Web(WebMixin, unittest.TestCase):
|
||||
return d
|
||||
|
||||
def failUnlessChildContentsAre(self, node, name, expected_contents):
|
||||
assert isinstance(name, unicode)
|
||||
d = node.get_child_at_path(name)
|
||||
d.addCallback(lambda node: node.download_to_data())
|
||||
def _check(contents):
|
||||
@ -866,6 +881,7 @@ class Web(WebMixin, unittest.TestCase):
|
||||
return d
|
||||
|
||||
def failUnlessChildURIIs(self, node, name, expected_uri):
|
||||
assert isinstance(name, unicode)
|
||||
d = node.get_child_at_path(name)
|
||||
def _check(child):
|
||||
self.failUnlessEqual(child.get_uri(), expected_uri.strip())
|
||||
@ -873,6 +889,7 @@ class Web(WebMixin, unittest.TestCase):
|
||||
return d
|
||||
|
||||
def failUnlessURIMatchesChild(self, got_uri, node, name):
|
||||
assert isinstance(name, unicode)
|
||||
d = node.get_child_at_path(name)
|
||||
def _check(child):
|
||||
self.failUnlessEqual(got_uri.strip(), child.get_uri())
|
||||
@ -896,15 +913,15 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.PUT(self.public_url + "/newdir?t=upload&localdir=%s"
|
||||
% urllib.quote(localdir), "")
|
||||
pr = self.public_root
|
||||
d.addCallback(lambda res: self.failUnlessNodeHasChild(pr, "newdir"))
|
||||
d.addCallback(lambda res: pr.get("newdir"))
|
||||
d.addCallback(lambda res: self.failUnlessNodeHasChild(pr, u"newdir"))
|
||||
d.addCallback(lambda res: pr.get(u"newdir"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre,
|
||||
["one", "two", "three", "zap.zip"])
|
||||
d.addCallback(lambda res: pr.get_child_at_path("newdir/one"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, ["sub"])
|
||||
d.addCallback(lambda res: pr.get_child_at_path("newdir/three"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, ["foo.txt", "bar.txt"])
|
||||
d.addCallback(lambda res: pr.get_child_at_path("newdir/three/bar.txt"))
|
||||
[u"one", u"two", u"three", u"zap.zip"])
|
||||
d.addCallback(lambda res: pr.get_child_at_path(u"newdir/one"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [u"sub"])
|
||||
d.addCallback(lambda res: pr.get_child_at_path(u"newdir/three"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [u"foo.txt", u"bar.txt"])
|
||||
d.addCallback(lambda res: pr.get_child_at_path(u"newdir/three/bar.txt"))
|
||||
d.addCallback(lambda barnode: barnode.download_to_data())
|
||||
d.addCallback(lambda contents:
|
||||
self.failUnlessEqual(contents,
|
||||
@ -945,16 +962,16 @@ class Web(WebMixin, unittest.TestCase):
|
||||
% urllib.quote(localdir),
|
||||
"")
|
||||
fn = self._foo_node
|
||||
d.addCallback(lambda res: self.failUnlessNodeHasChild(fn, "subdir"))
|
||||
d.addCallback(lambda res: fn.get_child_at_path("subdir/newdir"))
|
||||
d.addCallback(lambda res: self.failUnlessNodeHasChild(fn, u"subdir"))
|
||||
d.addCallback(lambda res: fn.get_child_at_path(u"subdir/newdir"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre,
|
||||
["one", "two", "three", "zap.zip"])
|
||||
d.addCallback(lambda res: fn.get_child_at_path("subdir/newdir/one"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, ["sub"])
|
||||
d.addCallback(lambda res: fn.get_child_at_path("subdir/newdir/three"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, ["foo.txt", "bar.txt"])
|
||||
[u"one", u"two", u"three", u"zap.zip"])
|
||||
d.addCallback(lambda res: fn.get_child_at_path(u"subdir/newdir/one"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [u"sub"])
|
||||
d.addCallback(lambda res: fn.get_child_at_path(u"subdir/newdir/three"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [u"foo.txt", u"bar.txt"])
|
||||
d.addCallback(lambda res:
|
||||
fn.get_child_at_path("subdir/newdir/three/bar.txt"))
|
||||
fn.get_child_at_path(u"subdir/newdir/three/bar.txt"))
|
||||
d.addCallback(lambda barnode: barnode.download_to_data())
|
||||
d.addCallback(lambda contents:
|
||||
self.failUnlessEqual(contents,
|
||||
@ -976,12 +993,28 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.POST(self.public_url + "/foo", t="upload",
|
||||
file=("new.txt", self.NEWFILE_CONTENTS))
|
||||
fn = self._foo_node
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, "new.txt")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, u"new.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(fn, "new.txt",
|
||||
self.failUnlessChildContentsAre(fn, u"new.txt",
|
||||
self.NEWFILE_CONTENTS))
|
||||
return d
|
||||
|
||||
def test_POST_upload_unicode(self):
|
||||
filename = u"n\u00e9wer.txt" # n e-acute w e r . t x t
|
||||
target_url = self.public_url + "/foo/" + filename.encode("utf-8")
|
||||
d = self.POST(self.public_url + "/foo", t="upload",
|
||||
file=(filename, self.NEWFILE_CONTENTS))
|
||||
fn = self._foo_node
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, filename)
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(fn, filename,
|
||||
self.NEWFILE_CONTENTS))
|
||||
d.addCallback(lambda res: self.GET(target_url))
|
||||
d.addCallback(lambda contents: self.failUnlessEqual(contents,
|
||||
self.NEWFILE_CONTENTS,
|
||||
contents))
|
||||
return d
|
||||
|
||||
def test_POST_upload_no_link(self):
|
||||
d = self.POST("/uri", t="upload",
|
||||
file=("new.txt", self.NEWFILE_CONTENTS))
|
||||
@ -1026,11 +1059,11 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.POST(self.public_url + "/foo", t="upload", mutable="true",
|
||||
file=("new.txt", self.NEWFILE_CONTENTS))
|
||||
fn = self._foo_node
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, "new.txt")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, u"new.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(fn, "new.txt",
|
||||
self.failUnlessChildContentsAre(fn, u"new.txt",
|
||||
self.NEWFILE_CONTENTS))
|
||||
d.addCallback(lambda res: self._foo_node.get("new.txt"))
|
||||
d.addCallback(lambda res: self._foo_node.get(u"new.txt"))
|
||||
def _got(newnode):
|
||||
self.failUnless(IMutableFileNode.providedBy(newnode))
|
||||
self.failUnless(newnode.is_mutable())
|
||||
@ -1044,11 +1077,11 @@ class Web(WebMixin, unittest.TestCase):
|
||||
self.POST(self.public_url + "/foo", t="upload",
|
||||
mutable="true",
|
||||
file=("new.txt", NEWER_CONTENTS)))
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, "new.txt")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, u"new.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(fn, "new.txt",
|
||||
self.failUnlessChildContentsAre(fn, u"new.txt",
|
||||
NEWER_CONTENTS))
|
||||
d.addCallback(lambda res: self._foo_node.get("new.txt"))
|
||||
d.addCallback(lambda res: self._foo_node.get(u"new.txt"))
|
||||
def _got2(newnode):
|
||||
self.failUnless(IMutableFileNode.providedBy(newnode))
|
||||
self.failUnless(newnode.is_mutable())
|
||||
@ -1085,9 +1118,9 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d.addCallback(_parse_overwrite_form_and_submit)
|
||||
d.addBoth(self.shouldRedirect, urllib.quote(self.public_url + "/foo/"))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(fn, "new.txt",
|
||||
self.failUnlessChildContentsAre(fn, u"new.txt",
|
||||
EVEN_NEWER_CONTENTS))
|
||||
d.addCallback(lambda res: self._foo_node.get("new.txt"))
|
||||
d.addCallback(lambda res: self._foo_node.get(u"new.txt"))
|
||||
def _got3(newnode):
|
||||
self.failUnless(IMutableFileNode.providedBy(newnode))
|
||||
self.failUnless(newnode.is_mutable())
|
||||
@ -1101,9 +1134,9 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.POST(self.public_url + "/foo", t="upload",
|
||||
file=("bar.txt", self.NEWFILE_CONTENTS))
|
||||
fn = self._foo_node
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, "bar.txt")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, u"bar.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(fn, "bar.txt",
|
||||
self.failUnlessChildContentsAre(fn, u"bar.txt",
|
||||
self.NEWFILE_CONTENTS))
|
||||
return d
|
||||
|
||||
@ -1144,7 +1177,7 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d.addBoth(self.shouldRedirect, "/THERE")
|
||||
fn = self._foo_node
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(fn, "new.txt",
|
||||
self.failUnlessChildContentsAre(fn, u"new.txt",
|
||||
self.NEWFILE_CONTENTS))
|
||||
return d
|
||||
|
||||
@ -1152,9 +1185,9 @@ class Web(WebMixin, unittest.TestCase):
|
||||
fn = self._foo_node
|
||||
d = self.POST(self.public_url + "/foo", t="upload",
|
||||
name="new.txt", file=self.NEWFILE_CONTENTS)
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, "new.txt")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, fn, u"new.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(fn, "new.txt",
|
||||
self.failUnlessChildContentsAre(fn, u"new.txt",
|
||||
self.NEWFILE_CONTENTS))
|
||||
return d
|
||||
|
||||
@ -1169,13 +1202,14 @@ class Web(WebMixin, unittest.TestCase):
|
||||
# make sure that nothing was added
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeKeysAre(self._foo_node,
|
||||
["bar.txt", "blockingfile",
|
||||
"empty", "sub"]))
|
||||
[u"bar.txt", u"blockingfile",
|
||||
u"empty", u"n\u00fc.txt",
|
||||
u"sub"]))
|
||||
return d
|
||||
|
||||
def test_POST_mkdir(self): # return value?
|
||||
d = self.POST(self.public_url + "/foo", t="mkdir", name="newdir")
|
||||
d.addCallback(lambda res: self._foo_node.get("newdir"))
|
||||
d.addCallback(lambda res: self._foo_node.get(u"newdir"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [])
|
||||
return d
|
||||
|
||||
@ -1223,7 +1257,7 @@ class Web(WebMixin, unittest.TestCase):
|
||||
|
||||
def test_POST_mkdir_replace(self): # return value?
|
||||
d = self.POST(self.public_url + "/foo", t="mkdir", name="sub")
|
||||
d.addCallback(lambda res: self._foo_node.get("sub"))
|
||||
d.addCallback(lambda res: self._foo_node.get(u"sub"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [])
|
||||
return d
|
||||
|
||||
@ -1234,8 +1268,8 @@ class Web(WebMixin, unittest.TestCase):
|
||||
"409 Conflict",
|
||||
"There was already a child by that name, and you asked me "
|
||||
"to not replace it")
|
||||
d.addCallback(lambda res: self._foo_node.get("sub"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, ["baz.txt"])
|
||||
d.addCallback(lambda res: self._foo_node.get(u"sub"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [u"baz.txt"])
|
||||
return d
|
||||
|
||||
def test_POST_mkdir_no_replace_field(self): # return value?
|
||||
@ -1245,15 +1279,15 @@ class Web(WebMixin, unittest.TestCase):
|
||||
"409 Conflict",
|
||||
"There was already a child by that name, and you asked me "
|
||||
"to not replace it")
|
||||
d.addCallback(lambda res: self._foo_node.get("sub"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, ["baz.txt"])
|
||||
d.addCallback(lambda res: self._foo_node.get(u"sub"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [u"baz.txt"])
|
||||
return d
|
||||
|
||||
def test_POST_mkdir_whendone_field(self):
|
||||
d = self.POST(self.public_url + "/foo",
|
||||
t="mkdir", name="newdir", when_done="/THERE")
|
||||
d.addBoth(self.shouldRedirect, "/THERE")
|
||||
d.addCallback(lambda res: self._foo_node.get("newdir"))
|
||||
d.addCallback(lambda res: self._foo_node.get(u"newdir"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [])
|
||||
return d
|
||||
|
||||
@ -1261,25 +1295,25 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.POST(self.public_url + "/foo?when_done=/THERE",
|
||||
t="mkdir", name="newdir")
|
||||
d.addBoth(self.shouldRedirect, "/THERE")
|
||||
d.addCallback(lambda res: self._foo_node.get("newdir"))
|
||||
d.addCallback(lambda res: self._foo_node.get(u"newdir"))
|
||||
d.addCallback(self.failUnlessNodeKeysAre, [])
|
||||
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)
|
||||
d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, "new.txt")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"new.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(self._foo_node, "new.txt",
|
||||
self.failUnlessChildContentsAre(self._foo_node, u"new.txt",
|
||||
contents))
|
||||
return d
|
||||
|
||||
def test_POST_put_uri_replace(self):
|
||||
contents, n, newuri = self.makefile(8)
|
||||
d = self.POST(self.public_url + "/foo", t="uri", name="bar.txt", uri=newuri)
|
||||
d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, "bar.txt")
|
||||
d.addCallback(self.failUnlessURIMatchesChild, self._foo_node, u"bar.txt")
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(self._foo_node, "bar.txt",
|
||||
self.failUnlessChildContentsAre(self._foo_node, u"bar.txt",
|
||||
contents))
|
||||
return d
|
||||
|
||||
@ -1313,7 +1347,7 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.POST(self.public_url + "/foo", t="delete", name="bar.txt")
|
||||
d.addCallback(lambda res: self._foo_node.list())
|
||||
def _check(children):
|
||||
self.failIf("bar.txt" in children)
|
||||
self.failIf(u"bar.txt" in children)
|
||||
d.addCallback(_check)
|
||||
return d
|
||||
|
||||
@ -1321,9 +1355,9 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.POST(self.public_url + "/foo", t="rename",
|
||||
from_name="bar.txt", to_name='wibble.txt')
|
||||
d.addCallback(lambda res:
|
||||
self.failIfNodeHasChild(self._foo_node, "bar.txt"))
|
||||
self.failIfNodeHasChild(self._foo_node, u"bar.txt"))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self._foo_node, "wibble.txt"))
|
||||
self.failUnlessNodeHasChild(self._foo_node, u"wibble.txt"))
|
||||
d.addCallback(lambda res: self.GET(self.public_url + "/foo/wibble.txt"))
|
||||
d.addCallback(self.failUnlessIsBarDotTxt)
|
||||
d.addCallback(lambda res: self.GET(self.public_url + "/foo/wibble.txt?t=json"))
|
||||
@ -1335,9 +1369,9 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.POST(self.public_url + "/foo", t="rename",
|
||||
from_name="bar.txt", to_name='empty')
|
||||
d.addCallback(lambda res:
|
||||
self.failIfNodeHasChild(self._foo_node, "bar.txt"))
|
||||
self.failIfNodeHasChild(self._foo_node, u"bar.txt"))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self._foo_node, "empty"))
|
||||
self.failUnlessNodeHasChild(self._foo_node, u"empty"))
|
||||
d.addCallback(lambda res: self.GET(self.public_url + "/foo/empty"))
|
||||
d.addCallback(self.failUnlessIsBarDotTxt)
|
||||
d.addCallback(lambda res: self.GET(self.public_url + "/foo/empty?t=json"))
|
||||
@ -1384,7 +1418,7 @@ class Web(WebMixin, unittest.TestCase):
|
||||
"to_name= may not contain a slash",
|
||||
)
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self._foo_node, "bar.txt"))
|
||||
self.failUnlessNodeHasChild(self._foo_node, u"bar.txt"))
|
||||
d.addCallback(lambda res: self.POST(self.public_url, t="rename",
|
||||
from_name="foo/bar.txt", to_name='george.txt'))
|
||||
d.addBoth(self.shouldFail, error.Error,
|
||||
@ -1393,11 +1427,11 @@ class Web(WebMixin, unittest.TestCase):
|
||||
"from_name= may not contain a slash",
|
||||
)
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self.public_root, "foo"))
|
||||
self.failUnlessNodeHasChild(self.public_root, u"foo"))
|
||||
d.addCallback(lambda res:
|
||||
self.failIfNodeHasChild(self.public_root, "george.txt"))
|
||||
self.failIfNodeHasChild(self.public_root, u"george.txt"))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self._foo_node, "bar.txt"))
|
||||
self.failUnlessNodeHasChild(self._foo_node, u"bar.txt"))
|
||||
d.addCallback(lambda res: self.GET(self.public_url + "/foo?t=json"))
|
||||
d.addCallback(self.failUnlessIsFooJSON)
|
||||
return d
|
||||
@ -1406,9 +1440,9 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.POST(self.public_url, t="rename",
|
||||
from_name="foo", to_name='plunk')
|
||||
d.addCallback(lambda res:
|
||||
self.failIfNodeHasChild(self.public_root, "foo"))
|
||||
self.failIfNodeHasChild(self.public_root, u"foo"))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessNodeHasChild(self.public_root, "plunk"))
|
||||
self.failUnlessNodeHasChild(self.public_root, u"plunk"))
|
||||
d.addCallback(lambda res: self.GET(self.public_url + "/plunk?t=json"))
|
||||
d.addCallback(self.failUnlessIsFooJSON)
|
||||
return d
|
||||
@ -1497,7 +1531,7 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.PUT(self.public_url + "/foo/new.txt?t=uri", new_uri)
|
||||
d.addCallback(lambda res: self.failUnlessEqual(res.strip(), new_uri))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(self._foo_node, "new.txt",
|
||||
self.failUnlessChildContentsAre(self._foo_node, u"new.txt",
|
||||
contents))
|
||||
return d
|
||||
|
||||
@ -1506,7 +1540,7 @@ class Web(WebMixin, unittest.TestCase):
|
||||
d = self.PUT(self.public_url + "/foo/bar.txt?t=uri", new_uri)
|
||||
d.addCallback(lambda res: self.failUnlessEqual(res.strip(), new_uri))
|
||||
d.addCallback(lambda res:
|
||||
self.failUnlessChildContentsAre(self._foo_node, "bar.txt",
|
||||
self.failUnlessChildContentsAre(self._foo_node, u"bar.txt",
|
||||
contents))
|
||||
return d
|
||||
|
||||
|
@ -233,6 +233,8 @@ class Directory(rend.Page):
|
||||
|
||||
def render_row(self, ctx, data):
|
||||
name, (target, metadata) = data
|
||||
name = name.encode("utf-8")
|
||||
assert not isinstance(name, unicode)
|
||||
|
||||
if self._dirnode.is_readonly():
|
||||
delete = "-"
|
||||
@ -480,9 +482,10 @@ class WebDownloadTarget:
|
||||
if self._save_to_file is not None:
|
||||
# tell the browser to save the file rather display it
|
||||
# TODO: quote save_to_file properly
|
||||
filename = self._save_to_file.encode("utf-8")
|
||||
self._req.setHeader("content-disposition",
|
||||
'attachment; filename="%s"'
|
||||
% self._save_to_file)
|
||||
% filename)
|
||||
|
||||
def write(self, data):
|
||||
self._req.write(data)
|
||||
@ -526,16 +529,16 @@ class FileDownloader(resource.Resource):
|
||||
|
||||
def render(self, req):
|
||||
gte = static.getTypeAndEncoding
|
||||
type, encoding = gte(self._name,
|
||||
static.File.contentTypes,
|
||||
static.File.contentEncodings,
|
||||
defaultType="text/plain")
|
||||
ctype, encoding = gte(self._name,
|
||||
static.File.contentTypes,
|
||||
static.File.contentEncodings,
|
||||
defaultType="text/plain")
|
||||
save_to_file = None
|
||||
if get_arg(req, "save", False):
|
||||
# TODO: make the API specification clear: should "save=" or
|
||||
# "save=false" count?
|
||||
save_to_file = self._name
|
||||
wdt = WebDownloadTarget(req, type, encoding, save_to_file)
|
||||
wdt = WebDownloadTarget(req, ctype, encoding, save_to_file)
|
||||
d = self._filenode.download(wdt)
|
||||
# exceptions during download are handled by the WebDownloadTarget
|
||||
d.addErrback(lambda why: None)
|
||||
@ -683,6 +686,7 @@ class LocalDirectoryDownloader(resource.Resource, DirnodeWalkerMixin):
|
||||
self._localdir = localdir
|
||||
|
||||
def _handle(self, path, node, metadata):
|
||||
path = tuple([p.encode("utf-8") for p in path])
|
||||
localfile = os.path.join(self._localdir, os.sep.join(path))
|
||||
if IDirectoryNode.providedBy(node):
|
||||
fileutil.make_dirs(localfile)
|
||||
@ -807,6 +811,8 @@ class POSTHandler(rend.Page):
|
||||
t = get_arg(req, "t")
|
||||
assert t is not None
|
||||
|
||||
charset = get_arg(req, "_charset", "utf-8")
|
||||
|
||||
name = get_arg(req, "name", None)
|
||||
if name and "/" in name:
|
||||
req.setResponseCode(http.BAD_REQUEST)
|
||||
@ -814,6 +820,8 @@ class POSTHandler(rend.Page):
|
||||
return "name= may not contain a slash"
|
||||
if name is not None:
|
||||
name = name.strip()
|
||||
name = name.decode(charset)
|
||||
assert isinstance(name, unicode)
|
||||
# we allow the user to delete an empty-named file, but not to create
|
||||
# them, since that's an easy and confusing mistake to make
|
||||
|
||||
@ -849,12 +857,16 @@ class POSTHandler(rend.Page):
|
||||
d = self._node.delete(name)
|
||||
d.addCallback(lambda res: "thing deleted")
|
||||
elif t == "rename":
|
||||
from_name = 'from_name' in req.fields and req.fields["from_name"].value
|
||||
from_name = get_arg(req, "from_name")
|
||||
if from_name is not None:
|
||||
from_name = from_name.strip()
|
||||
to_name = 'to_name' in req.fields and req.fields["to_name"].value
|
||||
from_name = from_name.decode(charset)
|
||||
assert isinstance(from_name, unicode)
|
||||
to_name = get_arg(req, "to_name")
|
||||
if to_name is not None:
|
||||
to_name = to_name.strip()
|
||||
to_name = to_name.decode(charset)
|
||||
assert isinstance(to_name, unicode)
|
||||
if not from_name or not to_name:
|
||||
raise RuntimeError("rename requires from_name and to_name")
|
||||
if not IDirectoryNode.providedBy(self._node):
|
||||
@ -877,13 +889,17 @@ class POSTHandler(rend.Page):
|
||||
d.addCallback(lambda res: "thing renamed")
|
||||
|
||||
elif t == "upload":
|
||||
contents = req.fields["file"]
|
||||
name = name or contents.filename
|
||||
if name is not None:
|
||||
name = name.strip()
|
||||
if not name:
|
||||
# this prohibts empty, missing, and all-whitespace filenames
|
||||
raise RuntimeError("upload requires a name")
|
||||
name = name.decode(charset)
|
||||
assert isinstance(name, unicode)
|
||||
|
||||
if "mutable" in req.fields:
|
||||
contents = req.fields["file"]
|
||||
name = name or contents.filename
|
||||
if name is not None:
|
||||
name = name.strip()
|
||||
if not name:
|
||||
raise RuntimeError("upload-mutable requires a name")
|
||||
# SDMF: files are small, and we can only upload data.
|
||||
contents.file.seek(0)
|
||||
data = contents.file.read()
|
||||
@ -910,12 +926,6 @@ class POSTHandler(rend.Page):
|
||||
return d2
|
||||
d.addCallback(_checked)
|
||||
else:
|
||||
contents = req.fields["file"]
|
||||
name = name or contents.filename
|
||||
if name is not None:
|
||||
name = name.strip()
|
||||
if not name:
|
||||
raise RuntimeError("upload requires a name")
|
||||
uploadable = FileHandle(contents.file)
|
||||
d = self._check_replacement(name)
|
||||
d.addCallback(lambda res: self._node.add_file(name, uploadable))
|
||||
@ -974,13 +984,13 @@ class DELETEHandler(rend.Page):
|
||||
d = self._node.delete(self._name)
|
||||
def _done(res):
|
||||
# what should this return??
|
||||
return "%s deleted" % self._name
|
||||
return "%s deleted" % self._name.encode("utf-8")
|
||||
d.addCallback(_done)
|
||||
def _trap_missing(f):
|
||||
f.trap(KeyError)
|
||||
req.setResponseCode(http.NOT_FOUND)
|
||||
req.setHeader("content-type", "text/plain")
|
||||
return "no such child %s" % self._name
|
||||
return "no such child %s" % self._name.encode("utf-8")
|
||||
d.addErrback(_trap_missing)
|
||||
return d
|
||||
|
||||
@ -1098,7 +1108,9 @@ class PUTHandler(rend.Page):
|
||||
return d
|
||||
|
||||
def _upload_localdir(self, node, localdir):
|
||||
# build up a list of files to upload
|
||||
# build up a list of files to upload. TODO: for now, these files and
|
||||
# directories must have UTF-8 encoded filenames: anything else will
|
||||
# cause the upload to break.
|
||||
all_files = []
|
||||
all_dirs = []
|
||||
msg = "No files to upload! %s is empty" % localdir
|
||||
@ -1112,9 +1124,13 @@ class PUTHandler(rend.Page):
|
||||
relative_root = root[len(localdir)+1:]
|
||||
path = tuple(relative_root.split(os.sep))
|
||||
for d in dirs:
|
||||
all_dirs.append(path + (d,))
|
||||
this_dir = path + (d,)
|
||||
this_dir = tuple([p.decode("utf-8") for p in this_dir])
|
||||
all_dirs.append(this_dir)
|
||||
for f in files:
|
||||
all_files.append(path + (f,))
|
||||
this_file = path + (f,)
|
||||
this_file = tuple([p.decode("utf-8") for p in this_file])
|
||||
all_files.append(this_file)
|
||||
d = defer.succeed(msg)
|
||||
for dir in all_dirs:
|
||||
if dir:
|
||||
@ -1190,7 +1206,7 @@ class VDrive(rend.Page):
|
||||
def locateChild(self, ctx, segments):
|
||||
req = inevow.IRequest(ctx)
|
||||
method = req.method
|
||||
path = segments
|
||||
path = tuple([seg.decode("utf-8") for seg in segments])
|
||||
|
||||
t = get_arg(req, "t", "")
|
||||
localfile = get_arg(req, "localfile", None)
|
||||
|
Loading…
Reference in New Issue
Block a user