Return string of contents of parse_tree folded according to RFC rules.
(parse_tree, *, policy)
| 2791 | return wsp |
| 2792 | |
| 2793 | def _refold_parse_tree(parse_tree, *, policy): |
| 2794 | """Return string of contents of parse_tree folded according to RFC rules. |
| 2795 | |
| 2796 | """ |
| 2797 | # max_line_length 0/None means no limit, ie: infinitely long. |
| 2798 | maxlen = policy.max_line_length or sys.maxsize |
| 2799 | encoding = 'utf-8' if policy.utf8 else 'us-ascii' |
| 2800 | lines = [''] # Folded lines to be output |
| 2801 | leading_whitespace = '' # When we have whitespace between two encoded |
| 2802 | # words, we may need to encode the whitespace |
| 2803 | # at the beginning of the second word. |
| 2804 | last_ew = None # Points to the last encoded character if there's an ew on |
| 2805 | # the line |
| 2806 | last_charset = None |
| 2807 | wrap_as_ew_blocked = 0 |
| 2808 | want_encoding = False # This is set to True if we need to encode this part |
| 2809 | end_ew_not_allowed = Terminal('', 'wrap_as_ew_blocked') |
| 2810 | parts = list(parse_tree) |
| 2811 | while parts: |
| 2812 | part = parts.pop(0) |
| 2813 | if part is end_ew_not_allowed: |
| 2814 | wrap_as_ew_blocked -= 1 |
| 2815 | continue |
| 2816 | tstr = str(part) |
| 2817 | if not want_encoding: |
| 2818 | if part.token_type in ('ptext', 'vtext'): |
| 2819 | # Encode if tstr contains special characters. |
| 2820 | want_encoding = not SPECIALSNL.isdisjoint(tstr) |
| 2821 | else: |
| 2822 | # Encode if tstr contains newlines. |
| 2823 | want_encoding = not NLSET.isdisjoint(tstr) |
| 2824 | try: |
| 2825 | tstr.encode(encoding) |
| 2826 | charset = encoding |
| 2827 | except UnicodeEncodeError: |
| 2828 | if any(isinstance(x, errors.UndecodableBytesDefect) |
| 2829 | for x in part.all_defects): |
| 2830 | charset = 'unknown-8bit' |
| 2831 | else: |
| 2832 | # If policy.utf8 is false this should really be taken from a |
| 2833 | # 'charset' property on the policy. |
| 2834 | charset = 'utf-8' |
| 2835 | want_encoding = True |
| 2836 | |
| 2837 | if part.token_type == 'mime-parameters': |
| 2838 | # Mime parameter folding (using RFC2231) is extra special. |
| 2839 | _fold_mime_parameters(part, lines, maxlen, encoding) |
| 2840 | continue |
| 2841 | |
| 2842 | if want_encoding and not wrap_as_ew_blocked: |
| 2843 | if not part.as_ew_allowed: |
| 2844 | want_encoding = False |
| 2845 | last_ew = None |
| 2846 | if part.syntactic_break: |
| 2847 | encoded_part = part.fold(policy=policy)[:-len(policy.linesep)] |
| 2848 | if policy.linesep not in encoded_part: |
| 2849 | # It fits on a single line |
| 2850 | if len(encoded_part) > maxlen - len(lines[-1]): |
no test coverage detected