annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/email/_policybase.py @ 68:5028fdace37b

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