[Zope3-checkins]
SVN: Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/
Fixed two bugs in FTP reported by Roger which pushed
Michael Kerrin
michael.kerrin at openapp.biz
Fri Feb 24 07:52:31 EST 2006
Log message for revision 41769:
Fixed two bugs in FTP reported by Roger which pushed
me to finishing this work.
Changed:
U Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/ftp.py
U Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/demofs.py
U Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/test_zope_ftp.py
U Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/test_zopetrial.py
-=-
Modified: Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/ftp.py
===================================================================
--- Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/ftp.py 2006-02-24 01:44:33 UTC (rev 41768)
+++ Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/ftp.py 2006-02-24 12:52:30 UTC (rev 41769)
@@ -15,6 +15,7 @@
"""
__docformat__="restructuredtext"
+import time
from cStringIO import StringIO
from types import StringTypes
@@ -22,6 +23,8 @@
from zope.publisher.interfaces import NotFound
from zope.security.interfaces import Unauthorized
+from zope.exceptions import DuplicationError
+from zope.app.copypastemove import ItemNotFoundError
from twisted.internet import threads, defer
from twisted.protocols import ftp
@@ -107,33 +110,41 @@
def _path(self, path):
return '/' + '/'.join(path)
+ def _perm_failed(self, failure):
+ raise ftp.PermissionDeniedError(self._path(path))
+
def makeDirectory(self, path):
- def failed(failure):
- raise ftp.PermissionDeniedError(self._path(path))
- d = threads.deferToThread(self.fs_access.mkdir, self._path(path))
- d.addErrback(failed)
+ p = self._path(path)
+ d = threads.deferToThread(self.fs_access.mkdir, p)
+ d.addErrback(self._perm_failed, p)
+
return d
def removeDirectory(self, path):
- def failed(failure):
- raise ftp.PermissionDeniedError(self._path(path))
- d = threads.deferToThread(self.fs_access.rmdir, self._path(path))
- d.addErrback(failed)
+ p = self._path(path)
+ d = threads.deferToThread(self.fs_access.rmdir, p)
+ d.addErrback(self._perm_failed, p)
+
return d
def removeFile(self, path):
- def failed(failure):
- raise ftp.PermissionDeniedError(self._path(path))
- d = threads.deferToThread(self.fs_access.remove, self._path(path))
- d.addErrback(failed)
+ p = self._path(path)
+ d = threads.deferToThread(self.fs_access.remove, p)
+ d.addErrback(self._perm_failed, p)
+
return d
def rename(self, fromPath, toPath):
def failed(failure):
- raise ftp.PermissionDeniedError(self._path(path))
+ if failure.type is DuplicationError:
+ raise ftp.PermissionDeniedError(self._path(toPath))
+ elif failure.type is ItemNotFoundError:
+ raise ftp.FileNotFoundError(self._path(fromPath))
+ raise ftp.PermissionDeniedError(self._path(fromPath))
+
d = threads.deferToThread(self.fs_access.rename,
self._path(fromPath),
self._path(toPath))
@@ -170,13 +181,21 @@
ent.append(val)
return result['name'].encode('utf-8'), ent
- def _stat(self, path, keys):
- result = self._gotlisting(self.fs_access.lsinfo(path), keys)
- return result[1]
-
def stat(self, path, keys=()):
- return threads.deferToThread(self._stat, self._path(path), keys)
+ p = self._path(path)
+ d = threads.deferToThread(self.fs_access.lsinfo, p)
+ d.addCallback(self._gotlisting, keys)
+ d.addCallback(lambda result: result[1])
+ d.addErrback(self._perm_failed, p)
+
+ return d
+
+ def _list(self, path):
+ if self.fs_access.type(path) == 'd':
+ return self.fs_access.ls(path)
+ return [self.fs_access.lsinfo(path)]
+
def list(self, path, keys=()):
def gotresults(results, keys):
ret = []
@@ -189,7 +208,7 @@
raise ftp.FileNotFoundError(self._path(path))
raise ftp.PermissionDeniedError(self._path(path))
- d = threads.deferToThread(self.fs_access.ls, self._path(path))
+ d = threads.deferToThread(self._list, self._path(path))
d.addCallback(gotresults, keys)
d.addErrback(goterror)
@@ -213,7 +232,7 @@
def _list_modified(self, value):
mtime = value.get('mtime', None)
if mtime:
- return int(mtime.strftime('%s'))
+ return int(time.mktime(mtime.utctimetuple()))
return 0
def _list_permissions(self, value):
@@ -242,24 +261,33 @@
ret |= 0040000
return ret
- def _checkFileReadAccess(self, fs_access, p):
- # run all these methods within the one thread.
- readable = fs_access.readable(p)
+ def _checkFileReadAccess(self, fs_access, path):
+ # run all these methods within the application thread
+ readable = fs_access.readable(path)
if not readable:
- raise ftp.PermissionDeniedError(p)
+ raise ftp.PermissionDeniedError(path)
- filetype = fs_access.type(p)
+ filetype = fs_access.type(path)
if filetype == 'd':
- raise ftp.FileNotFoundError(p)
+ raise ftp.FileNotFoundError(path)
- return ReadFileObj(fs_access, p)
+ return ReadFileObj(fs_access, path)
def openForReading(self, path):
p = self._path(path)
- return threads.deferToThread(self._checkFileReadAccess,
- self.fs_access, p)
+ def failed(failure):
+ if isinstance(failure.type, ftp.FTPCmdError):
+ raise failure
+ elif isinstance(failure.type, NotFound):
+ raise ftp.FileNotFoundError(p)
+ raise ftp.PermissionDeniedError(p)
+ d = threads.deferToThread(self._checkFileReadAccess, self.fs_access, p)
+ d.addErrback(failed)
+
+ return d
+
def openForWriting(self, path):
p = self._path(path)
@@ -268,11 +296,8 @@
return WriteFileObj(self.fs_access, p)
raise ftp.PermissionDeniedError(p)
- def failed(failure):
- raise ftp.PermissionDeniedError(p)
-
d = threads.deferToThread(self.fs_access.writable, p)
d.addCallback(succeed)
- d.addErrback(failed)
+ d.addErrback(self._perm_failed, p)
return d
Modified: Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/demofs.py
===================================================================
--- Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/demofs.py 2006-02-24 01:44:33 UTC (rev 41768)
+++ Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/demofs.py 2006-02-24 12:52:30 UTC (rev 41769)
@@ -17,6 +17,9 @@
from zope.security.interfaces import Unauthorized
from zope.publisher.interfaces import NotFound
+from zope.exceptions import DuplicationError
+from zope.app.copypastemove import ItemNotFoundError
+
from zope.app.twisted.interfaces import IFileSystem
from zope.interface import implements
@@ -155,7 +158,14 @@
def ls(self, path, filter=None):
"See zope.server.interfaces.ftp.IFileSystem"
- f = self.getdir(path)
+ if self.type(path) == 'd':
+ f = self.getdir(path)
+ else:
+ path = path.split('/')
+ name = path.pop()
+ f = self.getdir('/'.join(path))
+ return [self._lsinfo(name, f.files[name])]
+
if filter is None:
return [self._lsinfo(name, f.files[name])
for name in f
@@ -236,9 +246,11 @@
newdir = self.getwdir(newpath)
if oldname not in olddir.files:
- raise OSError("Not exists:", oldname)
+ ## raise exception that we are likely to get in Zope3
+ raise ItemNotFoundError(olddir, oldname)
if newname in newdir.files:
- raise OSError("Already exists:", newname)
+ ## raise exception that we are likely to get in Zope3
+ raise DuplicationError("%s is already in use" % newname)
newdir.files[newname] = olddir.files[oldname]
del olddir.files[oldname]
Modified: Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/test_zope_ftp.py
===================================================================
--- Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/test_zope_ftp.py 2006-02-24 01:44:33 UTC (rev 41768)
+++ Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/test_zope_ftp.py 2006-02-24 12:52:30 UTC (rev 41769)
@@ -13,12 +13,13 @@
##############################################################################
"""This file basically contains FTP functional tests.
-$Id:$
+$Id$
"""
__docformat__="restructuredtext"
from cStringIO import StringIO
import posixpath
import unittest
+from datetime import datetime
from twisted.test import test_ftp
from twisted.internet import reactor, protocol, defer
@@ -169,7 +170,57 @@
responseLines = wait(self.client.queueStringCommand('SIZE /'))
self.assertEqual(['213 0'] , responseLines)
+ def test_RENAME(self):
+ data = StringIO('x' * 20)
+ self.rootfs.writefile('/file.txt', data)
+ self._authLogin()
+ responseLines = wait(
+ self.client.queueStringCommand('RNFR /file.txt'))
+ self.assertEqual(
+ ['350 Requested file action pending further information.'],
+ responseLines)
+ responseLines = wait(
+ self.client.queueStringCommand('RNTO /newfile.txt'))
+ self.assertEqual(
+ ['250 Requested File Action Completed OK'], responseLines)
+
+ file = self.rootfs.get('newfile.txt')
+ self.assertEqual(file.data, data.getvalue())
+ self.assertEqual(['newfile.txt'], self.rootfs.names('/'))
+
+ def test_RENAME_duplicate(self):
+ data = StringIO('x' * 20)
+ self.rootfs.writefile('/file.txt', data)
+ datadest = StringIO('y' * 20)
+ self.rootfs.writefile('/newfile.txt', datadest)
+
+ self._authLogin()
+ responseLines = wait(
+ self.client.queueStringCommand('RNFR /file.txt'))
+ self.assertEqual(
+ ['350 Requested file action pending further information.'],
+ responseLines)
+ deferred = self.client.queueStringCommand('RNTO /newfile.txt')
+ responseLines = self._waitForCommandFailure(deferred)
+ self.assertEqual(
+ ['550 /newfile.txt: Permission denied.'], responseLines)
+
+ def test_RENAME_nosource_file(self):
+ self._authLogin()
+
+ responseLines = wait(
+ self.client.queueStringCommand('RNFR /file.txt'))
+ self.assertEqual(
+ ['350 Requested file action pending further information.'],
+ responseLines)
+ deferred = self.client.queueStringCommand('RNTO /newfile.txt')
+ responseLines = self._waitForCommandFailure(deferred)
+ self.assertEqual(
+ ['550 /file.txt: No such file or directory.'], responseLines)
+
+
+
class FTPServerPasvDataConnectionTestCase(FTPServerTestCase,
test_ftp.FTPServerPasvDataConnectionTestCase):
@@ -222,11 +273,41 @@
wait(defer.gatherResults([d, downloader.d]))
self.assertEqual('', downloader.buffer)
+ def testLIST_with_mtime(self):
+ self._anonymousLogin()
+
+ # Set up file with modification date set.
+ self.rootfs.writefile_nocheck('/foo', StringIO('x' * 20))
+ foo = self.rootfs.get('/foo')
+ now = datetime.now()
+ foo.modified = now
+
+ # Download a listing for foo.
+ downloader = self._makeDataConnection()
+ d = self.client.queueStringCommand('LIST /foo')
+ wait(defer.gatherResults([d, downloader.d]))
+
+ # check the data returned especially the date.
+ buf = downloader.buffer[:-2].split('\r\n')
+ self.assertEqual(len(buf), 1)
+ buf = buf[0]
+ buf = buf.split(None, 5)[5]
+ self.assertEqual(buf, '%s foo' % now.strftime('%b %d %H:%M'))
+
+ def testLIST_nofile(self):
+ self._anonymousLogin()
+
+ downloader = self._makeDataConnection()
+ d = self.client.queueStringCommand('LIST /foo')
+ responseLines = self._waitForCommandFailure(d)
+
+ self.assertEqual(['550 /foo: No such file or directory.'],
+ responseLines)
+
def testManyLargeDownloads(self):
# Login
self._anonymousLogin()
-
# Download a range of different size files
for size in range(100000, 110000, 500):
self.rootfs.writefile_nocheck('/%d.txt' % (size,),
Modified: Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/test_zopetrial.py
===================================================================
--- Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/test_zopetrial.py 2006-02-24 01:44:33 UTC (rev 41768)
+++ Zope3/branches/mkerrin-remove_trial_tests/src/zope/app/twisted/ftp/tests/test_zopetrial.py 2006-02-24 12:52:30 UTC (rev 41769)
@@ -27,7 +27,7 @@
Michael Kerrin <michael.kerrin at openapp.biz>
-$Id:$
+$Id$
"""
__docformat__="restructuredtext"
More information about the Zope3-Checkins
mailing list