[Python-checkins] cpython: #20098: add mangle_from_ policy option.

r.david.murray python-checkins at python.org
Sun May 17 20:24:48 CEST 2015


https://hg.python.org/cpython/rev/df81f9b67736
changeset:   96117:df81f9b67736
user:        R David Murray <rdmurray at bitdance.com>
date:        Sun May 17 14:24:33 2015 -0400
summary:
  #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.

files:
  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 +
  7 files changed, 76 insertions(+), 5 deletions(-)


diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst
--- a/Doc/library/email.policy.rst
+++ b/Doc/library/email.policy.rst
@@ -187,6 +187,18 @@
       :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
+      escaped by putting a ``>`` in front of them. This parameter is used when
+      the message is being serialized by a generator.
+      Default: :const:`False`.
+
+      .. versionadded:: 3.5
+         The *mangle_from_* parameter.
+
    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 @@
    :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``.
+
    The class provides the following concrete implementations of the
    abstract methods of :class:`Policy`:
 
@@ -356,6 +375,14 @@
       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
diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst
--- a/Doc/whatsnew/3.5.rst
+++ b/Doc/whatsnew/3.5.rst
@@ -351,6 +351,12 @@
 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` and ``False`` 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
diff --git a/Lib/email/_policybase.py b/Lib/email/_policybase.py
--- a/Lib/email/_policybase.py
+++ b/Lib/email/_policybase.py
@@ -149,12 +149,18 @@
                            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
+                           them. This is used when the message is being
+                           serialized by a generator. Default: True.
+
     """
 
     raise_on_defect = False
     linesep = '\n'
     cte_type = '8bit'
     max_line_length = 78
+    mangle_from_ = False
 
     def handle_defect(self, obj, defect):
         """Based on policy, either raise defect or call register_defect.
@@ -266,6 +272,8 @@
     replicates the behavior of the email package version 5.1.
     """
 
+    mangle_from_ = True
+
     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.
diff --git a/Lib/email/generator.py b/Lib/email/generator.py
--- a/Lib/email/generator.py
+++ b/Lib/email/generator.py
@@ -32,16 +32,16 @@
     # Public interface
     #
 
-    def __init__(self, outfp, mangle_from_=True, maxheaderlen=None, *,
+    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
-        From_ lines in the body of the message by putting a `>' in front of
-        them.
+        Optional mangle_from_ is a flag that, when True (the default if policy
+        is not set), escapes From_ lines in the body of the message by putting
+        a `>' in front of them.
 
         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 @@
         flatten method is used.
 
         """
+
+        if mangle_from_ is None:
+            mangle_from_ = True if policy is None else policy.mangle_from_
         self._fp = outfp
         self._mangle_from_ = mangle_from_
         self.maxheaderlen = maxheaderlen
@@ -449,7 +452,7 @@
     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_=True, maxheaderlen=78, fmt=None):
+    def __init__(self, outfp, mangle_from_=None, maxheaderlen=78, fmt=None):
         """Like Generator.__init__() except that an additional optional
         argument is allowed.
 
diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py
--- a/Lib/test/test_email/test_generator.py
+++ b/Lib/test/test_email/test_generator.py
@@ -140,6 +140,28 @@
         g.flatten(msg, linesep='\n')
         self.assertEqual(s.getvalue(), self.typ(expected))
 
+    def test_set_mangle_from_via_policy(self):
+        source = textwrap.dedent("""\
+            Subject: test that
+             from is mangeld in the body!
+
+            From time to time I write a rhyme.
+            """)
+        variants = (
+            (None, True),
+            (policy.compat32, True),
+            (policy.default, False),
+            (policy.default.clone(mangle_from_=True), True),
+            )
+        for p, mangle in variants:
+            expected = source.replace('From ', '>From ') if mangle else source
+            with self.subTest(policy=p, mangle_from_=mangle):
+                msg = self.msgmaker(self.typ(source))
+                s = self.ioclass()
+                g = self.genclass(s, policy=p)
+                g.flatten(msg)
+                self.assertEqual(s.getvalue(), self.typ(expected))
+
 
 class TestGenerator(TestGeneratorBase, TestEmailBase):
 
diff --git a/Lib/test/test_email/test_policy.py b/Lib/test/test_email/test_policy.py
--- a/Lib/test/test_email/test_policy.py
+++ b/Lib/test/test_email/test_policy.py
@@ -22,6 +22,7 @@
         'linesep':                  '\n',
         'cte_type':                 '8bit',
         'raise_on_defect':          False,
+        'mangle_from_':             True,
         }
     # These default values are the ones set on email.policy.default.
     # If any of these defaults change, the docs must be updated.
@@ -32,6 +33,7 @@
         'header_factory':           email.policy.EmailPolicy.header_factory,
         'refold_source':            'long',
         'content_manager':          email.policy.EmailPolicy.content_manager,
+        'mangle_from_':             False,
         })
 
     # For each policy under test, we give here what we expect the defaults to
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -47,6 +47,9 @@
 Library
 -------
 
+- Issue #20098: New mangle_from_ policy option for email, default True
+  for compat32, but False for all other policies.
+
 - Issue #24211: The email library now supports RFC 6532: it can generate
   headers using utf-8 instead of encoded words.
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list