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