ยปCore Development>Code coverage>Lib/email/_policybase.py

Python code coverage for Lib/email/_policybase.py

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