OLD | NEW |
(Empty) | |
| 1 """Policy framework for the email package. |
| 2 |
| 3 Allows fine grained feature control of how the package parses and emits data. |
| 4 """ |
| 5 from __future__ import unicode_literals |
| 6 from __future__ import print_function |
| 7 from __future__ import division |
| 8 from __future__ import absolute_import |
| 9 from future.builtins import super |
| 10 from future.builtins import str |
| 11 from future.utils import with_metaclass |
| 12 |
| 13 import abc |
| 14 from future.backports.email import header |
| 15 from future.backports.email import charset as _charset |
| 16 from future.backports.email.utils import _has_surrogates |
| 17 |
| 18 __all__ = [ |
| 19 'Policy', |
| 20 'Compat32', |
| 21 'compat32', |
| 22 ] |
| 23 |
| 24 |
| 25 class _PolicyBase(object): |
| 26 |
| 27 """Policy Object basic framework. |
| 28 |
| 29 This class is useless unless subclassed. A subclass should define |
| 30 class attributes with defaults for any values that are to be |
| 31 managed by the Policy object. The constructor will then allow |
| 32 non-default values to be set for these attributes at instance |
| 33 creation time. The instance will be callable, taking these same |
| 34 attributes keyword arguments, and returning a new instance |
| 35 identical to the called instance except for those values changed |
| 36 by the keyword arguments. Instances may be added, yielding new |
| 37 instances with any non-default values from the right hand |
| 38 operand overriding those in the left hand operand. That is, |
| 39 |
| 40 A + B == A(<non-default values of B>) |
| 41 |
| 42 The repr of an instance can be used to reconstruct the object |
| 43 if and only if the repr of the values can be used to reconstruct |
| 44 those values. |
| 45 |
| 46 """ |
| 47 |
| 48 def __init__(self, **kw): |
| 49 """Create new Policy, possibly overriding some defaults. |
| 50 |
| 51 See class docstring for a list of overridable attributes. |
| 52 |
| 53 """ |
| 54 for name, value in kw.items(): |
| 55 if hasattr(self, name): |
| 56 super(_PolicyBase,self).__setattr__(name, value) |
| 57 else: |
| 58 raise TypeError( |
| 59 "{!r} is an invalid keyword argument for {}".format( |
| 60 name, self.__class__.__name__)) |
| 61 |
| 62 def __repr__(self): |
| 63 args = [ "{}={!r}".format(name, value) |
| 64 for name, value in self.__dict__.items() ] |
| 65 return "{}({})".format(self.__class__.__name__, ', '.join(args)) |
| 66 |
| 67 def clone(self, **kw): |
| 68 """Return a new instance with specified attributes changed. |
| 69 |
| 70 The new instance has the same attribute values as the current object, |
| 71 except for the changes passed in as keyword arguments. |
| 72 |
| 73 """ |
| 74 newpolicy = self.__class__.__new__(self.__class__) |
| 75 for attr, value in self.__dict__.items(): |
| 76 object.__setattr__(newpolicy, attr, value) |
| 77 for attr, value in kw.items(): |
| 78 if not hasattr(self, attr): |
| 79 raise TypeError( |
| 80 "{!r} is an invalid keyword argument for {}".format( |
| 81 attr, self.__class__.__name__)) |
| 82 object.__setattr__(newpolicy, attr, value) |
| 83 return newpolicy |
| 84 |
| 85 def __setattr__(self, name, value): |
| 86 if hasattr(self, name): |
| 87 msg = "{!r} object attribute {!r} is read-only" |
| 88 else: |
| 89 msg = "{!r} object has no attribute {!r}" |
| 90 raise AttributeError(msg.format(self.__class__.__name__, name)) |
| 91 |
| 92 def __add__(self, other): |
| 93 """Non-default values from right operand override those from left. |
| 94 |
| 95 The object returned is a new instance of the subclass. |
| 96 |
| 97 """ |
| 98 return self.clone(**other.__dict__) |
| 99 |
| 100 |
| 101 def _append_doc(doc, added_doc): |
| 102 doc = doc.rsplit('\n', 1)[0] |
| 103 added_doc = added_doc.split('\n', 1)[1] |
| 104 return doc + '\n' + added_doc |
| 105 |
| 106 def _extend_docstrings(cls): |
| 107 if cls.__doc__ and cls.__doc__.startswith('+'): |
| 108 cls.__doc__ = _append_doc(cls.__bases__[0].__doc__, cls.__doc__) |
| 109 for name, attr in cls.__dict__.items(): |
| 110 if attr.__doc__ and attr.__doc__.startswith('+'): |
| 111 for c in (c for base in cls.__bases__ for c in base.mro()): |
| 112 doc = getattr(getattr(c, name), '__doc__') |
| 113 if doc: |
| 114 attr.__doc__ = _append_doc(doc, attr.__doc__) |
| 115 break |
| 116 return cls |
| 117 |
| 118 |
| 119 class Policy(with_metaclass(abc.ABCMeta, _PolicyBase)): |
| 120 |
| 121 r"""Controls for how messages are interpreted and formatted. |
| 122 |
| 123 Most of the classes and many of the methods in the email package accept |
| 124 Policy objects as parameters. A Policy object contains a set of values and |
| 125 functions that control how input is interpreted and how output is rendered. |
| 126 For example, the parameter 'raise_on_defect' controls whether or not an RFC |
| 127 violation results in an error being raised or not, while 'max_line_length' |
| 128 controls the maximum length of output lines when a Message is serialized. |
| 129 |
| 130 Any valid attribute may be overridden when a Policy is created by passing |
| 131 it as a keyword argument to the constructor. Policy objects are immutable, |
| 132 but a new Policy object can be created with only certain values changed by |
| 133 calling the Policy instance with keyword arguments. Policy objects can |
| 134 also be added, producing a new Policy object in which the non-default |
| 135 attributes set in the right hand operand overwrite those specified in the |
| 136 left operand. |
| 137 |
| 138 Settable attributes: |
| 139 |
| 140 raise_on_defect -- If true, then defects should be raised as errors. |
| 141 Default: False. |
| 142 |
| 143 linesep -- string containing the value to use as separation |
| 144 between output lines. Default '\n'. |
| 145 |
| 146 cte_type -- Type of allowed content transfer encodings |
| 147 |
| 148 7bit -- ASCII only |
| 149 8bit -- Content-Transfer-Encoding: 8bit is allowed |
| 150 |
| 151 Default: 8bit. Also controls the disposition of |
| 152 (RFC invalid) binary data in headers; see the |
| 153 documentation of the binary_fold method. |
| 154 |
| 155 max_line_length -- maximum length of lines, excluding 'linesep', |
| 156 during serialization. None or 0 means no line |
| 157 wrapping is done. Default is 78. |
| 158 |
| 159 """ |
| 160 |
| 161 raise_on_defect = False |
| 162 linesep = '\n' |
| 163 cte_type = '8bit' |
| 164 max_line_length = 78 |
| 165 |
| 166 def handle_defect(self, obj, defect): |
| 167 """Based on policy, either raise defect or call register_defect. |
| 168 |
| 169 handle_defect(obj, defect) |
| 170 |
| 171 defect should be a Defect subclass, but in any case must be an |
| 172 Exception subclass. obj is the object on which the defect should be |
| 173 registered if it is not raised. If the raise_on_defect is True, the |
| 174 defect is raised as an error, otherwise the object and the defect are |
| 175 passed to register_defect. |
| 176 |
| 177 This method is intended to be called by parsers that discover defects. |
| 178 The email package parsers always call it with Defect instances. |
| 179 |
| 180 """ |
| 181 if self.raise_on_defect: |
| 182 raise defect |
| 183 self.register_defect(obj, defect) |
| 184 |
| 185 def register_defect(self, obj, defect): |
| 186 """Record 'defect' on 'obj'. |
| 187 |
| 188 Called by handle_defect if raise_on_defect is False. This method is |
| 189 part of the Policy API so that Policy subclasses can implement custom |
| 190 defect handling. The default implementation calls the append method of |
| 191 the defects attribute of obj. The objects used by the email package by |
| 192 default that get passed to this method will always have a defects |
| 193 attribute with an append method. |
| 194 |
| 195 """ |
| 196 obj.defects.append(defect) |
| 197 |
| 198 def header_max_count(self, name): |
| 199 """Return the maximum allowed number of headers named 'name'. |
| 200 |
| 201 Called when a header is added to a Message object. If the returned |
| 202 value is not 0 or None, and there are already a number of headers with |
| 203 the name 'name' equal to the value returned, a ValueError is raised. |
| 204 |
| 205 Because the default behavior of Message's __setitem__ is to append the |
| 206 value to the list of headers, it is easy to create duplicate headers |
| 207 without realizing it. This method allows certain headers to be limited |
| 208 in the number of instances of that header that may be added to a |
| 209 Message programmatically. (The limit is not observed by the parser, |
| 210 which will faithfully produce as many headers as exist in the message |
| 211 being parsed.) |
| 212 |
| 213 The default implementation returns None for all header names. |
| 214 """ |
| 215 return None |
| 216 |
| 217 @abc.abstractmethod |
| 218 def header_source_parse(self, sourcelines): |
| 219 """Given a list of linesep terminated strings constituting the lines of |
| 220 a single header, return the (name, value) tuple that should be stored |
| 221 in the model. The input lines should retain their terminating linesep |
| 222 characters. The lines passed in by the email package may contain |
| 223 surrogateescaped binary data. |
| 224 """ |
| 225 raise NotImplementedError |
| 226 |
| 227 @abc.abstractmethod |
| 228 def header_store_parse(self, name, value): |
| 229 """Given the header name and the value provided by the application |
| 230 program, return the (name, value) that should be stored in the model. |
| 231 """ |
| 232 raise NotImplementedError |
| 233 |
| 234 @abc.abstractmethod |
| 235 def header_fetch_parse(self, name, value): |
| 236 """Given the header name and the value from the model, return the value |
| 237 to be returned to the application program that is requesting that |
| 238 header. The value passed in by the email package may contain |
| 239 surrogateescaped binary data if the lines were parsed by a BytesParser. |
| 240 The returned value should not contain any surrogateescaped data. |
| 241 |
| 242 """ |
| 243 raise NotImplementedError |
| 244 |
| 245 @abc.abstractmethod |
| 246 def fold(self, name, value): |
| 247 """Given the header name and the value from the model, return a string |
| 248 containing linesep characters that implement the folding of the header |
| 249 according to the policy controls. The value passed in by the email |
| 250 package may contain surrogateescaped binary data if the lines were |
| 251 parsed by a BytesParser. The returned value should not contain any |
| 252 surrogateescaped data. |
| 253 |
| 254 """ |
| 255 raise NotImplementedError |
| 256 |
| 257 @abc.abstractmethod |
| 258 def fold_binary(self, name, value): |
| 259 """Given the header name and the value from the model, return binary |
| 260 data containing linesep characters that implement the folding of the |
| 261 header according to the policy controls. The value passed in by the |
| 262 email package may contain surrogateescaped binary data. |
| 263 |
| 264 """ |
| 265 raise NotImplementedError |
| 266 |
| 267 |
| 268 @_extend_docstrings |
| 269 class Compat32(Policy): |
| 270 |
| 271 """+ |
| 272 This particular policy is the backward compatibility Policy. It |
| 273 replicates the behavior of the email package version 5.1. |
| 274 """ |
| 275 |
| 276 def _sanitize_header(self, name, value): |
| 277 # If the header value contains surrogates, return a Header using |
| 278 # the unknown-8bit charset to encode the bytes as encoded words. |
| 279 if not isinstance(value, str): |
| 280 # Assume it is already a header object |
| 281 return value |
| 282 if _has_surrogates(value): |
| 283 return header.Header(value, charset=_charset.UNKNOWN8BIT, |
| 284 header_name=name) |
| 285 else: |
| 286 return value |
| 287 |
| 288 def header_source_parse(self, sourcelines): |
| 289 """+ |
| 290 The name is parsed as everything up to the ':' and returned unmodified. |
| 291 The value is determined by stripping leading whitespace off the |
| 292 remainder of the first line, joining all subsequent lines together, and |
| 293 stripping any trailing carriage return or linefeed characters. |
| 294 |
| 295 """ |
| 296 name, value = sourcelines[0].split(':', 1) |
| 297 value = value.lstrip(' \t') + ''.join(sourcelines[1:]) |
| 298 return (name, value.rstrip('\r\n')) |
| 299 |
| 300 def header_store_parse(self, name, value): |
| 301 """+ |
| 302 The name and value are returned unmodified. |
| 303 """ |
| 304 return (name, value) |
| 305 |
| 306 def header_fetch_parse(self, name, value): |
| 307 """+ |
| 308 If the value contains binary data, it is converted into a Header object |
| 309 using the unknown-8bit charset. Otherwise it is returned unmodified. |
| 310 """ |
| 311 return self._sanitize_header(name, value) |
| 312 |
| 313 def fold(self, name, value): |
| 314 """+ |
| 315 Headers are folded using the Header folding algorithm, which preserves |
| 316 existing line breaks in the value, and wraps each resulting line to the |
| 317 max_line_length. Non-ASCII binary data are CTE encoded using the |
| 318 unknown-8bit charset. |
| 319 |
| 320 """ |
| 321 return self._fold(name, value, sanitize=True) |
| 322 |
| 323 def fold_binary(self, name, value): |
| 324 """+ |
| 325 Headers are folded using the Header folding algorithm, which preserves |
| 326 existing line breaks in the value, and wraps each resulting line to the |
| 327 max_line_length. If cte_type is 7bit, non-ascii binary data is CTE |
| 328 encoded using the unknown-8bit charset. Otherwise the original source |
| 329 header is used, with its existing line breaks and/or binary data. |
| 330 |
| 331 """ |
| 332 folded = self._fold(name, value, sanitize=self.cte_type=='7bit') |
| 333 return folded.encode('ascii', 'surrogateescape') |
| 334 |
| 335 def _fold(self, name, value, sanitize): |
| 336 parts = [] |
| 337 parts.append('%s: ' % name) |
| 338 if isinstance(value, str): |
| 339 if _has_surrogates(value): |
| 340 if sanitize: |
| 341 h = header.Header(value, |
| 342 charset=_charset.UNKNOWN8BIT, |
| 343 header_name=name) |
| 344 else: |
| 345 # If we have raw 8bit data in a byte string, we have no idea |
| 346 # what the encoding is. There is no safe way to split this |
| 347 # string. If it's ascii-subset, then we could do a normal |
| 348 # ascii split, but if it's multibyte then we could break the |
| 349 # string. There's no way to know so the least harm seems to |
| 350 # be to not split the string and risk it being too long. |
| 351 parts.append(value) |
| 352 h = None |
| 353 else: |
| 354 h = header.Header(value, header_name=name) |
| 355 else: |
| 356 # Assume it is a Header-like object. |
| 357 h = value |
| 358 if h is not None: |
| 359 parts.append(h.encode(linesep=self.linesep, |
| 360 maxlinelen=self.max_line_length)) |
| 361 parts.append(self.linesep) |
| 362 return ''.join(parts) |
| 363 |
| 364 |
| 365 compat32 = Compat32() |
OLD | NEW |