Generates a bytes version of a Message object tree. Functionally identical to the base Generator except that the output is bytes and not string. When surrogates were used in the input to encode bytes, these are decoded back to bytes for output. If the policy has cte_type set to 7b
| 405 | |
| 406 | |
| 407 | class BytesGenerator(Generator): |
| 408 | """Generates a bytes version of a Message object tree. |
| 409 | |
| 410 | Functionally identical to the base Generator except that the output is |
| 411 | bytes and not string. When surrogates were used in the input to encode |
| 412 | bytes, these are decoded back to bytes for output. If the policy has |
| 413 | cte_type set to 7bit, then the message is transformed such that the |
| 414 | non-ASCII bytes are properly content transfer encoded, using the charset |
| 415 | unknown-8bit. |
| 416 | |
| 417 | The outfp object must accept bytes in its write method. |
| 418 | """ |
| 419 | |
| 420 | def write(self, s): |
| 421 | self._fp.write(s.encode('ascii', 'surrogateescape')) |
| 422 | |
| 423 | def _new_buffer(self): |
| 424 | return BytesIO() |
| 425 | |
| 426 | def _encode(self, s): |
| 427 | return s.encode('ascii') |
| 428 | |
| 429 | def _write_headers(self, msg): |
| 430 | # This is almost the same as the string version, except for handling |
| 431 | # strings with 8bit bytes. |
| 432 | for h, v in msg.raw_items(): |
| 433 | folded = self.policy.fold_binary(h, v) |
| 434 | if self.policy.verify_generated_headers: |
| 435 | linesep = self.policy.linesep.encode() |
| 436 | if not folded.endswith(linesep): |
| 437 | raise HeaderWriteError( |
| 438 | f'folded header does not end with {linesep!r}: {folded!r}') |
| 439 | if NEWLINE_WITHOUT_FWSP_BYTES.search(folded.removesuffix(linesep)): |
| 440 | raise HeaderWriteError( |
| 441 | f'folded header contains newline: {folded!r}') |
| 442 | self._fp.write(folded) |
| 443 | # A blank line always separates headers from body |
| 444 | self.write(self._NL) |
| 445 | |
| 446 | def _handle_text(self, msg): |
| 447 | # If the string has surrogates the original source was bytes, so |
| 448 | # just write it back out. |
| 449 | if msg._payload is None: |
| 450 | return |
| 451 | if _has_surrogates(msg._payload) and not self.policy.cte_type=='7bit': |
| 452 | if self._mangle_from_: |
| 453 | msg._payload = fcre.sub(">From ", msg._payload) |
| 454 | self._write_lines(msg._payload) |
| 455 | else: |
| 456 | super(BytesGenerator,self)._handle_text(msg) |
| 457 | |
| 458 | # Default body handler |
| 459 | _writeBody = _handle_text |
| 460 | |
| 461 | @classmethod |
| 462 | def _compile_re(cls, s, flags): |
| 463 | return re.compile(s.encode('ascii'), flags) |
| 464 |
no outgoing calls
searching dependent graphs…