cpython: df81f9b67736 (original) (raw)
Mercurial > cpython
changeset 96117:df81f9b67736
#20098: add mangle_from_ policy option. This defaults to True in the compat32 policy for backward compatibility, but to False for all new policies. Patch by Milan Oberkirch, with a few tweaks. [#20098]
R David Murray rdmurray@bitdance.com | |
---|---|
date | Sun, 17 May 2015 14:24:33 -0400 |
parents | 9f0d5e33230f |
children | c060d20651fa |
files | Doc/library/email.policy.rst Doc/whatsnew/3.5.rst Lib/email/_policybase.py Lib/email/generator.py Lib/test/test_email/test_generator.py Lib/test/test_email/test_policy.py Misc/NEWS |
diffstat | 7 files changed, 76 insertions(+), 5 deletions(-)[+] [-] Doc/library/email.policy.rst 27 Doc/whatsnew/3.5.rst 6 Lib/email/_policybase.py 8 Lib/email/generator.py 13 Lib/test/test_email/test_generator.py 22 Lib/test/test_email/test_policy.py 2 Misc/NEWS 3 |
line wrap: on
line diff
--- a/Doc/library/email.policy.rst
+++ b/Doc/library/email.policy.rst
@@ -187,6 +187,18 @@ added matters. To illustrate::
:const:False
(the default), defects will be passed to the
:meth:register_defect
method.
+
+
- .. attribute:: mangle_from_ +
If :const:`True`, lines starting with *"From "* in the body are[](#l1.11)
escaped by putting a ``>`` in front of them. This parameter is used when[](#l1.12)
the message is being serialized by a generator.[](#l1.13)
Default: :const:`False`.[](#l1.14)
.. versionadded:: 3.5[](#l1.16)
The *mangle_from_* parameter.[](#l1.17)
+
The following :class:Policy
method is intended to be called by code using
the email library to create policy instances with custom settings:
@@ -319,6 +331,13 @@ added matters. To illustrate::
:const:compat32
, that is used as the default policy. Thus the default
behavior of the email package is to maintain compatibility with Python 3.2.
- The following attributes have values that are different from the
- :class:
Policy
default: + - .. attribute:: mangle_from_ +
The default is ``True``.[](#l1.31)
+
The class provides the following concrete implementations of the
abstract methods of :class:Policy
:
@@ -356,6 +375,14 @@ added matters. To illustrate::
line breaks and any (RFC invalid) binary data it may contain.
+An instance of :class:Compat32
is provided as a module constant:
+
+.. data:: compat32
+
- An instance of :class:
Compat32
, providing backward compatibility with the - behavior of the email package in Python 3.2. +
+ .. note:: The documentation below describes new policies that are included in the
--- a/Doc/whatsnew/3.5.rst
+++ b/Doc/whatsnew/3.5.rst
@@ -351,6 +351,12 @@ doctest
email
-----
+* A new policy option :attr:~email.policy.Policy.mangle_from_
controls
- whether or not lines that start with "From " in email bodies are prefixed with
- a '>' character by generators. The default is
True
for - :attr:
~email.policy.compat32
andFalse
for all other policies. - (Contributed by Milan Oberkirch in :issue:
20098
.) +
- A new method :meth:
~email.message.Message.get_content_disposition
provides easy access to a canonical value for the :mailheader:Content-Disposition
header (None
if there is no such header). (Contributed by Abhilash Raj
--- a/Lib/email/_policybase.py +++ b/Lib/email/_policybase.py @@ -149,12 +149,18 @@ class Policy(_PolicyBase, metaclass=abc. during serialization. None or 0 means no line wrapping is done. Default is 78.
- mangle_from_ -- a flag that, when True escapes From_ lines in the
body of the message by putting a `>' in front of[](#l3.8)
them. This is used when the message is being[](#l3.9)
serialized by a generator. Default: True.[](#l3.10)
+ """ raise_on_defect = False linesep = '\n' cte_type = '8bit' max_line_length = 78
def handle_defect(self, obj, defect): """Based on policy, either raise defect or call register_defect. @@ -266,6 +272,8 @@ class Compat32(Policy): replicates the behavior of the email package version 5.1. """
+ def _sanitize_header(self, name, value): # If the header value contains surrogates, return a Header using # the unknown-8bit charset to encode the bytes as encoded words.
--- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -32,16 +32,16 @@ class Generator: # Public interface #
- def init(self, outfp, mangle_from_=None, maxheaderlen=None, *, policy=None): """Create the generator for message flattening.
outfp is the output file-like object for writing the message to. It must have a write() method.
Optional mangle_from_ is a flag that, when True (the default), escapes[](#l4.15)
From_ lines in the body of the message by putting a `>' in front of[](#l4.16)
them.[](#l4.17)
Optional mangle_from_ is a flag that, when True (the default if policy[](#l4.18)
is not set), escapes From_ lines in the body of the message by putting[](#l4.19)
a `>' in front of them.[](#l4.20)
Optional maxheaderlen specifies the longest length for a non-continued header. When a header line is longer (in characters, with tabs @@ -56,6 +56,9 @@ class Generator: flatten method is used. """ +
if mangle_from_ is None:[](#l4.29)
mangle_from_ = True if policy is None else policy.mangle_from_[](#l4.30) self._fp = outfp[](#l4.31) self._mangle_from_ = mangle_from_[](#l4.32) self.maxheaderlen = maxheaderlen[](#l4.33)
@@ -449,7 +452,7 @@ class DecodedGenerator(Generator): Like the Generator base class, except that non-text parts are substituted with a format string representing the part. """
- def init(self, outfp, mangle_from_=None, maxheaderlen=78, fmt=None): """Like Generator.init() except that an additional optional argument is allowed.
--- a/Lib/test/test_email/test_generator.py +++ b/Lib/test/test_email/test_generator.py @@ -140,6 +140,28 @@ class TestGeneratorBase: g.flatten(msg, linesep='\n') self.assertEqual(s.getvalue(), self.typ(expected))
- def test_set_mangle_from_via_policy(self):
source = textwrap.dedent("""\[](#l5.8)
Subject: test that[](#l5.9)
from is mangeld in the body
From time to time I write a rhyme.[](#l5.12)
""")[](#l5.13)
variants = ([](#l5.14)
(None, True),[](#l5.15)
(policy.compat32, True),[](#l5.16)
(policy.default, False),[](#l5.17)
(policy.default.clone(mangle_from_=True), True),[](#l5.18)
)[](#l5.19)
for p, mangle in variants:[](#l5.20)
expected = source.replace('From ', '>From ') if mangle else source[](#l5.21)
with self.subTest(policy=p, mangle_from_=mangle):[](#l5.22)
msg = self.msgmaker(self.typ(source))[](#l5.23)
s = self.ioclass()[](#l5.24)
g = self.genclass(s, policy=p)[](#l5.25)
g.flatten(msg)[](#l5.26)
self.assertEqual(s.getvalue(), self.typ(expected))[](#l5.27)
+ class TestGenerator(TestGeneratorBase, TestEmailBase):
--- a/Lib/test/test_email/test_policy.py +++ b/Lib/test/test_email/test_policy.py @@ -22,6 +22,7 @@ class PolicyAPITests(unittest.TestCase): 'linesep': '\n', 'cte_type': '8bit', 'raise_on_defect': False,
'mangle_from_': True,[](#l6.7) }[](#l6.8)
These default values are the ones set on email.policy.default.
@@ -32,6 +33,7 @@ class PolicyAPITests(unittest.TestCase): If any of these defaults change, the docs must be updated. 'header_factory': email.policy.EmailPolicy.header_factory, 'refold_source': 'long', 'content_manager': email.policy.EmailPolicy.content_manager,
'mangle_from_': False,[](#l6.15) })[](#l6.16)
# For each policy under test, we give here what we expect the defaults to
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -47,6 +47,9 @@ Core and Builtins Library ------- +- Issue #20098: New mangle_from_ policy option for email, default True