← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/txpkgupload:py3-sftp-paths into txpkgupload:master

 

Colin Watson has proposed merging ~cjwatson/txpkgupload:py3-sftp-paths into txpkgupload:master.

Commit message:
Handle FTP/SFTP path type mismatch in UploadFileSystem

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/txpkgupload/+git/txpkgupload/+merge/392996

zope.server's FTP implementation passes paths as text, while Twisted's SFTP implementation passes paths as bytes.  Resolve this mismatch in a semi-reasonable way.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/txpkgupload:py3-sftp-paths into txpkgupload:master.
diff --git a/src/txpkgupload/filesystem.py b/src/txpkgupload/filesystem.py
index eccf4b7..b80837f 100644
--- a/src/txpkgupload/filesystem.py
+++ b/src/txpkgupload/filesystem.py
@@ -29,6 +29,19 @@ class UploadFileSystem:
         return full_path
 
     def _sanitize(self, path):
+        if isinstance(path, bytes):
+            # zope.server's FTP implementation seems to decode all commands
+            # (including the paths they contain) to text using UTF-8,
+            # effectively assuming the recommendation in RFC 2640 except
+            # without the feature negotiation part.  However, Twisted's SFTP
+            # implementation leaves paths as bytes.  Since in practice
+            # legitimate uses of txpkgupload will only involve ASCII paths,
+            # and since UTF-8 has low risk of undetected decoding errors,
+            # let's try to decode SFTP paths as UTF-8.
+            try:
+                path = path.decode('UTF-8')
+            except UnicodeDecodeError:
+                raise NotImplementedError('Paths must be encoded using UTF-8')
         if path.startswith('/'):
             path = path[1:]
         path = os.path.normpath(path)
diff --git a/src/txpkgupload/tests/test_twistedsftp.py b/src/txpkgupload/tests/test_twistedsftp.py
index 3ddeeb0..01b5e20 100644
--- a/src/txpkgupload/tests/test_twistedsftp.py
+++ b/src/txpkgupload/tests/test_twistedsftp.py
@@ -9,6 +9,7 @@ import os
 
 import fixtures
 from lazr.sshserver.sftp import FileIsADirectory
+import six
 import testtools
 
 from txpkgupload.twistedsftp import SFTPServer
@@ -73,4 +74,5 @@ class TestSFTPServer(testtools.TestCase):
         upload_file = self.sftp_server.openFile('bar/foo', None, None)
         err = self.assertRaises(
             FileIsADirectory, upload_file.writeChunk, 0, b"This is a test")
-        self.assertEqual("File is a directory: '%s'" % dir_name, str(err))
+        self.assertEqual(
+            "File is a directory: %r" % six.ensure_text(dir_name), str(err))