comparison mercurial/mail.py @ 43325:7d4f2e4899c5 stable

py3: fix headencode() with display=False We previously called str() on a email.header.Header object. On Python 2, this returns a bytestring and the __str__ method is actually an alias to .encode() method. On Python 3, __str__ does not perform encoding (and returns a unicode string). To keep a consistent behavior across Python versions, we explicitly use .encode() and we wrap the result with encoding.strtolocal() to get a bytestring in all cases. As a side effect of forcing bytes conversion, we need to decode back in _addressencode(). This is to make test-notify.t pass on Python 3. Also note that headers are now encoded in some patchbomb tests; this is because the charset is not always "us-ascii" ("iso-8859-1" otherwise) on Python 3.
author Denis Laxalde <denis.laxalde@logilab.fr>
date Thu, 24 Oct 2019 17:16:43 +0200
parents 866bd2cf764b
children ef81de93143e
comparison
equal deleted inserted replaced
43324:866bd2cf764b 43325:7d4f2e4899c5
360 def headencode(ui, s, charsets=None, display=False): 360 def headencode(ui, s, charsets=None, display=False):
361 '''Returns RFC-2047 compliant header from given string.''' 361 '''Returns RFC-2047 compliant header from given string.'''
362 if not display: 362 if not display:
363 # split into words? 363 # split into words?
364 s, cs = _encode(ui, s, charsets) 364 s, cs = _encode(ui, s, charsets)
365 return str(email.header.Header(s, cs)) 365 return encoding.strtolocal(email.header.Header(s, cs).encode())
366 return s 366 return s
367 367
368 368
369 def _addressencode(ui, name, addr, charsets=None): 369 def _addressencode(ui, name, addr, charsets=None):
370 assert isinstance(addr, bytes) 370 assert isinstance(addr, bytes)
371 name = headencode(ui, name, charsets) 371 name = encoding.strfromlocal(headencode(ui, name, charsets))
372 try: 372 try:
373 acc, dom = addr.split(b'@') 373 acc, dom = addr.split(b'@')
374 acc.decode('ascii') 374 acc.decode('ascii')
375 dom = dom.decode(pycompat.sysstr(encoding.encoding)).encode('idna') 375 dom = dom.decode(pycompat.sysstr(encoding.encoding)).encode('idna')
376 addr = b'%s@%s' % (acc, dom) 376 addr = b'%s@%s' % (acc, dom)