d.addCallback(lambda n: n.set_children(initial_children))
return d
- def create_mutable_file(self, contents="", keysize=None):
+ def create_mutable_file(self, contents=None, keysize=None):
return self.nodemaker.create_mutable_file(contents, keysize)
def upload(self, uploadable):
"""
def create_mutable_file(contents=""):
- """Create a new mutable file with contents, get back the URI string.
- @param contents: the initial contents to place in the file.
+ """Create a new mutable file (with initial) contents, get back the
+ URI string.
+
+ @param contents: (bytestring, callable, or None): this provides the
+ initial contents of the mutable file. If 'contents' is a bytestring,
+ it will be used as-is. If 'contents' is a callable, it will be
+ invoked with the new MutableFileNode instance and is expected to
+ return a bytestring with the initial contents of the file (the
+ callable can use node.get_writekey() to decide how to encrypt the
+ initial contents, e.g. for a brand new dirnode with initial
+ children). contents=None is equivalent to an empty string. Using
+ content_maker= is more efficient than creating a mutable file and
+ setting its contents in two separate operations.
+
@return: a Deferred that fires with tne (string) SSK URI for the new
file.
"""
self._encprivkey = None
return self
- def create_with_keys(self, (pubkey, privkey), initial_contents):
+ def create_with_keys(self, (pubkey, privkey), contents):
"""Call this to create a brand-new mutable file. It will create the
- shares, find homes for them, and upload the initial contents. Returns
- a Deferred that fires (with the MutableFileNode instance you should
+ shares, find homes for them, and upload the initial contents (created
+ with the same rules as IClient.create_mutable_file() ). Returns a
+ Deferred that fires (with the MutableFileNode instance you should
use) when it completes.
"""
self._pubkey, self._privkey = pubkey, privkey
self._uri = WriteableSSKFileURI(self._writekey, self._fingerprint)
self._readkey = self._uri.readkey
self._storage_index = self._uri.storage_index
+ initial_contents = self._get_initial_contents(contents)
return self._upload(initial_contents, None)
+ def _get_initial_contents(self, contents):
+ if isinstance(contents, str):
+ return contents
+ if contents is None:
+ return ""
+ assert callable(contents), "%s should be callable, not %s" % \
+ (contents, type(contents))
+ return contents(self)
+
def _encrypt_privkey(self, writekey, privkey):
enc = AES(writekey)
crypttext = enc.process(privkey)
return node
- def create_mutable_file(self, contents="", keysize=None):
+ def create_mutable_file(self, contents=None, keysize=None):
n = MutableFileNode(self.storage_broker, self.secret_holder,
self.default_encoding_parameters, self.history)
d = self.key_generator.generate(keysize)
d.addCallback(_created)
return d
+ def test_create_with_initial_contents_function(self):
+ data = "initial contents"
+ def _make_contents(n):
+ self.failUnless(isinstance(n, MutableFileNode))
+ key = n.get_writekey()
+ self.failUnless(isinstance(key, str), key)
+ self.failUnlessEqual(len(key), 16) # AES key size
+ return data
+ d = self.nodemaker.create_mutable_file(_make_contents)
+ def _created(n):
+ return n.download_best_version()
+ d.addCallback(_created)
+ d.addCallback(lambda data2: self.failUnlessEqual(data2, data))
+ return d
+
def test_create_with_too_large_contents(self):
BIG = "a" * (self.OLD_MAX_SEGMENT_SIZE + 1)
d = self.nodemaker.create_mutable_file(BIG)