Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/future/backports/email/policy.py @ 0:d30785e31577 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:18:57 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:d30785e31577 |
|---|---|
| 1 """This will be the home for the policy that hooks in the new | |
| 2 code that adds all the email6 features. | |
| 3 """ | |
| 4 from __future__ import unicode_literals | |
| 5 from __future__ import division | |
| 6 from __future__ import absolute_import | |
| 7 from future.builtins import super | |
| 8 | |
| 9 from future.standard_library.email._policybase import (Policy, Compat32, | |
| 10 compat32, _extend_docstrings) | |
| 11 from future.standard_library.email.utils import _has_surrogates | |
| 12 from future.standard_library.email.headerregistry import HeaderRegistry as HeaderRegistry | |
| 13 | |
| 14 __all__ = [ | |
| 15 'Compat32', | |
| 16 'compat32', | |
| 17 'Policy', | |
| 18 'EmailPolicy', | |
| 19 'default', | |
| 20 'strict', | |
| 21 'SMTP', | |
| 22 'HTTP', | |
| 23 ] | |
| 24 | |
| 25 @_extend_docstrings | |
| 26 class EmailPolicy(Policy): | |
| 27 | |
| 28 """+ | |
| 29 PROVISIONAL | |
| 30 | |
| 31 The API extensions enabled by this policy are currently provisional. | |
| 32 Refer to the documentation for details. | |
| 33 | |
| 34 This policy adds new header parsing and folding algorithms. Instead of | |
| 35 simple strings, headers are custom objects with custom attributes | |
| 36 depending on the type of the field. The folding algorithm fully | |
| 37 implements RFCs 2047 and 5322. | |
| 38 | |
| 39 In addition to the settable attributes listed above that apply to | |
| 40 all Policies, this policy adds the following additional attributes: | |
| 41 | |
| 42 refold_source -- if the value for a header in the Message object | |
| 43 came from the parsing of some source, this attribute | |
| 44 indicates whether or not a generator should refold | |
| 45 that value when transforming the message back into | |
| 46 stream form. The possible values are: | |
| 47 | |
| 48 none -- all source values use original folding | |
| 49 long -- source values that have any line that is | |
| 50 longer than max_line_length will be | |
| 51 refolded | |
| 52 all -- all values are refolded. | |
| 53 | |
| 54 The default is 'long'. | |
| 55 | |
| 56 header_factory -- a callable that takes two arguments, 'name' and | |
| 57 'value', where 'name' is a header field name and | |
| 58 'value' is an unfolded header field value, and | |
| 59 returns a string-like object that represents that | |
| 60 header. A default header_factory is provided that | |
| 61 understands some of the RFC5322 header field types. | |
| 62 (Currently address fields and date fields have | |
| 63 special treatment, while all other fields are | |
| 64 treated as unstructured. This list will be | |
| 65 completed before the extension is marked stable.) | |
| 66 """ | |
| 67 | |
| 68 refold_source = 'long' | |
| 69 header_factory = HeaderRegistry() | |
| 70 | |
| 71 def __init__(self, **kw): | |
| 72 # Ensure that each new instance gets a unique header factory | |
| 73 # (as opposed to clones, which share the factory). | |
| 74 if 'header_factory' not in kw: | |
| 75 object.__setattr__(self, 'header_factory', HeaderRegistry()) | |
| 76 super().__init__(**kw) | |
| 77 | |
| 78 def header_max_count(self, name): | |
| 79 """+ | |
| 80 The implementation for this class returns the max_count attribute from | |
| 81 the specialized header class that would be used to construct a header | |
| 82 of type 'name'. | |
| 83 """ | |
| 84 return self.header_factory[name].max_count | |
| 85 | |
| 86 # The logic of the next three methods is chosen such that it is possible to | |
| 87 # switch a Message object between a Compat32 policy and a policy derived | |
| 88 # from this class and have the results stay consistent. This allows a | |
| 89 # Message object constructed with this policy to be passed to a library | |
| 90 # that only handles Compat32 objects, or to receive such an object and | |
| 91 # convert it to use the newer style by just changing its policy. It is | |
| 92 # also chosen because it postpones the relatively expensive full rfc5322 | |
| 93 # parse until as late as possible when parsing from source, since in many | |
| 94 # applications only a few headers will actually be inspected. | |
| 95 | |
| 96 def header_source_parse(self, sourcelines): | |
| 97 """+ | |
| 98 The name is parsed as everything up to the ':' and returned unmodified. | |
| 99 The value is determined by stripping leading whitespace off the | |
| 100 remainder of the first line, joining all subsequent lines together, and | |
| 101 stripping any trailing carriage return or linefeed characters. (This | |
| 102 is the same as Compat32). | |
| 103 | |
| 104 """ | |
| 105 name, value = sourcelines[0].split(':', 1) | |
| 106 value = value.lstrip(' \t') + ''.join(sourcelines[1:]) | |
| 107 return (name, value.rstrip('\r\n')) | |
| 108 | |
| 109 def header_store_parse(self, name, value): | |
| 110 """+ | |
| 111 The name is returned unchanged. If the input value has a 'name' | |
| 112 attribute and it matches the name ignoring case, the value is returned | |
| 113 unchanged. Otherwise the name and value are passed to header_factory | |
| 114 method, and the resulting custom header object is returned as the | |
| 115 value. In this case a ValueError is raised if the input value contains | |
| 116 CR or LF characters. | |
| 117 | |
| 118 """ | |
| 119 if hasattr(value, 'name') and value.name.lower() == name.lower(): | |
| 120 return (name, value) | |
| 121 if isinstance(value, str) and len(value.splitlines())>1: | |
| 122 raise ValueError("Header values may not contain linefeed " | |
| 123 "or carriage return characters") | |
| 124 return (name, self.header_factory(name, value)) | |
| 125 | |
| 126 def header_fetch_parse(self, name, value): | |
| 127 """+ | |
| 128 If the value has a 'name' attribute, it is returned to unmodified. | |
| 129 Otherwise the name and the value with any linesep characters removed | |
| 130 are passed to the header_factory method, and the resulting custom | |
| 131 header object is returned. Any surrogateescaped bytes get turned | |
| 132 into the unicode unknown-character glyph. | |
| 133 | |
| 134 """ | |
| 135 if hasattr(value, 'name'): | |
| 136 return value | |
| 137 return self.header_factory(name, ''.join(value.splitlines())) | |
| 138 | |
| 139 def fold(self, name, value): | |
| 140 """+ | |
| 141 Header folding is controlled by the refold_source policy setting. A | |
| 142 value is considered to be a 'source value' if and only if it does not | |
| 143 have a 'name' attribute (having a 'name' attribute means it is a header | |
| 144 object of some sort). If a source value needs to be refolded according | |
| 145 to the policy, it is converted into a custom header object by passing | |
| 146 the name and the value with any linesep characters removed to the | |
| 147 header_factory method. Folding of a custom header object is done by | |
| 148 calling its fold method with the current policy. | |
| 149 | |
| 150 Source values are split into lines using splitlines. If the value is | |
| 151 not to be refolded, the lines are rejoined using the linesep from the | |
| 152 policy and returned. The exception is lines containing non-ascii | |
| 153 binary data. In that case the value is refolded regardless of the | |
| 154 refold_source setting, which causes the binary data to be CTE encoded | |
| 155 using the unknown-8bit charset. | |
| 156 | |
| 157 """ | |
| 158 return self._fold(name, value, refold_binary=True) | |
| 159 | |
| 160 def fold_binary(self, name, value): | |
| 161 """+ | |
| 162 The same as fold if cte_type is 7bit, except that the returned value is | |
| 163 bytes. | |
| 164 | |
| 165 If cte_type is 8bit, non-ASCII binary data is converted back into | |
| 166 bytes. Headers with binary data are not refolded, regardless of the | |
| 167 refold_header setting, since there is no way to know whether the binary | |
| 168 data consists of single byte characters or multibyte characters. | |
| 169 | |
| 170 """ | |
| 171 folded = self._fold(name, value, refold_binary=self.cte_type=='7bit') | |
| 172 return folded.encode('ascii', 'surrogateescape') | |
| 173 | |
| 174 def _fold(self, name, value, refold_binary=False): | |
| 175 if hasattr(value, 'name'): | |
| 176 return value.fold(policy=self) | |
| 177 maxlen = self.max_line_length if self.max_line_length else float('inf') | |
| 178 lines = value.splitlines() | |
| 179 refold = (self.refold_source == 'all' or | |
| 180 self.refold_source == 'long' and | |
| 181 (lines and len(lines[0])+len(name)+2 > maxlen or | |
| 182 any(len(x) > maxlen for x in lines[1:]))) | |
| 183 if refold or refold_binary and _has_surrogates(value): | |
| 184 return self.header_factory(name, ''.join(lines)).fold(policy=self) | |
| 185 return name + ': ' + self.linesep.join(lines) + self.linesep | |
| 186 | |
| 187 | |
| 188 default = EmailPolicy() | |
| 189 # Make the default policy use the class default header_factory | |
| 190 del default.header_factory | |
| 191 strict = default.clone(raise_on_defect=True) | |
| 192 SMTP = default.clone(linesep='\r\n') | |
| 193 HTTP = default.clone(linesep='\r\n', max_line_length=None) |
