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

Proposed by Mgorse on 2019-05-14
Status: Merged
Merged at revision: 1364
Proposed branch: lp:~mgorse/duplicity/0.8-series
Merge into: lp:duplicity
Diff against target: 173 lines (+39/-18)
4 files modified
bin/duplicity (+9/-2)
duplicity/backends/imapbackend.py (+20/-12)
duplicity/patchdir.py (+8/-2)
setup.py (+2/-2)
To merge this branch: bzr merge lp:~mgorse/duplicity/0.8-series
Reviewer Review Type Date Requested Status
duplicity-team 2019-05-14 Pending
Review via email: mp+367433@code.launchpad.net

Commit message

imap: python3 fixes

Description of the change

Also fix bug 1828869: refresh CollectionsStatus after sync

To post a comment you must log in.
lp:~mgorse/duplicity/0.8-series updated on 2019-05-17
1364. By Mgorse on 2019-05-17

setup.py: allow python 2.7 again

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/duplicity'
2--- bin/duplicity 2019-05-05 12:16:14 +0000
3+++ bin/duplicity 2019-05-17 14:00:52 +0000
4@@ -1156,8 +1156,14 @@
5 except collections.CollectionsError:
6 # With zero or multiple chains at this time, do a full sync
7 return True
8- return parsed.end_time >= target_chain.start_time and \
9- parsed.start_time <= target_chain.end_time
10+ if parsed.start_time is None and parsed.end_time is None:
11+ start_time = end_time = parsed.time
12+ else:
13+ start_time = parsed.start_time
14+ end_time = parsed.end_time
15+
16+ return end_time >= target_chain.start_time and \
17+ start_time <= target_chain.end_time
18
19 def get_metafiles(filelist):
20 u"""
21@@ -1338,6 +1344,7 @@
22 globals.backend.pre_process_download(local_missing)
23 for fn in local_missing:
24 copy_to_local(fn)
25+ col_stats.set_values()
26 else:
27 if local_missing:
28 log.Notice(_(u"Sync would copy the following from remote to local:") +
29
30=== modified file 'duplicity/backends/imapbackend.py'
31--- duplicity/backends/imapbackend.py 2018-11-29 19:00:15 +0000
32+++ duplicity/backends/imapbackend.py 2019-05-17 14:00:52 +0000
33@@ -32,12 +32,19 @@
34 import io
35 import getpass
36 import email
37+import email.encoders
38+import email.mime.multipart
39 from email.parser import Parser
40 try:
41 from email.policy import default # pylint: disable=import-error
42 except:
43 pass
44
45+# TODO: should probably change use of socket.sslerror instead of doing this
46+if sys.version_info.major >= 3:
47+ import ssl
48+ socket.sslerror = ssl.SSLError
49+
50 import duplicity.backend
51 from duplicity import globals
52 from duplicity import log
53@@ -107,18 +114,18 @@
54 log.Info(u"IMAP connected")
55
56 def prepareBody(self, f, rname):
57- mp = email.MIMEMultipart.MIMEMultipart()
58+ mp = email.mime.multipart.MIMEMultipart()
59
60 # I am going to use the remote_dir as the From address so that
61 # multiple archives can be stored in an IMAP account and can be
62 # accessed separately
63 mp[u"From"] = self.remote_dir
64- mp[u"Subject"] = rname
65+ mp[u"Subject"] = rname.decode()
66
67- a = email.MIMEBase.MIMEBase(u"application", u"binary")
68+ a = email.mime.multipart.MIMEBase(u"application", u"binary")
69 a.set_payload(f.read())
70
71- email.Encoders.encode_base64(a)
72+ email.encoders.encode_base64(a)
73
74 mp.attach(a)
75
76@@ -137,7 +144,7 @@
77 # If we don't select the IMAP folder before
78 # append, the message goes into the INBOX.
79 self.conn.select(globals.imap_mailbox)
80- self.conn.append(globals.imap_mailbox, None, None, body)
81+ self.conn.append(globals.imap_mailbox, None, None, body.encode())
82 break
83 except (imaplib.IMAP4.abort, socket.error, socket.sslerror):
84 allowedTimeout -= 1
85@@ -176,9 +183,9 @@
86 raise Exception(list[0])
87 rawbody = list[0][1]
88
89- p = email.Parser.Parser()
90+ p = Parser()
91
92- m = p.parsestr(rawbody)
93+ m = p.parsestr(rawbody.decode())
94
95 mp = m.get_payload(0)
96
97@@ -199,6 +206,7 @@
98
99 tfile = local_path.open(u"wb")
100 tfile.write(body)
101+ tfile.close()
102 local_path.setdata()
103 log.Info(u"IMAP mail with '%s' subject fetched" % remote_filename)
104
105@@ -215,10 +223,10 @@
106 (result, list) = self.conn.search(None, u'FROM', self.remote_dir)
107 if result != u"OK":
108 raise Exception(list[0])
109- if list[0] == u'':
110+ if list[0] == b'':
111 return ret
112- nums = list[0].strip().split(u" ")
113- set = u"%s:%s" % (nums[0], nums[-1])
114+ nums = list[0].strip().split(b" ")
115+ set = b"%s:%s" % (nums[0], nums[-1])
116 (result, list) = self.conn.fetch(set, u"(BODY[HEADER])")
117 if result != u"OK":
118 raise Exception(list[0])
119@@ -227,9 +235,9 @@
120 if (len(msg) == 1):
121 continue
122 if sys.version_info.major >= 3:
123- headers = Parser(policy=default).parsestr(msg[1]) # pylint: disable=unsubscriptable-object
124+ headers = Parser(policy=default).parsestr(msg[1].decode(u"unicode-escape")) # pylint: disable=unsubscriptable-object
125 else:
126- headers = Parser().parsestr(msg[1]) # pylint: disable=unsubscriptable-object
127+ headers = Parser().parsestr(msg[1].decode(u"unicode-escape")) # pylint: disable=unsubscriptable-object
128 subj = headers[u"subject"]
129 header_from = headers[u"from"]
130
131
132=== modified file 'duplicity/patchdir.py'
133--- duplicity/patchdir.py 2019-02-21 21:48:53 +0000
134+++ duplicity/patchdir.py 2019-05-17 14:00:52 +0000
135@@ -123,7 +123,10 @@
136 # The next tar_info is stored in this one element list so
137 # Multivol_Filelike below can update it. Any StopIterations will
138 # be passed upwards.
139- tarinfo_list = [next(tar_iter)]
140+ try:
141+ tarinfo_list = [next(tar_iter)]
142+ except StopIteration:
143+ return
144
145 while 1:
146 # This section relevant when a multivol diff is last in tar
147@@ -349,7 +352,10 @@
148
149 def __next__(self):
150 if not self.tarfile:
151- self.set_tarfile()
152+ try:
153+ self.set_tarfile()
154+ except StopIteration:
155+ return
156 try:
157 return next(self.tar_iter)
158 except StopIteration:
159
160=== modified file 'setup.py'
161--- setup.py 2019-04-30 14:40:17 +0000
162+++ setup.py 2019-05-17 14:00:52 +0000
163@@ -30,8 +30,8 @@
164
165 version_string = "$version"
166
167-if sys.version_info[:2] < (3, 5):
168- print("Sorry, duplicity requires version 3.5 or later of Python.")
169+if not (sys.version_info[:2] >= (3, 5) or (sys.version_info[0] == 2 and sys.version_info[:2] >= (2, 7))):
170+ print("Sorry, duplicity requires version 2.7 or version 3.5 or later of Python.")
171 sys.exit(1)
172
173 incdir_list = libdir_list = None

Subscribers

People subscribed via source and target branches