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
# 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 == "":
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)
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))])
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
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)
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)
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):
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)
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)
else:
assert len(e) == 3
name, child, new_metadata = e
+ assert isinstance(name, unicode)
if name in children:
metadata = children[name][1].copy()
else:
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)
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()
"""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()
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)
"""
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
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.
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() ).
"""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
"""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
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
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)
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
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
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):
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"]}))
# 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)
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()))
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
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:
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()
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):
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)
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):
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
# 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
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)
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
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")
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)
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)
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
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
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
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/
# 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
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)
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
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('')
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
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
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
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):
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
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
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
"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):
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))
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)
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):
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())
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())
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,
% 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,
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, 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, "new.txt",
+ 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(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())
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())
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())
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
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
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
# 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
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
"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?
"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
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
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
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"))
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"))
"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,
"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
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
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
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
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 = "-"
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)
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)
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)
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)
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
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):
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()
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))
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
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
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:
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)