Show More
@@ -253,17 +253,13 b' def validateconfig(ui):' | |||
|
253 | 253 | |
|
254 | 254 | |
|
255 | 255 | def codec2iana(cs): |
|
256 |
# type: ( |
|
|
256 | # type: (str) -> str | |
|
257 | 257 | '''''' |
|
258 | cs = pycompat.sysbytes( | |
|
259 | email.charset.Charset( | |
|
260 | cs # pytype: disable=wrong-arg-types | |
|
261 | ).input_charset.lower() | |
|
262 | ) | |
|
258 | cs = email.charset.Charset(cs).input_charset.lower() | |
|
263 | 259 | |
|
264 | 260 | # "latin1" normalizes to "iso8859-1", standard calls for "iso-8859-1" |
|
265 |
if cs.startswith( |
|
|
266 |
return |
|
|
261 | if cs.startswith("iso") and not cs.startswith("iso-"): | |
|
262 | return "iso-" + cs[3:] | |
|
267 | 263 | return cs |
|
268 | 264 | |
|
269 | 265 | |
@@ -275,27 +271,30 b" def mimetextpatch(s, subtype=b'plain', d" | |||
|
275 | 271 | ISO-8859-1, an encoding with that allows all byte sequences. |
|
276 | 272 | Transfer encodings will be used if necessary.''' |
|
277 | 273 | |
|
278 | cs = [b'us-ascii', b'utf-8', encoding.encoding, encoding.fallbackencoding] | |
|
274 | cs = [ | |
|
275 | 'us-ascii', | |
|
276 | 'utf-8', | |
|
277 | pycompat.sysstr(encoding.encoding), | |
|
278 | pycompat.sysstr(encoding.fallbackencoding), | |
|
279 | ] | |
|
279 | 280 | if display: |
|
280 |
cs = [ |
|
|
281 | cs = ['us-ascii'] | |
|
281 | 282 | for charset in cs: |
|
282 | 283 | try: |
|
283 |
s.decode( |
|
|
284 | s.decode(charset) | |
|
284 | 285 | return mimetextqp(s, subtype, codec2iana(charset)) |
|
285 | 286 | except UnicodeDecodeError: |
|
286 | 287 | pass |
|
287 | 288 | |
|
288 |
return mimetextqp(s, subtype, |
|
|
289 | return mimetextqp(s, subtype, "iso-8859-1") | |
|
289 | 290 | |
|
290 | 291 | |
|
291 | 292 | def mimetextqp(body, subtype, charset): |
|
292 |
# type: (bytes, bytes, |
|
|
293 | # type: (bytes, bytes, str) -> email.message.Message | |
|
293 | 294 | '''Return MIME message. |
|
294 | 295 | Quoted-printable transfer encoding will be used if necessary. |
|
295 | 296 | ''' |
|
296 | # Experimentally charset is okay as a bytes even if the type | |
|
297 | # stubs disagree. | |
|
298 | cs = email.charset.Charset(charset) # pytype: disable=wrong-arg-types | |
|
297 | cs = email.charset.Charset(charset) | |
|
299 | 298 | msg = email.message.Message() |
|
300 | 299 | msg.set_type(pycompat.sysstr(b'text/' + subtype)) |
|
301 | 300 | |
@@ -317,24 +316,25 b' def mimetextqp(body, subtype, charset):' | |||
|
317 | 316 | |
|
318 | 317 | |
|
319 | 318 | def _charsets(ui): |
|
320 |
# type: (Any) -> List[ |
|
|
319 | # type: (Any) -> List[str] | |
|
321 | 320 | '''Obtains charsets to send mail parts not containing patches.''' |
|
322 | 321 | charsets = [ |
|
323 | cs.lower() for cs in ui.configlist(b'email', b'charsets') | |
|
324 | ] # type: List[bytes] | |
|
322 | pycompat.sysstr(cs.lower()) | |
|
323 | for cs in ui.configlist(b'email', b'charsets') | |
|
324 | ] | |
|
325 | 325 | fallbacks = [ |
|
326 | encoding.fallbackencoding.lower(), | |
|
327 | encoding.encoding.lower(), | |
|
328 |
|
|
|
329 | ] # type: List[bytes] | |
|
326 | pycompat.sysstr(encoding.fallbackencoding.lower()), | |
|
327 | pycompat.sysstr(encoding.encoding.lower()), | |
|
328 | 'utf-8', | |
|
329 | ] | |
|
330 | 330 | for cs in fallbacks: # find unique charsets while keeping order |
|
331 | 331 | if cs not in charsets: |
|
332 | 332 | charsets.append(cs) |
|
333 |
return [cs for cs in charsets if not cs.endswith( |
|
|
333 | return [cs for cs in charsets if not cs.endswith('ascii')] | |
|
334 | 334 | |
|
335 | 335 | |
|
336 | 336 | def _encode(ui, s, charsets): |
|
337 |
# type: (Any, bytes, List[ |
|
|
337 | # type: (Any, bytes, List[str]) -> Tuple[bytes, str] | |
|
338 | 338 | '''Returns (converted) string, charset tuple. |
|
339 | 339 | Finds out best charset by cycling through sendcharsets in descending |
|
340 | 340 | order. Tries both encoding and fallbackencoding for input. Only as |
@@ -347,14 +347,17 b' def _encode(ui, s, charsets):' | |||
|
347 | 347 | # wants, and fall back to garbage-in-ascii. |
|
348 | 348 | for ocs in sendcharsets: |
|
349 | 349 | try: |
|
350 |
return s.encode( |
|
|
350 | return s.encode(ocs), ocs | |
|
351 | 351 | except UnicodeEncodeError: |
|
352 | 352 | pass |
|
353 | 353 | except LookupError: |
|
354 | ui.warn(_(b'ignoring invalid sendcharset: %s\n') % ocs) | |
|
354 | ui.warn( | |
|
355 | _(b'ignoring invalid sendcharset: %s\n') | |
|
356 | % pycompat.sysbytes(ocs) | |
|
357 | ) | |
|
355 | 358 | else: |
|
356 | 359 | # Everything failed, ascii-armor what we've got and send it. |
|
357 |
return s.encode('ascii', 'backslashreplace'), |
|
|
360 | return s.encode('ascii', 'backslashreplace'), 'us-ascii' | |
|
358 | 361 | # We have a bytes of unknown encoding. We'll try and guess a valid |
|
359 | 362 | # encoding, falling back to pretending we had ascii even though we |
|
360 | 363 | # know that's wrong. |
@@ -369,29 +372,30 b' def _encode(ui, s, charsets):' | |||
|
369 | 372 | continue |
|
370 | 373 | for ocs in sendcharsets: |
|
371 | 374 | try: |
|
372 |
return u.encode( |
|
|
375 | return u.encode(ocs), ocs | |
|
373 | 376 | except UnicodeEncodeError: |
|
374 | 377 | pass |
|
375 | 378 | except LookupError: |
|
376 | ui.warn(_(b'ignoring invalid sendcharset: %s\n') % ocs) | |
|
379 | ui.warn( | |
|
380 | _(b'ignoring invalid sendcharset: %s\n') | |
|
381 | % pycompat.sysbytes(ocs) | |
|
382 | ) | |
|
377 | 383 | # if ascii, or all conversion attempts fail, send (broken) ascii |
|
378 |
return s, |
|
|
384 | return s, 'us-ascii' | |
|
379 | 385 | |
|
380 | 386 | |
|
381 | 387 | def headencode(ui, s, charsets=None, display=False): |
|
382 |
# type: (Any, Union[bytes, str], List[ |
|
|
388 | # type: (Any, Union[bytes, str], List[str], bool) -> str | |
|
383 | 389 | '''Returns RFC-2047 compliant header from given string.''' |
|
384 | 390 | if not display: |
|
385 | 391 | # split into words? |
|
386 | 392 | s, cs = _encode(ui, s, charsets) |
|
387 | return email.header.Header( | |
|
388 | s, cs # pytype: disable=wrong-arg-types | |
|
389 | ).encode() | |
|
393 | return email.header.Header(s, cs).encode() | |
|
390 | 394 | return encoding.strfromlocal(s) |
|
391 | 395 | |
|
392 | 396 | |
|
393 | 397 | def _addressencode(ui, name, addr, charsets=None): |
|
394 |
# type: (Any, str, bytes, List[ |
|
|
398 | # type: (Any, str, bytes, List[str]) -> str | |
|
395 | 399 | assert isinstance(addr, bytes) |
|
396 | 400 | name = headencode(ui, name, charsets) |
|
397 | 401 | try: |
@@ -411,7 +415,7 b' def _addressencode(ui, name, addr, chars' | |||
|
411 | 415 | |
|
412 | 416 | |
|
413 | 417 | def addressencode(ui, address, charsets=None, display=False): |
|
414 |
# type: (Any, bytes, List[ |
|
|
418 | # type: (Any, bytes, List[str], bool) -> str | |
|
415 | 419 | '''Turns address into RFC-2047 compliant header.''' |
|
416 | 420 | if display or not address: |
|
417 | 421 | return encoding.strfromlocal(address or b'') |
@@ -420,7 +424,7 b' def addressencode(ui, address, charsets=' | |||
|
420 | 424 | |
|
421 | 425 | |
|
422 | 426 | def addrlistencode(ui, addrs, charsets=None, display=False): |
|
423 |
# type: (Any, List[bytes], List[ |
|
|
427 | # type: (Any, List[bytes], List[str], bool) -> List[str] | |
|
424 | 428 | '''Turns a list of addresses into a list of RFC-2047 compliant headers. |
|
425 | 429 | A single element of input list may contain multiple addresses, but output |
|
426 | 430 | always has one address per item''' |
@@ -440,10 +444,10 b' def addrlistencode(ui, addrs, charsets=N' | |||
|
440 | 444 | |
|
441 | 445 | |
|
442 | 446 | def mimeencode(ui, s, charsets=None, display=False): |
|
443 |
# type: (Any, bytes, List[ |
|
|
447 | # type: (Any, bytes, List[str], bool) -> email.message.Message | |
|
444 | 448 | '''creates mime text object, encodes it if needed, and sets |
|
445 | 449 | charset and transfer-encoding accordingly.''' |
|
446 |
cs = |
|
|
450 | cs = 'us-ascii' | |
|
447 | 451 | if not display: |
|
448 | 452 | s, cs = _encode(ui, s, charsets) |
|
449 | 453 | return mimetextqp(s, b'plain', cs) |
General Comments 0
You need to be logged in to leave comments.
Login now