← Back to team overview

duplicity-team team mailing list archive

[Merge] lp:~mgorse/duplicity/0.8-series into lp:duplicity

 

Mgorse has proposed merging lp:~mgorse/duplicity/0.8-series into lp:duplicity.

Commit message:
imap: python3 fixes

Requested reviews:
  duplicity-team (duplicity-team)

For more details, see:
https://code.launchpad.net/~mgorse/duplicity/0.8-series/+merge/367433

Also fix bug 1828869: refresh CollectionsStatus after sync
-- 
Your team duplicity-team is requested to review the proposed merge of lp:~mgorse/duplicity/0.8-series into lp:duplicity.
=== modified file 'bin/duplicity'
--- bin/duplicity	2019-05-05 12:16:14 +0000
+++ bin/duplicity	2019-05-14 20:44:56 +0000
@@ -1156,8 +1156,14 @@
         except collections.CollectionsError:
             # With zero or multiple chains at this time, do a full sync
             return True
-        return parsed.end_time >= target_chain.start_time and \
-            parsed.start_time <= target_chain.end_time
+        if parsed.start_time is None and parsed.end_time is None:
+            start_time = end_time = parsed.time
+        else:
+            start_time = parsed.start_time
+            end_time = parsed.end_time
+
+        return end_time >= target_chain.start_time and \
+            start_time <= target_chain.end_time
 
     def get_metafiles(filelist):
         u"""

=== modified file 'duplicity/backends/imapbackend.py'
--- duplicity/backends/imapbackend.py	2018-11-29 19:00:15 +0000
+++ duplicity/backends/imapbackend.py	2019-05-14 20:44:56 +0000
@@ -32,12 +32,19 @@
 import io
 import getpass
 import email
+import email.encoders
+import email.mime.multipart
 from email.parser import Parser
 try:
     from email.policy import default  # pylint: disable=import-error
 except:
     pass
 
+# TODO: should probably change use of socket.sslerror instead of doing this
+if sys.version_info.major >= 3:
+    import ssl
+    socket.sslerror = ssl.SSLError
+
 import duplicity.backend
 from duplicity import globals
 from duplicity import log
@@ -107,18 +114,18 @@
             log.Info(u"IMAP connected")
 
     def prepareBody(self, f, rname):
-        mp = email.MIMEMultipart.MIMEMultipart()
+        mp = email.mime.multipart.MIMEMultipart()
 
         # I am going to use the remote_dir as the From address so that
         # multiple archives can be stored in an IMAP account and can be
         # accessed separately
         mp[u"From"] = self.remote_dir
-        mp[u"Subject"] = rname
+        mp[u"Subject"] = rname.decode()
 
-        a = email.MIMEBase.MIMEBase(u"application", u"binary")
+        a = email.mime.multipart.MIMEBase(u"application", u"binary")
         a.set_payload(f.read())
 
-        email.Encoders.encode_base64(a)
+        email.encoders.encode_base64(a)
 
         mp.attach(a)
 
@@ -137,7 +144,7 @@
                 # If we don't select the IMAP folder before
                 # append, the message goes into the INBOX.
                 self.conn.select(globals.imap_mailbox)
-                self.conn.append(globals.imap_mailbox, None, None, body)
+                self.conn.append(globals.imap_mailbox, None, None, body.encode())
                 break
             except (imaplib.IMAP4.abort, socket.error, socket.sslerror):
                 allowedTimeout -= 1
@@ -176,9 +183,9 @@
                     raise Exception(list[0])
                 rawbody = list[0][1]
 
-                p = email.Parser.Parser()
+                p = Parser()
 
-                m = p.parsestr(rawbody)
+                m = p.parsestr(rawbody.decode())
 
                 mp = m.get_payload(0)
 
@@ -199,6 +206,7 @@
 
         tfile = local_path.open(u"wb")
         tfile.write(body)
+        tfile.close()
         local_path.setdata()
         log.Info(u"IMAP mail with '%s' subject fetched" % remote_filename)
 
@@ -215,10 +223,10 @@
         (result, list) = self.conn.search(None, u'FROM', self.remote_dir)
         if result != u"OK":
             raise Exception(list[0])
-        if list[0] == u'':
+        if list[0] == b'':
             return ret
-        nums = list[0].strip().split(u" ")
-        set = u"%s:%s" % (nums[0], nums[-1])
+        nums = list[0].strip().split(b" ")
+        set = b"%s:%s" % (nums[0], nums[-1])
         (result, list) = self.conn.fetch(set, u"(BODY[HEADER])")
         if result != u"OK":
             raise Exception(list[0])
@@ -227,9 +235,9 @@
             if (len(msg) == 1):
                 continue
             if sys.version_info.major >= 3:
-                headers = Parser(policy=default).parsestr(msg[1])  # pylint: disable=unsubscriptable-object
+                headers = Parser(policy=default).parsestr(msg[1].decode(u"unicode-escape"))  # pylint: disable=unsubscriptable-object
             else:
-                headers = Parser().parsestr(msg[1])  # pylint: disable=unsubscriptable-object
+                headers = Parser().parsestr(msg[1].decode(u"unicode-escape"))  # pylint: disable=unsubscriptable-object
             subj = headers[u"subject"]
             header_from = headers[u"from"]
 

=== modified file 'duplicity/patchdir.py'
--- duplicity/patchdir.py	2019-02-21 21:48:53 +0000
+++ duplicity/patchdir.py	2019-05-14 20:44:56 +0000
@@ -123,7 +123,10 @@
     # The next tar_info is stored in this one element list so
     # Multivol_Filelike below can update it.  Any StopIterations will
     # be passed upwards.
-    tarinfo_list = [next(tar_iter)]
+    try:
+        tarinfo_list = [next(tar_iter)]
+    except StopIteration:
+        return
 
     while 1:
         # This section relevant when a multivol diff is last in tar
@@ -349,7 +352,10 @@
 
     def __next__(self):
         if not self.tarfile:
-            self.set_tarfile()
+            try:
+                self.set_tarfile()
+            except StopIteration:
+                return
         try:
             return next(self.tar_iter)
         except StopIteration:


Follow ups