Copy all daira code from other branch...

This commit is contained in:
David Stainton 2015-05-26 09:42:19 -07:00 committed by Daira Hopwood
parent 1a5726eda4
commit 6aefeb2ea7
2 changed files with 37 additions and 10 deletions

View File

@ -5,6 +5,7 @@ from collections import deque
from twisted.internet import defer, reactor, task from twisted.internet import defer, reactor, task
from twisted.python.failure import Failure from twisted.python.failure import Failure
from twisted.python import runtime
from twisted.application import service from twisted.application import service
from allmydata.interfaces import IDirectoryNode, NoSuchChildError, ExistingChildError from allmydata.interfaces import IDirectoryNode, NoSuchChildError, ExistingChildError
@ -16,6 +17,24 @@ from allmydata.immutable.upload import FileName, Data
from allmydata import backupdb, magicpath from allmydata import backupdb, magicpath
def get_inotify_module():
try:
if sys.platform == "win32":
from allmydata.windows import inotify
elif runtime.platform.supportsINotify():
from twisted.internet import inotify
else:
raise NotImplementedError("filesystem notification needed for drop-upload is not supported.\n"
"This currently requires Linux or Windows.")
return inotify
except (ImportError, AttributeError) as e:
log.msg(e)
if sys.platform == "win32":
raise NotImplementedError("filesystem notification needed for drop-upload is not supported.\n"
"Windows support requires at least Vista, and has only been tested on Windows 7.")
raise
class DropUploader(service.MultiService): class DropUploader(service.MultiService):
name = 'drop-upload' name = 'drop-upload'

View File

@ -14,6 +14,7 @@ from allmydata.test.no_network import GridTestMixin
from allmydata.test.common_util import ReallyEqualMixin, NonASCIIPathMixin from allmydata.test.common_util import ReallyEqualMixin, NonASCIIPathMixin
from allmydata.test.common import ShouldFailMixin from allmydata.test.common import ShouldFailMixin
from allmydata.frontends import drop_upload
from allmydata.frontends.drop_upload import DropUploader from allmydata.frontends.drop_upload import DropUploader
from allmydata import backupdb from allmydata import backupdb
from allmydata.util.fileutil import abspath_expanduser_unicode from allmydata.util.fileutil import abspath_expanduser_unicode
@ -146,7 +147,7 @@ class DropUploadTestMixin(GridTestMixin, ShouldFailMixin, ReallyEqualMixin, NonA
d2 = defer.Deferred() d2 = defer.Deferred()
self.uploader.set_uploaded_callback(d2.callback, ignore_count=0) self.uploader.set_uploaded_callback(d2.callback, ignore_count=0)
os.rename(empty_tree_dir, new_empty_tree_dir) os.rename(empty_tree_dir, new_empty_tree_dir)
self.notify_close_write(to_filepath(new_empty_tree_dir)) self.notify(to_filepath(new_empty_tree_dir), self.inotify.IN_CLOSE_WRITE) # XXX
return d2 return d2
d.addCallback(_check_move_empty_tree) d.addCallback(_check_move_empty_tree)
d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('drop_upload.objects_uploaded'), 1)) d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('drop_upload.objects_uploaded'), 1))
@ -160,7 +161,7 @@ class DropUploadTestMixin(GridTestMixin, ShouldFailMixin, ReallyEqualMixin, NonA
d2 = defer.Deferred() d2 = defer.Deferred()
self.uploader.set_uploaded_callback(d2.callback, ignore_count=1) self.uploader.set_uploaded_callback(d2.callback, ignore_count=1)
os.rename(small_tree_dir, new_small_tree_dir) os.rename(small_tree_dir, new_small_tree_dir)
self.notify_close_write(to_filepath(new_small_tree_dir)) self.notify(to_filepath(new_small_tree_dir), self.inotify.IN_CLOSE_WRITE)
return d2 return d2
d.addCallback(_check_move_small_tree) d.addCallback(_check_move_small_tree)
d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('drop_upload.objects_uploaded'), 3)) d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('drop_upload.objects_uploaded'), 3))
@ -172,7 +173,7 @@ class DropUploadTestMixin(GridTestMixin, ShouldFailMixin, ReallyEqualMixin, NonA
d2 = defer.Deferred() d2 = defer.Deferred()
self.uploader.set_uploaded_callback(d2.callback, ignore_count=0) self.uploader.set_uploaded_callback(d2.callback, ignore_count=0)
fileutil.write(abspath_expanduser_unicode(u"another", base=new_small_tree_dir), "file") fileutil.write(abspath_expanduser_unicode(u"another", base=new_small_tree_dir), "file")
self.notify_close_write(to_filepath(abspath_expanduser_unicode(u"another", base=new_small_tree_dir))) self.notify(to_filepath(abspath_expanduser_unicode(u"another", base=new_small_tree_dir)), self.inotify.IN_CLOSE_WRITE)
return d2 return d2
d.addCallback(_check_moved_tree_is_watched) d.addCallback(_check_moved_tree_is_watched)
d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('drop_upload.objects_uploaded'), 4)) d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('drop_upload.objects_uploaded'), 4))
@ -205,7 +206,7 @@ class DropUploadTestMixin(GridTestMixin, ShouldFailMixin, ReallyEqualMixin, NonA
self.uploader.set_uploaded_callback(d2.callback) self.uploader.set_uploaded_callback(d2.callback)
test_file = abspath_expanduser_unicode(u"what", base=self.local_dir) test_file = abspath_expanduser_unicode(u"what", base=self.local_dir)
fileutil.write(test_file, "meow") fileutil.write(test_file, "meow")
self.notify_close_write(to_filepath(test_file)) self.notify(to_filepath(test_file), self.inotify.IN_CLOSE_WRITE)
return d2 return d2
d.addCallback(create_file) d.addCallback(create_file)
d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('drop_upload.objects_uploaded'), 1)) d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('drop_upload.objects_uploaded'), 1))
@ -243,7 +244,7 @@ class DropUploadTestMixin(GridTestMixin, ShouldFailMixin, ReallyEqualMixin, NonA
d2 = defer.Deferred() d2 = defer.Deferred()
self.uploader.set_uploaded_callback(d2.callback, ignore_count=0) self.uploader.set_uploaded_callback(d2.callback, ignore_count=0)
os.rename(empty_tree_dir, new_empty_tree_dir) os.rename(empty_tree_dir, new_empty_tree_dir)
self.notify_close_write(to_filepath(new_empty_tree_dir)) self.notify(to_filepath(new_empty_tree_dir), self.inotify.IN_CLOSE_WRITE) # XXX
return d2 return d2
d.addCallback(_check_move_empty_tree) d.addCallback(_check_move_empty_tree)
d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('drop_upload.objects_uploaded'), 1)) d.addCallback(lambda ign: self.failUnlessReallyEqual(self._get_count('drop_upload.objects_uploaded'), 1))
@ -335,7 +336,7 @@ class DropUploadTestMixin(GridTestMixin, ShouldFailMixin, ReallyEqualMixin, NonA
if temporary and sys.platform == "win32": if temporary and sys.platform == "win32":
os.unlink(path_u) os.unlink(path_u)
fileutil.flush_volume(path_u) fileutil.flush_volume(path_u)
self.notify_close_write(path) self.notify(path, self.inotify.IN_CLOSE_WRITE)
if temporary: if temporary:
d.addCallback(lambda ign: self.shouldFail(NoSuchChildError, 'temp file not uploaded', None, d.addCallback(lambda ign: self.shouldFail(NoSuchChildError, 'temp file not uploaded', None,
@ -360,7 +361,6 @@ class MockTest(DropUploadTestMixin, unittest.TestCase):
DropUploadTestMixin.setUp(self) DropUploadTestMixin.setUp(self)
self.inotify = fake_inotify self.inotify = fake_inotify
def notify(self, path, mask): def notify(self, path, mask):
self.uploader._notifier.event(path, mask) self.uploader._notifier.event(path, mask)
@ -391,7 +391,13 @@ class MockTest(DropUploadTestMixin, unittest.TestCase):
DropUploader, client, 'URI:LIT:foo', errors_dir, magicfolderdb, inotify=fake_inotify) DropUploader, client, 'URI:LIT:foo', errors_dir, magicfolderdb, inotify=fake_inotify)
self.shouldFail(AssertionError, 'readonly upload.dircap', 'is not a writecap to a directory', self.shouldFail(AssertionError, 'readonly upload.dircap', 'is not a writecap to a directory',
DropUploader, client, readonly_dircap, errors_dir, magicfolderdb, inotify=fake_inotify) DropUploader, client, readonly_dircap, errors_dir, magicfolderdb, inotify=fake_inotify)
d.addCallback(_check_errors)
def _not_implemented():
raise NotImplementedError("blah")
self.patch(drop_upload, 'get_inotify_module', _not_implemented)
self.shouldFail(NotImplementedError, 'unsupported', 'blah',
DropUploader, client, upload_dircap, errors_dir, magicfolderdb)
d.addCallback(_check_errors)
return d return d
@ -400,11 +406,13 @@ class RealTest(DropUploadTestMixin, unittest.TestCase):
def setUp(self): def setUp(self):
DropUploadTestMixin.setUp(self) DropUploadTestMixin.setUp(self)
self.inotify = None self.inotify = drop_upload.get_inotify_module()
def notify(self, path, mask): def notify(self, path, mask):
# Writing to the filesystem causes the notification. # Writing to the filesystem causes the notification.
pass pass
if sys.platform != "win32" and not runtime.platform.supportsINotify(): try:
drop_upload.get_inotify_module()
except NotImplementedError:
RealTest.skip = "Drop-upload support can only be tested for-real on an OS that supports inotify or equivalent." RealTest.skip = "Drop-upload support can only be tested for-real on an OS that supports inotify or equivalent."