##// END OF EJS Templates
mail: handle renamed email.Header...
Pulkit Goyal -
r30072:87b8e40e default
parent child Browse files
Show More
@@ -1,346 +1,347 b''
1 # mail.py - mail sending bits for mercurial
1 # mail.py - mail sending bits for mercurial
2 #
2 #
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import, print_function
8 from __future__ import absolute_import, print_function
9
9
10 import email
10 import email
11 import email.header
11 import os
12 import os
12 import quopri
13 import quopri
13 import smtplib
14 import smtplib
14 import socket
15 import socket
15 import sys
16 import sys
16 import time
17 import time
17
18
18 from .i18n import _
19 from .i18n import _
19 from . import (
20 from . import (
20 encoding,
21 encoding,
21 error,
22 error,
22 sslutil,
23 sslutil,
23 util,
24 util,
24 )
25 )
25
26
26 _oldheaderinit = email.Header.Header.__init__
27 _oldheaderinit = email.header.Header.__init__
27 def _unifiedheaderinit(self, *args, **kw):
28 def _unifiedheaderinit(self, *args, **kw):
28 """
29 """
29 Python 2.7 introduces a backwards incompatible change
30 Python 2.7 introduces a backwards incompatible change
30 (Python issue1974, r70772) in email.Generator.Generator code:
31 (Python issue1974, r70772) in email.Generator.Generator code:
31 pre-2.7 code passed "continuation_ws='\t'" to the Header
32 pre-2.7 code passed "continuation_ws='\t'" to the Header
32 constructor, and 2.7 removed this parameter.
33 constructor, and 2.7 removed this parameter.
33
34
34 Default argument is continuation_ws=' ', which means that the
35 Default argument is continuation_ws=' ', which means that the
35 behavior is different in <2.7 and 2.7
36 behavior is different in <2.7 and 2.7
36
37
37 We consider the 2.7 behavior to be preferable, but need
38 We consider the 2.7 behavior to be preferable, but need
38 to have an unified behavior for versions 2.4 to 2.7
39 to have an unified behavior for versions 2.4 to 2.7
39 """
40 """
40 # override continuation_ws
41 # override continuation_ws
41 kw['continuation_ws'] = ' '
42 kw['continuation_ws'] = ' '
42 _oldheaderinit(self, *args, **kw)
43 _oldheaderinit(self, *args, **kw)
43
44
44 setattr(email.header.Header, '__init__', _unifiedheaderinit)
45 setattr(email.header.Header, '__init__', _unifiedheaderinit)
45
46
46 class STARTTLS(smtplib.SMTP):
47 class STARTTLS(smtplib.SMTP):
47 '''Derived class to verify the peer certificate for STARTTLS.
48 '''Derived class to verify the peer certificate for STARTTLS.
48
49
49 This class allows to pass any keyword arguments to SSL socket creation.
50 This class allows to pass any keyword arguments to SSL socket creation.
50 '''
51 '''
51 def __init__(self, ui, host=None, **kwargs):
52 def __init__(self, ui, host=None, **kwargs):
52 smtplib.SMTP.__init__(self, **kwargs)
53 smtplib.SMTP.__init__(self, **kwargs)
53 self._ui = ui
54 self._ui = ui
54 self._host = host
55 self._host = host
55
56
56 def starttls(self, keyfile=None, certfile=None):
57 def starttls(self, keyfile=None, certfile=None):
57 if not self.has_extn("starttls"):
58 if not self.has_extn("starttls"):
58 msg = "STARTTLS extension not supported by server"
59 msg = "STARTTLS extension not supported by server"
59 raise smtplib.SMTPException(msg)
60 raise smtplib.SMTPException(msg)
60 (resp, reply) = self.docmd("STARTTLS")
61 (resp, reply) = self.docmd("STARTTLS")
61 if resp == 220:
62 if resp == 220:
62 self.sock = sslutil.wrapsocket(self.sock, keyfile, certfile,
63 self.sock = sslutil.wrapsocket(self.sock, keyfile, certfile,
63 ui=self._ui,
64 ui=self._ui,
64 serverhostname=self._host)
65 serverhostname=self._host)
65 self.file = smtplib.SSLFakeFile(self.sock)
66 self.file = smtplib.SSLFakeFile(self.sock)
66 self.helo_resp = None
67 self.helo_resp = None
67 self.ehlo_resp = None
68 self.ehlo_resp = None
68 self.esmtp_features = {}
69 self.esmtp_features = {}
69 self.does_esmtp = 0
70 self.does_esmtp = 0
70 return (resp, reply)
71 return (resp, reply)
71
72
72 class SMTPS(smtplib.SMTP):
73 class SMTPS(smtplib.SMTP):
73 '''Derived class to verify the peer certificate for SMTPS.
74 '''Derived class to verify the peer certificate for SMTPS.
74
75
75 This class allows to pass any keyword arguments to SSL socket creation.
76 This class allows to pass any keyword arguments to SSL socket creation.
76 '''
77 '''
77 def __init__(self, ui, keyfile=None, certfile=None, host=None,
78 def __init__(self, ui, keyfile=None, certfile=None, host=None,
78 **kwargs):
79 **kwargs):
79 self.keyfile = keyfile
80 self.keyfile = keyfile
80 self.certfile = certfile
81 self.certfile = certfile
81 smtplib.SMTP.__init__(self, **kwargs)
82 smtplib.SMTP.__init__(self, **kwargs)
82 self._host = host
83 self._host = host
83 self.default_port = smtplib.SMTP_SSL_PORT
84 self.default_port = smtplib.SMTP_SSL_PORT
84 self._ui = ui
85 self._ui = ui
85
86
86 def _get_socket(self, host, port, timeout):
87 def _get_socket(self, host, port, timeout):
87 if self.debuglevel > 0:
88 if self.debuglevel > 0:
88 print('connect:', (host, port), file=sys.stderr)
89 print('connect:', (host, port), file=sys.stderr)
89 new_socket = socket.create_connection((host, port), timeout)
90 new_socket = socket.create_connection((host, port), timeout)
90 new_socket = sslutil.wrapsocket(new_socket,
91 new_socket = sslutil.wrapsocket(new_socket,
91 self.keyfile, self.certfile,
92 self.keyfile, self.certfile,
92 ui=self._ui,
93 ui=self._ui,
93 serverhostname=self._host)
94 serverhostname=self._host)
94 self.file = smtplib.SSLFakeFile(new_socket)
95 self.file = smtplib.SSLFakeFile(new_socket)
95 return new_socket
96 return new_socket
96
97
97 def _smtp(ui):
98 def _smtp(ui):
98 '''build an smtp connection and return a function to send mail'''
99 '''build an smtp connection and return a function to send mail'''
99 local_hostname = ui.config('smtp', 'local_hostname')
100 local_hostname = ui.config('smtp', 'local_hostname')
100 tls = ui.config('smtp', 'tls', 'none')
101 tls = ui.config('smtp', 'tls', 'none')
101 # backward compatible: when tls = true, we use starttls.
102 # backward compatible: when tls = true, we use starttls.
102 starttls = tls == 'starttls' or util.parsebool(tls)
103 starttls = tls == 'starttls' or util.parsebool(tls)
103 smtps = tls == 'smtps'
104 smtps = tls == 'smtps'
104 if (starttls or smtps) and not util.safehasattr(socket, 'ssl'):
105 if (starttls or smtps) and not util.safehasattr(socket, 'ssl'):
105 raise error.Abort(_("can't use TLS: Python SSL support not installed"))
106 raise error.Abort(_("can't use TLS: Python SSL support not installed"))
106 mailhost = ui.config('smtp', 'host')
107 mailhost = ui.config('smtp', 'host')
107 if not mailhost:
108 if not mailhost:
108 raise error.Abort(_('smtp.host not configured - cannot send mail'))
109 raise error.Abort(_('smtp.host not configured - cannot send mail'))
109 if smtps:
110 if smtps:
110 ui.note(_('(using smtps)\n'))
111 ui.note(_('(using smtps)\n'))
111 s = SMTPS(ui, local_hostname=local_hostname, host=mailhost)
112 s = SMTPS(ui, local_hostname=local_hostname, host=mailhost)
112 elif starttls:
113 elif starttls:
113 s = STARTTLS(ui, local_hostname=local_hostname, host=mailhost)
114 s = STARTTLS(ui, local_hostname=local_hostname, host=mailhost)
114 else:
115 else:
115 s = smtplib.SMTP(local_hostname=local_hostname)
116 s = smtplib.SMTP(local_hostname=local_hostname)
116 if smtps:
117 if smtps:
117 defaultport = 465
118 defaultport = 465
118 else:
119 else:
119 defaultport = 25
120 defaultport = 25
120 mailport = util.getport(ui.config('smtp', 'port', defaultport))
121 mailport = util.getport(ui.config('smtp', 'port', defaultport))
121 ui.note(_('sending mail: smtp host %s, port %d\n') %
122 ui.note(_('sending mail: smtp host %s, port %d\n') %
122 (mailhost, mailport))
123 (mailhost, mailport))
123 s.connect(host=mailhost, port=mailport)
124 s.connect(host=mailhost, port=mailport)
124 if starttls:
125 if starttls:
125 ui.note(_('(using starttls)\n'))
126 ui.note(_('(using starttls)\n'))
126 s.ehlo()
127 s.ehlo()
127 s.starttls()
128 s.starttls()
128 s.ehlo()
129 s.ehlo()
129 if starttls or smtps:
130 if starttls or smtps:
130 ui.note(_('(verifying remote certificate)\n'))
131 ui.note(_('(verifying remote certificate)\n'))
131 sslutil.validatesocket(s.sock)
132 sslutil.validatesocket(s.sock)
132 username = ui.config('smtp', 'username')
133 username = ui.config('smtp', 'username')
133 password = ui.config('smtp', 'password')
134 password = ui.config('smtp', 'password')
134 if username and not password:
135 if username and not password:
135 password = ui.getpass()
136 password = ui.getpass()
136 if username and password:
137 if username and password:
137 ui.note(_('(authenticating to mail server as %s)\n') %
138 ui.note(_('(authenticating to mail server as %s)\n') %
138 (username))
139 (username))
139 try:
140 try:
140 s.login(username, password)
141 s.login(username, password)
141 except smtplib.SMTPException as inst:
142 except smtplib.SMTPException as inst:
142 raise error.Abort(inst)
143 raise error.Abort(inst)
143
144
144 def send(sender, recipients, msg):
145 def send(sender, recipients, msg):
145 try:
146 try:
146 return s.sendmail(sender, recipients, msg)
147 return s.sendmail(sender, recipients, msg)
147 except smtplib.SMTPRecipientsRefused as inst:
148 except smtplib.SMTPRecipientsRefused as inst:
148 recipients = [r[1] for r in inst.recipients.values()]
149 recipients = [r[1] for r in inst.recipients.values()]
149 raise error.Abort('\n' + '\n'.join(recipients))
150 raise error.Abort('\n' + '\n'.join(recipients))
150 except smtplib.SMTPException as inst:
151 except smtplib.SMTPException as inst:
151 raise error.Abort(inst)
152 raise error.Abort(inst)
152
153
153 return send
154 return send
154
155
155 def _sendmail(ui, sender, recipients, msg):
156 def _sendmail(ui, sender, recipients, msg):
156 '''send mail using sendmail.'''
157 '''send mail using sendmail.'''
157 program = ui.config('email', 'method', 'smtp')
158 program = ui.config('email', 'method', 'smtp')
158 cmdline = '%s -f %s %s' % (program, util.email(sender),
159 cmdline = '%s -f %s %s' % (program, util.email(sender),
159 ' '.join(map(util.email, recipients)))
160 ' '.join(map(util.email, recipients)))
160 ui.note(_('sending mail: %s\n') % cmdline)
161 ui.note(_('sending mail: %s\n') % cmdline)
161 fp = util.popen(cmdline, 'w')
162 fp = util.popen(cmdline, 'w')
162 fp.write(msg)
163 fp.write(msg)
163 ret = fp.close()
164 ret = fp.close()
164 if ret:
165 if ret:
165 raise error.Abort('%s %s' % (
166 raise error.Abort('%s %s' % (
166 os.path.basename(program.split(None, 1)[0]),
167 os.path.basename(program.split(None, 1)[0]),
167 util.explainexit(ret)[0]))
168 util.explainexit(ret)[0]))
168
169
169 def _mbox(mbox, sender, recipients, msg):
170 def _mbox(mbox, sender, recipients, msg):
170 '''write mails to mbox'''
171 '''write mails to mbox'''
171 fp = open(mbox, 'ab+')
172 fp = open(mbox, 'ab+')
172 # Should be time.asctime(), but Windows prints 2-characters day
173 # Should be time.asctime(), but Windows prints 2-characters day
173 # of month instead of one. Make them print the same thing.
174 # of month instead of one. Make them print the same thing.
174 date = time.strftime('%a %b %d %H:%M:%S %Y', time.localtime())
175 date = time.strftime('%a %b %d %H:%M:%S %Y', time.localtime())
175 fp.write('From %s %s\n' % (sender, date))
176 fp.write('From %s %s\n' % (sender, date))
176 fp.write(msg)
177 fp.write(msg)
177 fp.write('\n\n')
178 fp.write('\n\n')
178 fp.close()
179 fp.close()
179
180
180 def connect(ui, mbox=None):
181 def connect(ui, mbox=None):
181 '''make a mail connection. return a function to send mail.
182 '''make a mail connection. return a function to send mail.
182 call as sendmail(sender, list-of-recipients, msg).'''
183 call as sendmail(sender, list-of-recipients, msg).'''
183 if mbox:
184 if mbox:
184 open(mbox, 'wb').close()
185 open(mbox, 'wb').close()
185 return lambda s, r, m: _mbox(mbox, s, r, m)
186 return lambda s, r, m: _mbox(mbox, s, r, m)
186 if ui.config('email', 'method', 'smtp') == 'smtp':
187 if ui.config('email', 'method', 'smtp') == 'smtp':
187 return _smtp(ui)
188 return _smtp(ui)
188 return lambda s, r, m: _sendmail(ui, s, r, m)
189 return lambda s, r, m: _sendmail(ui, s, r, m)
189
190
190 def sendmail(ui, sender, recipients, msg, mbox=None):
191 def sendmail(ui, sender, recipients, msg, mbox=None):
191 send = connect(ui, mbox=mbox)
192 send = connect(ui, mbox=mbox)
192 return send(sender, recipients, msg)
193 return send(sender, recipients, msg)
193
194
194 def validateconfig(ui):
195 def validateconfig(ui):
195 '''determine if we have enough config data to try sending email.'''
196 '''determine if we have enough config data to try sending email.'''
196 method = ui.config('email', 'method', 'smtp')
197 method = ui.config('email', 'method', 'smtp')
197 if method == 'smtp':
198 if method == 'smtp':
198 if not ui.config('smtp', 'host'):
199 if not ui.config('smtp', 'host'):
199 raise error.Abort(_('smtp specified as email transport, '
200 raise error.Abort(_('smtp specified as email transport, '
200 'but no smtp host configured'))
201 'but no smtp host configured'))
201 else:
202 else:
202 if not util.findexe(method):
203 if not util.findexe(method):
203 raise error.Abort(_('%r specified as email transport, '
204 raise error.Abort(_('%r specified as email transport, '
204 'but not in PATH') % method)
205 'but not in PATH') % method)
205
206
206 def mimetextpatch(s, subtype='plain', display=False):
207 def mimetextpatch(s, subtype='plain', display=False):
207 '''Return MIME message suitable for a patch.
208 '''Return MIME message suitable for a patch.
208 Charset will be detected as utf-8 or (possibly fake) us-ascii.
209 Charset will be detected as utf-8 or (possibly fake) us-ascii.
209 Transfer encodings will be used if necessary.'''
210 Transfer encodings will be used if necessary.'''
210
211
211 cs = 'us-ascii'
212 cs = 'us-ascii'
212 if not display:
213 if not display:
213 try:
214 try:
214 s.decode('us-ascii')
215 s.decode('us-ascii')
215 except UnicodeDecodeError:
216 except UnicodeDecodeError:
216 try:
217 try:
217 s.decode('utf-8')
218 s.decode('utf-8')
218 cs = 'utf-8'
219 cs = 'utf-8'
219 except UnicodeDecodeError:
220 except UnicodeDecodeError:
220 # We'll go with us-ascii as a fallback.
221 # We'll go with us-ascii as a fallback.
221 pass
222 pass
222
223
223 return mimetextqp(s, subtype, cs)
224 return mimetextqp(s, subtype, cs)
224
225
225 def mimetextqp(body, subtype, charset):
226 def mimetextqp(body, subtype, charset):
226 '''Return MIME message.
227 '''Return MIME message.
227 Quoted-printable transfer encoding will be used if necessary.
228 Quoted-printable transfer encoding will be used if necessary.
228 '''
229 '''
229 enc = None
230 enc = None
230 for line in body.splitlines():
231 for line in body.splitlines():
231 if len(line) > 950:
232 if len(line) > 950:
232 body = quopri.encodestring(body)
233 body = quopri.encodestring(body)
233 enc = "quoted-printable"
234 enc = "quoted-printable"
234 break
235 break
235
236
236 msg = email.MIMEText.MIMEText(body, subtype, charset)
237 msg = email.MIMEText.MIMEText(body, subtype, charset)
237 if enc:
238 if enc:
238 del msg['Content-Transfer-Encoding']
239 del msg['Content-Transfer-Encoding']
239 msg['Content-Transfer-Encoding'] = enc
240 msg['Content-Transfer-Encoding'] = enc
240 return msg
241 return msg
241
242
242 def _charsets(ui):
243 def _charsets(ui):
243 '''Obtains charsets to send mail parts not containing patches.'''
244 '''Obtains charsets to send mail parts not containing patches.'''
244 charsets = [cs.lower() for cs in ui.configlist('email', 'charsets')]
245 charsets = [cs.lower() for cs in ui.configlist('email', 'charsets')]
245 fallbacks = [encoding.fallbackencoding.lower(),
246 fallbacks = [encoding.fallbackencoding.lower(),
246 encoding.encoding.lower(), 'utf-8']
247 encoding.encoding.lower(), 'utf-8']
247 for cs in fallbacks: # find unique charsets while keeping order
248 for cs in fallbacks: # find unique charsets while keeping order
248 if cs not in charsets:
249 if cs not in charsets:
249 charsets.append(cs)
250 charsets.append(cs)
250 return [cs for cs in charsets if not cs.endswith('ascii')]
251 return [cs for cs in charsets if not cs.endswith('ascii')]
251
252
252 def _encode(ui, s, charsets):
253 def _encode(ui, s, charsets):
253 '''Returns (converted) string, charset tuple.
254 '''Returns (converted) string, charset tuple.
254 Finds out best charset by cycling through sendcharsets in descending
255 Finds out best charset by cycling through sendcharsets in descending
255 order. Tries both encoding and fallbackencoding for input. Only as
256 order. Tries both encoding and fallbackencoding for input. Only as
256 last resort send as is in fake ascii.
257 last resort send as is in fake ascii.
257 Caveat: Do not use for mail parts containing patches!'''
258 Caveat: Do not use for mail parts containing patches!'''
258 try:
259 try:
259 s.decode('ascii')
260 s.decode('ascii')
260 except UnicodeDecodeError:
261 except UnicodeDecodeError:
261 sendcharsets = charsets or _charsets(ui)
262 sendcharsets = charsets or _charsets(ui)
262 for ics in (encoding.encoding, encoding.fallbackencoding):
263 for ics in (encoding.encoding, encoding.fallbackencoding):
263 try:
264 try:
264 u = s.decode(ics)
265 u = s.decode(ics)
265 except UnicodeDecodeError:
266 except UnicodeDecodeError:
266 continue
267 continue
267 for ocs in sendcharsets:
268 for ocs in sendcharsets:
268 try:
269 try:
269 return u.encode(ocs), ocs
270 return u.encode(ocs), ocs
270 except UnicodeEncodeError:
271 except UnicodeEncodeError:
271 pass
272 pass
272 except LookupError:
273 except LookupError:
273 ui.warn(_('ignoring invalid sendcharset: %s\n') % ocs)
274 ui.warn(_('ignoring invalid sendcharset: %s\n') % ocs)
274 # if ascii, or all conversion attempts fail, send (broken) ascii
275 # if ascii, or all conversion attempts fail, send (broken) ascii
275 return s, 'us-ascii'
276 return s, 'us-ascii'
276
277
277 def headencode(ui, s, charsets=None, display=False):
278 def headencode(ui, s, charsets=None, display=False):
278 '''Returns RFC-2047 compliant header from given string.'''
279 '''Returns RFC-2047 compliant header from given string.'''
279 if not display:
280 if not display:
280 # split into words?
281 # split into words?
281 s, cs = _encode(ui, s, charsets)
282 s, cs = _encode(ui, s, charsets)
282 return str(email.Header.Header(s, cs))
283 return str(email.header.Header(s, cs))
283 return s
284 return s
284
285
285 def _addressencode(ui, name, addr, charsets=None):
286 def _addressencode(ui, name, addr, charsets=None):
286 name = headencode(ui, name, charsets)
287 name = headencode(ui, name, charsets)
287 try:
288 try:
288 acc, dom = addr.split('@')
289 acc, dom = addr.split('@')
289 acc = acc.encode('ascii')
290 acc = acc.encode('ascii')
290 dom = dom.decode(encoding.encoding).encode('idna')
291 dom = dom.decode(encoding.encoding).encode('idna')
291 addr = '%s@%s' % (acc, dom)
292 addr = '%s@%s' % (acc, dom)
292 except UnicodeDecodeError:
293 except UnicodeDecodeError:
293 raise error.Abort(_('invalid email address: %s') % addr)
294 raise error.Abort(_('invalid email address: %s') % addr)
294 except ValueError:
295 except ValueError:
295 try:
296 try:
296 # too strict?
297 # too strict?
297 addr = addr.encode('ascii')
298 addr = addr.encode('ascii')
298 except UnicodeDecodeError:
299 except UnicodeDecodeError:
299 raise error.Abort(_('invalid local address: %s') % addr)
300 raise error.Abort(_('invalid local address: %s') % addr)
300 return email.Utils.formataddr((name, addr))
301 return email.Utils.formataddr((name, addr))
301
302
302 def addressencode(ui, address, charsets=None, display=False):
303 def addressencode(ui, address, charsets=None, display=False):
303 '''Turns address into RFC-2047 compliant header.'''
304 '''Turns address into RFC-2047 compliant header.'''
304 if display or not address:
305 if display or not address:
305 return address or ''
306 return address or ''
306 name, addr = email.Utils.parseaddr(address)
307 name, addr = email.Utils.parseaddr(address)
307 return _addressencode(ui, name, addr, charsets)
308 return _addressencode(ui, name, addr, charsets)
308
309
309 def addrlistencode(ui, addrs, charsets=None, display=False):
310 def addrlistencode(ui, addrs, charsets=None, display=False):
310 '''Turns a list of addresses into a list of RFC-2047 compliant headers.
311 '''Turns a list of addresses into a list of RFC-2047 compliant headers.
311 A single element of input list may contain multiple addresses, but output
312 A single element of input list may contain multiple addresses, but output
312 always has one address per item'''
313 always has one address per item'''
313 if display:
314 if display:
314 return [a.strip() for a in addrs if a.strip()]
315 return [a.strip() for a in addrs if a.strip()]
315
316
316 result = []
317 result = []
317 for name, addr in email.Utils.getaddresses(addrs):
318 for name, addr in email.Utils.getaddresses(addrs):
318 if name or addr:
319 if name or addr:
319 result.append(_addressencode(ui, name, addr, charsets))
320 result.append(_addressencode(ui, name, addr, charsets))
320 return result
321 return result
321
322
322 def mimeencode(ui, s, charsets=None, display=False):
323 def mimeencode(ui, s, charsets=None, display=False):
323 '''creates mime text object, encodes it if needed, and sets
324 '''creates mime text object, encodes it if needed, and sets
324 charset and transfer-encoding accordingly.'''
325 charset and transfer-encoding accordingly.'''
325 cs = 'us-ascii'
326 cs = 'us-ascii'
326 if not display:
327 if not display:
327 s, cs = _encode(ui, s, charsets)
328 s, cs = _encode(ui, s, charsets)
328 return mimetextqp(s, 'plain', cs)
329 return mimetextqp(s, 'plain', cs)
329
330
330 def headdecode(s):
331 def headdecode(s):
331 '''Decodes RFC-2047 header'''
332 '''Decodes RFC-2047 header'''
332 uparts = []
333 uparts = []
333 for part, charset in email.Header.decode_header(s):
334 for part, charset in email.header.decode_header(s):
334 if charset is not None:
335 if charset is not None:
335 try:
336 try:
336 uparts.append(part.decode(charset))
337 uparts.append(part.decode(charset))
337 continue
338 continue
338 except UnicodeDecodeError:
339 except UnicodeDecodeError:
339 pass
340 pass
340 try:
341 try:
341 uparts.append(part.decode('UTF-8'))
342 uparts.append(part.decode('UTF-8'))
342 continue
343 continue
343 except UnicodeDecodeError:
344 except UnicodeDecodeError:
344 pass
345 pass
345 uparts.append(part.decode('ISO-8859-1'))
346 uparts.append(part.decode('ISO-8859-1'))
346 return encoding.tolocal(u' '.join(uparts).encode('UTF-8'))
347 return encoding.tolocal(u' '.join(uparts).encode('UTF-8'))
@@ -1,158 +1,156 b''
1 #require test-repo
1 #require test-repo
2
2
3 $ . "$TESTDIR/helpers-testrepo.sh"
3 $ . "$TESTDIR/helpers-testrepo.sh"
4 $ cd "$TESTDIR"/..
4 $ cd "$TESTDIR"/..
5
5
6 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
6 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
7 hgext/fsmonitor/pywatchman/__init__.py not using absolute_import
7 hgext/fsmonitor/pywatchman/__init__.py not using absolute_import
8 hgext/fsmonitor/pywatchman/__init__.py requires print_function
8 hgext/fsmonitor/pywatchman/__init__.py requires print_function
9 hgext/fsmonitor/pywatchman/capabilities.py not using absolute_import
9 hgext/fsmonitor/pywatchman/capabilities.py not using absolute_import
10 hgext/fsmonitor/pywatchman/pybser.py not using absolute_import
10 hgext/fsmonitor/pywatchman/pybser.py not using absolute_import
11 i18n/check-translation.py not using absolute_import
11 i18n/check-translation.py not using absolute_import
12 setup.py not using absolute_import
12 setup.py not using absolute_import
13 tests/test-demandimport.py not using absolute_import
13 tests/test-demandimport.py not using absolute_import
14
14
15 #if py3exe
15 #if py3exe
16 $ hg files 'set:(**.py) - grep(pygments)' | sed 's|\\|/|g' \
16 $ hg files 'set:(**.py) - grep(pygments)' | sed 's|\\|/|g' \
17 > | xargs $PYTHON3 contrib/check-py3-compat.py \
17 > | xargs $PYTHON3 contrib/check-py3-compat.py \
18 > | sed 's/[0-9][0-9]*)$/*)/'
18 > | sed 's/[0-9][0-9]*)$/*)/'
19 hgext/acl.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
19 hgext/acl.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
20 hgext/automv.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
20 hgext/automv.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
21 hgext/blackbox.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
21 hgext/blackbox.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
22 hgext/bugzilla.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
22 hgext/bugzilla.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
23 hgext/censor.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
23 hgext/censor.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
24 hgext/chgserver.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
24 hgext/chgserver.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
25 hgext/children.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
25 hgext/children.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
26 hgext/churn.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
26 hgext/churn.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
27 hgext/clonebundles.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
27 hgext/clonebundles.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
28 hgext/color.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
28 hgext/color.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
29 hgext/convert/bzr.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *)
29 hgext/convert/bzr.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *)
30 hgext/convert/common.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
30 hgext/convert/common.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
31 hgext/convert/convcmd.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
31 hgext/convert/convcmd.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
32 hgext/convert/cvs.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
32 hgext/convert/cvs.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
33 hgext/convert/cvsps.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
33 hgext/convert/cvsps.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
34 hgext/convert/darcs.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
34 hgext/convert/darcs.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
35 hgext/convert/filemap.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *)
35 hgext/convert/filemap.py: error importing module: <SystemError> Parent module 'hgext.convert' not loaded, cannot perform relative import (line *)
36 hgext/convert/git.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
36 hgext/convert/git.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
37 hgext/convert/gnuarch.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
37 hgext/convert/gnuarch.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
38 hgext/convert/hg.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
38 hgext/convert/hg.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
39 hgext/convert/monotone.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
39 hgext/convert/monotone.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
40 hgext/convert/p4.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
40 hgext/convert/p4.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
41 hgext/convert/subversion.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
41 hgext/convert/subversion.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
42 hgext/convert/transport.py: error importing module: <ImportError> No module named 'svn.client' (line *)
42 hgext/convert/transport.py: error importing module: <ImportError> No module named 'svn.client' (line *)
43 hgext/eol.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
43 hgext/eol.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
44 hgext/extdiff.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
44 hgext/extdiff.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
45 hgext/factotum.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
45 hgext/factotum.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
46 hgext/fetch.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
46 hgext/fetch.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
47 hgext/fsmonitor/state.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
47 hgext/fsmonitor/state.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
48 hgext/fsmonitor/watchmanclient.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
48 hgext/fsmonitor/watchmanclient.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
49 hgext/gpg.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
49 hgext/gpg.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
50 hgext/graphlog.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
50 hgext/graphlog.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
51 hgext/hgk.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
51 hgext/hgk.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
52 hgext/histedit.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
52 hgext/histedit.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
53 hgext/journal.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
53 hgext/journal.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
54 hgext/keyword.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
54 hgext/keyword.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
55 hgext/largefiles/basestore.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
55 hgext/largefiles/basestore.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
56 hgext/largefiles/lfcommands.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
56 hgext/largefiles/lfcommands.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
57 hgext/largefiles/lfutil.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
57 hgext/largefiles/lfutil.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
58 hgext/largefiles/localstore.py: error importing module: <SystemError> Parent module 'hgext.largefiles' not loaded, cannot perform relative import (line *)
58 hgext/largefiles/localstore.py: error importing module: <SystemError> Parent module 'hgext.largefiles' not loaded, cannot perform relative import (line *)
59 hgext/largefiles/overrides.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
59 hgext/largefiles/overrides.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
60 hgext/largefiles/proto.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
60 hgext/largefiles/proto.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
61 hgext/largefiles/remotestore.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
61 hgext/largefiles/remotestore.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
62 hgext/largefiles/reposetup.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
62 hgext/largefiles/reposetup.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
63 hgext/largefiles/storefactory.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
63 hgext/largefiles/storefactory.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
64 hgext/largefiles/uisetup.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
64 hgext/largefiles/uisetup.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
65 hgext/largefiles/wirestore.py: error importing module: <SystemError> Parent module 'hgext.largefiles' not loaded, cannot perform relative import (line *)
65 hgext/largefiles/wirestore.py: error importing module: <SystemError> Parent module 'hgext.largefiles' not loaded, cannot perform relative import (line *)
66 hgext/mq.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
66 hgext/mq.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
67 hgext/notify.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
67 hgext/notify.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
68 hgext/pager.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
68 hgext/pager.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
69 hgext/patchbomb.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
69 hgext/patchbomb.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
70 hgext/purge.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
70 hgext/purge.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
71 hgext/rebase.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
71 hgext/rebase.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
72 hgext/record.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
72 hgext/record.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
73 hgext/relink.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
73 hgext/relink.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
74 hgext/schemes.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
74 hgext/schemes.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
75 hgext/share.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
75 hgext/share.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
76 hgext/shelve.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
76 hgext/shelve.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
77 hgext/strip.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
77 hgext/strip.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
78 hgext/transplant.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
78 hgext/transplant.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
79 hgext/win32text.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
79 hgext/win32text.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
80 mercurial/archival.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
80 mercurial/archival.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
81 mercurial/bookmarks.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
81 mercurial/bookmarks.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
82 mercurial/branchmap.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
82 mercurial/branchmap.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
83 mercurial/bundle2.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
83 mercurial/bundle2.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
84 mercurial/bundlerepo.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
84 mercurial/bundlerepo.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
85 mercurial/byterange.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
85 mercurial/byterange.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
86 mercurial/changegroup.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
86 mercurial/changegroup.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
87 mercurial/changelog.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
87 mercurial/changelog.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
88 mercurial/cmdutil.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
88 mercurial/cmdutil.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
89 mercurial/commands.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
89 mercurial/commands.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
90 mercurial/commandserver.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
90 mercurial/commandserver.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
91 mercurial/config.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
91 mercurial/config.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
92 mercurial/context.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
92 mercurial/context.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
93 mercurial/copies.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
93 mercurial/copies.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
94 mercurial/crecord.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
94 mercurial/crecord.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
95 mercurial/destutil.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
95 mercurial/destutil.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
96 mercurial/dirstate.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
96 mercurial/dirstate.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
97 mercurial/discovery.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
97 mercurial/discovery.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
98 mercurial/dispatch.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
98 mercurial/dispatch.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
99 mercurial/encoding.py: error importing module: <TypeError> bytes expected, not str (line *)
99 mercurial/encoding.py: error importing module: <TypeError> bytes expected, not str (line *)
100 mercurial/exchange.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
100 mercurial/exchange.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
101 mercurial/extensions.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
101 mercurial/extensions.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
102 mercurial/filelog.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
102 mercurial/filelog.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
103 mercurial/filemerge.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
103 mercurial/filemerge.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
104 mercurial/fileset.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
104 mercurial/fileset.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
105 mercurial/formatter.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
105 mercurial/formatter.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
106 mercurial/graphmod.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
106 mercurial/graphmod.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
107 mercurial/help.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
107 mercurial/help.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
108 mercurial/hg.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
108 mercurial/hg.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
109 mercurial/hgweb/common.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
109 mercurial/hgweb/common.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
110 mercurial/hgweb/hgweb_mod.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
110 mercurial/hgweb/hgweb_mod.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
111 mercurial/hgweb/hgwebdir_mod.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
111 mercurial/hgweb/hgwebdir_mod.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
112 mercurial/hgweb/protocol.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
112 mercurial/hgweb/protocol.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
113 mercurial/hgweb/request.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
113 mercurial/hgweb/request.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
114 mercurial/hgweb/server.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
114 mercurial/hgweb/server.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
115 mercurial/hgweb/webcommands.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
115 mercurial/hgweb/webcommands.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
116 mercurial/hgweb/webutil.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
116 mercurial/hgweb/webutil.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
117 mercurial/hgweb/wsgicgi.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
117 mercurial/hgweb/wsgicgi.py: error importing module: <SystemError> Parent module 'mercurial.hgweb' not loaded, cannot perform relative import (line *)
118 mercurial/hook.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
118 mercurial/hook.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
119 mercurial/httpconnection.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
119 mercurial/httpconnection.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
120 mercurial/httppeer.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
120 mercurial/httppeer.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
121 mercurial/i18n.py: error importing module: <TypeError> bytes expected, not str (line *)
121 mercurial/i18n.py: error importing module: <TypeError> bytes expected, not str (line *)
122 mercurial/keepalive.py: error importing module: <AttributeError> module 'mercurial.util' has no attribute 'httplib' (line *)
122 mercurial/keepalive.py: error importing module: <AttributeError> module 'mercurial.util' has no attribute 'httplib' (line *)
123 mercurial/localrepo.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'urlerr' (error at httpconnection.py:*)
123 mercurial/localrepo.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'urlerr' (error at httpconnection.py:*)
124 mercurial/mail.py: error importing module: <AttributeError> module 'email' has no attribute 'Header' (line *)
124 mercurial/manifest.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
125 mercurial/manifest.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
125 mercurial/merge.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
126 mercurial/merge.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
126 mercurial/namespaces.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
127 mercurial/namespaces.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
127 mercurial/patch.py: error importing module: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (line *)
128 mercurial/patch.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
129 mercurial/pvec.py: error importing module: <NameError> name 'xrange' is not defined (line *)
128 mercurial/pvec.py: error importing module: <NameError> name 'xrange' is not defined (line *)
130 mercurial/repair.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'urlerr' (error at httpconnection.py:*)
129 mercurial/repair.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'urlerr' (error at httpconnection.py:*)
131 mercurial/revlog.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
130 mercurial/revlog.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
132 mercurial/revset.py: error importing module: <AttributeError> 'dict' object has no attribute 'iteritems' (line *)
131 mercurial/revset.py: error importing module: <AttributeError> 'dict' object has no attribute 'iteritems' (line *)
133 mercurial/scmwindows.py: error importing module: <ImportError> No module named 'winreg' (line *)
132 mercurial/scmwindows.py: error importing module: <ImportError> No module named 'winreg' (line *)
134 mercurial/sshpeer.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'urlerr' (error at httpconnection.py:*)
133 mercurial/sshpeer.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'urlerr' (error at httpconnection.py:*)
135 mercurial/sshserver.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
134 mercurial/sshserver.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
136 mercurial/statichttprepo.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'urlerr' (error at byterange.py:*)
135 mercurial/statichttprepo.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'urlerr' (error at byterange.py:*)
137 mercurial/store.py: error importing module: <NameError> name 'xrange' is not defined (line *)
136 mercurial/store.py: error importing module: <NameError> name 'xrange' is not defined (line *)
138 mercurial/streamclone.py: error importing: <TypeError> can't concat bytes to str (error at store.py:*)
137 mercurial/streamclone.py: error importing: <TypeError> can't concat bytes to str (error at store.py:*)
139 mercurial/subrepo.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
138 mercurial/subrepo.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
140 mercurial/templatefilters.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
139 mercurial/templatefilters.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
141 mercurial/templatekw.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
140 mercurial/templatekw.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
142 mercurial/templater.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
141 mercurial/templater.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
143 mercurial/ui.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
142 mercurial/ui.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
144 mercurial/unionrepo.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
143 mercurial/unionrepo.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'stringio' (error at patch.py:*)
145 mercurial/url.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'urlerr' (error at httpconnection.py:*)
144 mercurial/url.py: error importing: <AttributeError> module 'mercurial.util' has no attribute 'urlerr' (error at httpconnection.py:*)
146 mercurial/verify.py: error importing: <AttributeError> module 'email' has no attribute 'Header' (error at mail.py:*)
147 mercurial/win32.py: error importing module: <ImportError> No module named 'msvcrt' (line *)
145 mercurial/win32.py: error importing module: <ImportError> No module named 'msvcrt' (line *)
148 mercurial/windows.py: error importing module: <ImportError> No module named 'msvcrt' (line *)
146 mercurial/windows.py: error importing module: <ImportError> No module named 'msvcrt' (line *)
149 mercurial/wireproto.py: error importing: <TypeError> %b requires bytes, or an object that implements __bytes__, not 'str' (error at bundle2.py:*)
147 mercurial/wireproto.py: error importing: <TypeError> %b requires bytes, or an object that implements __bytes__, not 'str' (error at bundle2.py:*)
150
148
151 #endif
149 #endif
152
150
153 #if py3exe py3pygments
151 #if py3exe py3pygments
154 $ hg files 'set:(**.py) and grep(pygments)' | sed 's|\\|/|g' \
152 $ hg files 'set:(**.py) and grep(pygments)' | sed 's|\\|/|g' \
155 > | xargs $PYTHON3 contrib/check-py3-compat.py \
153 > | xargs $PYTHON3 contrib/check-py3-compat.py \
156 > | sed 's/[0-9][0-9]*)$/*)/'
154 > | sed 's/[0-9][0-9]*)$/*)/'
157 hgext/highlight/highlight.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
155 hgext/highlight/highlight.py: error importing: <TypeError> Can't mix strings and bytes in path components (error at i18n.py:*)
158 #endif
156 #endif
General Comments 0
You need to be logged in to leave comments. Login now