mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
#27331: add policy keyword argument to all MIME subclasses.
Patch by Berker Peksag.
This commit is contained in:
parent
3788b85628
commit
56b1f1b4d5
11 changed files with 117 additions and 20 deletions
|
|
@ -25,7 +25,7 @@ Here are the classes:
|
||||||
|
|
||||||
.. currentmodule:: email.mime.base
|
.. currentmodule:: email.mime.base
|
||||||
|
|
||||||
.. class:: MIMEBase(_maintype, _subtype, **_params)
|
.. class:: MIMEBase(_maintype, _subtype, *, policy=compat32, **_params)
|
||||||
|
|
||||||
Module: :mod:`email.mime.base`
|
Module: :mod:`email.mime.base`
|
||||||
|
|
||||||
|
|
@ -41,10 +41,17 @@ Here are the classes:
|
||||||
key/value dictionary and is passed directly to :meth:`Message.add_header
|
key/value dictionary and is passed directly to :meth:`Message.add_header
|
||||||
<email.message.Message.add_header>`.
|
<email.message.Message.add_header>`.
|
||||||
|
|
||||||
|
If *policy* is specified, (defaults to the
|
||||||
|
:class:`compat32 <email.policy.Compat32>` policy) it will be passed to
|
||||||
|
:class:`~email.message.Message`.
|
||||||
|
|
||||||
The :class:`MIMEBase` class always adds a :mailheader:`Content-Type` header
|
The :class:`MIMEBase` class always adds a :mailheader:`Content-Type` header
|
||||||
(based on *_maintype*, *_subtype*, and *_params*), and a
|
(based on *_maintype*, *_subtype*, and *_params*), and a
|
||||||
:mailheader:`MIME-Version` header (always set to ``1.0``).
|
:mailheader:`MIME-Version` header (always set to ``1.0``).
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
Added *policy* keyword-only parameter.
|
||||||
|
|
||||||
|
|
||||||
.. currentmodule:: email.mime.nonmultipart
|
.. currentmodule:: email.mime.nonmultipart
|
||||||
|
|
||||||
|
|
@ -62,7 +69,8 @@ Here are the classes:
|
||||||
|
|
||||||
.. currentmodule:: email.mime.multipart
|
.. currentmodule:: email.mime.multipart
|
||||||
|
|
||||||
.. class:: MIMEMultipart(_subtype='mixed', boundary=None, _subparts=None, **_params)
|
.. class:: MIMEMultipart(_subtype='mixed', boundary=None, _subparts=None, \
|
||||||
|
*, policy=compat32, **_params)
|
||||||
|
|
||||||
Module: :mod:`email.mime.multipart`
|
Module: :mod:`email.mime.multipart`
|
||||||
|
|
||||||
|
|
@ -82,14 +90,20 @@ Here are the classes:
|
||||||
to the message by using the :meth:`Message.attach
|
to the message by using the :meth:`Message.attach
|
||||||
<email.message.Message.attach>` method.
|
<email.message.Message.attach>` method.
|
||||||
|
|
||||||
|
Optional *policy* argument defaults to :class:`compat32 <email.policy.Compat32>`.
|
||||||
|
|
||||||
Additional parameters for the :mailheader:`Content-Type` header are taken from
|
Additional parameters for the :mailheader:`Content-Type` header are taken from
|
||||||
the keyword arguments, or passed into the *_params* argument, which is a keyword
|
the keyword arguments, or passed into the *_params* argument, which is a keyword
|
||||||
dictionary.
|
dictionary.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
Added *policy* keyword-only parameter.
|
||||||
|
|
||||||
.. currentmodule:: email.mime.application
|
.. currentmodule:: email.mime.application
|
||||||
|
|
||||||
.. class:: MIMEApplication(_data, _subtype='octet-stream', _encoder=email.encoders.encode_base64, **_params)
|
.. class:: MIMEApplication(_data, _subtype='octet-stream', \
|
||||||
|
_encoder=email.encoders.encode_base64, \
|
||||||
|
*, policy=compat32, **_params)
|
||||||
|
|
||||||
Module: :mod:`email.mime.application`
|
Module: :mod:`email.mime.application`
|
||||||
|
|
||||||
|
|
@ -109,12 +123,18 @@ Here are the classes:
|
||||||
object as necessary. The default encoding is base64. See the
|
object as necessary. The default encoding is base64. See the
|
||||||
:mod:`email.encoders` module for a list of the built-in encoders.
|
:mod:`email.encoders` module for a list of the built-in encoders.
|
||||||
|
|
||||||
|
Optional *policy* argument defaults to :class:`compat32 <email.policy.Compat32>`.
|
||||||
|
|
||||||
*_params* are passed straight through to the base class constructor.
|
*_params* are passed straight through to the base class constructor.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
Added *policy* keyword-only parameter.
|
||||||
|
|
||||||
.. currentmodule:: email.mime.audio
|
.. currentmodule:: email.mime.audio
|
||||||
|
|
||||||
.. class:: MIMEAudio(_audiodata, _subtype=None, _encoder=email.encoders.encode_base64, **_params)
|
.. class:: MIMEAudio(_audiodata, _subtype=None, \
|
||||||
|
_encoder=email.encoders.encode_base64, \
|
||||||
|
*, policy=compat32, **_params)
|
||||||
|
|
||||||
Module: :mod:`email.mime.audio`
|
Module: :mod:`email.mime.audio`
|
||||||
|
|
||||||
|
|
@ -137,12 +157,18 @@ Here are the classes:
|
||||||
object as necessary. The default encoding is base64. See the
|
object as necessary. The default encoding is base64. See the
|
||||||
:mod:`email.encoders` module for a list of the built-in encoders.
|
:mod:`email.encoders` module for a list of the built-in encoders.
|
||||||
|
|
||||||
|
Optional *policy* argument defaults to :class:`compat32 <email.policy.Compat32>`.
|
||||||
|
|
||||||
*_params* are passed straight through to the base class constructor.
|
*_params* are passed straight through to the base class constructor.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
Added *policy* keyword-only parameter.
|
||||||
|
|
||||||
.. currentmodule:: email.mime.image
|
.. currentmodule:: email.mime.image
|
||||||
|
|
||||||
.. class:: MIMEImage(_imagedata, _subtype=None, _encoder=email.encoders.encode_base64, **_params)
|
.. class:: MIMEImage(_imagedata, _subtype=None, \
|
||||||
|
_encoder=email.encoders.encode_base64, \
|
||||||
|
*, policy=compat32, **_params)
|
||||||
|
|
||||||
Module: :mod:`email.mime.image`
|
Module: :mod:`email.mime.image`
|
||||||
|
|
||||||
|
|
@ -165,13 +191,17 @@ Here are the classes:
|
||||||
object as necessary. The default encoding is base64. See the
|
object as necessary. The default encoding is base64. See the
|
||||||
:mod:`email.encoders` module for a list of the built-in encoders.
|
:mod:`email.encoders` module for a list of the built-in encoders.
|
||||||
|
|
||||||
|
Optional *policy* argument defaults to :class:`compat32 <email.policy.Compat32>`.
|
||||||
|
|
||||||
*_params* are passed straight through to the :class:`~email.mime.base.MIMEBase`
|
*_params* are passed straight through to the :class:`~email.mime.base.MIMEBase`
|
||||||
constructor.
|
constructor.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
Added *policy* keyword-only parameter.
|
||||||
|
|
||||||
.. currentmodule:: email.mime.message
|
.. currentmodule:: email.mime.message
|
||||||
|
|
||||||
.. class:: MIMEMessage(_msg, _subtype='rfc822')
|
.. class:: MIMEMessage(_msg, _subtype='rfc822', *, policy=compat32)
|
||||||
|
|
||||||
Module: :mod:`email.mime.message`
|
Module: :mod:`email.mime.message`
|
||||||
|
|
||||||
|
|
@ -184,10 +214,14 @@ Here are the classes:
|
||||||
Optional *_subtype* sets the subtype of the message; it defaults to
|
Optional *_subtype* sets the subtype of the message; it defaults to
|
||||||
:mimetype:`rfc822`.
|
:mimetype:`rfc822`.
|
||||||
|
|
||||||
|
Optional *policy* argument defaults to :class:`compat32 <email.policy.Compat32>`.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
Added *policy* keyword-only parameter.
|
||||||
|
|
||||||
.. currentmodule:: email.mime.text
|
.. currentmodule:: email.mime.text
|
||||||
|
|
||||||
.. class:: MIMEText(_text, _subtype='plain', _charset=None)
|
.. class:: MIMEText(_text, _subtype='plain', _charset=None, *, policy=compat32)
|
||||||
|
|
||||||
Module: :mod:`email.mime.text`
|
Module: :mod:`email.mime.text`
|
||||||
|
|
||||||
|
|
@ -211,5 +245,10 @@ Here are the classes:
|
||||||
will automatically encode the new payload (and add a new
|
will automatically encode the new payload (and add a new
|
||||||
:mailheader:`Content-Transfer-Encoding` header).
|
:mailheader:`Content-Transfer-Encoding` header).
|
||||||
|
|
||||||
|
Optional *policy* argument defaults to :class:`compat32 <email.policy.Compat32>`.
|
||||||
|
|
||||||
.. versionchanged:: 3.5
|
.. versionchanged:: 3.5
|
||||||
*_charset* also accepts :class:`~email.charset.Charset` instances.
|
*_charset* also accepts :class:`~email.charset.Charset` instances.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
Added *policy* keyword-only parameter.
|
||||||
|
|
|
||||||
|
|
@ -455,6 +455,13 @@ Any code relying on the presence of ``default_format`` may
|
||||||
need to be adapted. See :issue:`27819` for more details.
|
need to be adapted. See :issue:`27819` for more details.
|
||||||
|
|
||||||
|
|
||||||
|
email
|
||||||
|
-----
|
||||||
|
|
||||||
|
The :mod:`email.mime` classes now all accept an optional *policy* keyword.
|
||||||
|
(Contributed by Berker Peksag in :issue:`27331`.)
|
||||||
|
|
||||||
|
|
||||||
encodings
|
encodings
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class MIMEApplication(MIMENonMultipart):
|
||||||
"""Class for generating application/* MIME documents."""
|
"""Class for generating application/* MIME documents."""
|
||||||
|
|
||||||
def __init__(self, _data, _subtype='octet-stream',
|
def __init__(self, _data, _subtype='octet-stream',
|
||||||
_encoder=encoders.encode_base64, **_params):
|
_encoder=encoders.encode_base64, *, policy=None, **_params):
|
||||||
"""Create an application/* type MIME document.
|
"""Create an application/* type MIME document.
|
||||||
|
|
||||||
_data is a string containing the raw application data.
|
_data is a string containing the raw application data.
|
||||||
|
|
@ -31,6 +31,7 @@ class MIMEApplication(MIMENonMultipart):
|
||||||
"""
|
"""
|
||||||
if _subtype is None:
|
if _subtype is None:
|
||||||
raise TypeError('Invalid application MIME subtype')
|
raise TypeError('Invalid application MIME subtype')
|
||||||
MIMENonMultipart.__init__(self, 'application', _subtype, **_params)
|
MIMENonMultipart.__init__(self, 'application', _subtype, policy=policy,
|
||||||
|
**_params)
|
||||||
self.set_payload(_data)
|
self.set_payload(_data)
|
||||||
_encoder(self)
|
_encoder(self)
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class MIMEAudio(MIMENonMultipart):
|
||||||
"""Class for generating audio/* MIME documents."""
|
"""Class for generating audio/* MIME documents."""
|
||||||
|
|
||||||
def __init__(self, _audiodata, _subtype=None,
|
def __init__(self, _audiodata, _subtype=None,
|
||||||
_encoder=encoders.encode_base64, **_params):
|
_encoder=encoders.encode_base64, *, policy=None, **_params):
|
||||||
"""Create an audio/* type MIME document.
|
"""Create an audio/* type MIME document.
|
||||||
|
|
||||||
_audiodata is a string containing the raw audio data. If this data
|
_audiodata is a string containing the raw audio data. If this data
|
||||||
|
|
@ -68,6 +68,7 @@ class MIMEAudio(MIMENonMultipart):
|
||||||
_subtype = _whatsnd(_audiodata)
|
_subtype = _whatsnd(_audiodata)
|
||||||
if _subtype is None:
|
if _subtype is None:
|
||||||
raise TypeError('Could not find audio MIME subtype')
|
raise TypeError('Could not find audio MIME subtype')
|
||||||
MIMENonMultipart.__init__(self, 'audio', _subtype, **_params)
|
MIMENonMultipart.__init__(self, 'audio', _subtype, policy=policy,
|
||||||
|
**_params)
|
||||||
self.set_payload(_audiodata)
|
self.set_payload(_audiodata)
|
||||||
_encoder(self)
|
_encoder(self)
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
__all__ = ['MIMEBase']
|
__all__ = ['MIMEBase']
|
||||||
|
|
||||||
|
import email.policy
|
||||||
|
|
||||||
from email import message
|
from email import message
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -13,14 +15,16 @@ from email import message
|
||||||
class MIMEBase(message.Message):
|
class MIMEBase(message.Message):
|
||||||
"""Base class for MIME specializations."""
|
"""Base class for MIME specializations."""
|
||||||
|
|
||||||
def __init__(self, _maintype, _subtype, **_params):
|
def __init__(self, _maintype, _subtype, *, policy=None, **_params):
|
||||||
"""This constructor adds a Content-Type: and a MIME-Version: header.
|
"""This constructor adds a Content-Type: and a MIME-Version: header.
|
||||||
|
|
||||||
The Content-Type: header is taken from the _maintype and _subtype
|
The Content-Type: header is taken from the _maintype and _subtype
|
||||||
arguments. Additional parameters for this header are taken from the
|
arguments. Additional parameters for this header are taken from the
|
||||||
keyword arguments.
|
keyword arguments.
|
||||||
"""
|
"""
|
||||||
message.Message.__init__(self)
|
if policy is None:
|
||||||
|
policy = email.policy.compat32
|
||||||
|
message.Message.__init__(self, policy=policy)
|
||||||
ctype = '%s/%s' % (_maintype, _subtype)
|
ctype = '%s/%s' % (_maintype, _subtype)
|
||||||
self.add_header('Content-Type', ctype, **_params)
|
self.add_header('Content-Type', ctype, **_params)
|
||||||
self['MIME-Version'] = '1.0'
|
self['MIME-Version'] = '1.0'
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class MIMEImage(MIMENonMultipart):
|
||||||
"""Class for generating image/* type MIME documents."""
|
"""Class for generating image/* type MIME documents."""
|
||||||
|
|
||||||
def __init__(self, _imagedata, _subtype=None,
|
def __init__(self, _imagedata, _subtype=None,
|
||||||
_encoder=encoders.encode_base64, **_params):
|
_encoder=encoders.encode_base64, *, policy=None, **_params):
|
||||||
"""Create an image/* type MIME document.
|
"""Create an image/* type MIME document.
|
||||||
|
|
||||||
_imagedata is a string containing the raw image data. If this data
|
_imagedata is a string containing the raw image data. If this data
|
||||||
|
|
@ -41,6 +41,7 @@ class MIMEImage(MIMENonMultipart):
|
||||||
_subtype = imghdr.what(None, _imagedata)
|
_subtype = imghdr.what(None, _imagedata)
|
||||||
if _subtype is None:
|
if _subtype is None:
|
||||||
raise TypeError('Could not guess image MIME subtype')
|
raise TypeError('Could not guess image MIME subtype')
|
||||||
MIMENonMultipart.__init__(self, 'image', _subtype, **_params)
|
MIMENonMultipart.__init__(self, 'image', _subtype, policy=policy,
|
||||||
|
**_params)
|
||||||
self.set_payload(_imagedata)
|
self.set_payload(_imagedata)
|
||||||
_encoder(self)
|
_encoder(self)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from email.mime.nonmultipart import MIMENonMultipart
|
||||||
class MIMEMessage(MIMENonMultipart):
|
class MIMEMessage(MIMENonMultipart):
|
||||||
"""Class representing message/* MIME documents."""
|
"""Class representing message/* MIME documents."""
|
||||||
|
|
||||||
def __init__(self, _msg, _subtype='rfc822'):
|
def __init__(self, _msg, _subtype='rfc822', *, policy=None):
|
||||||
"""Create a message/* type MIME document.
|
"""Create a message/* type MIME document.
|
||||||
|
|
||||||
_msg is a message object and must be an instance of Message, or a
|
_msg is a message object and must be an instance of Message, or a
|
||||||
|
|
@ -24,7 +24,7 @@ class MIMEMessage(MIMENonMultipart):
|
||||||
default is "rfc822" (this is defined by the MIME standard, even though
|
default is "rfc822" (this is defined by the MIME standard, even though
|
||||||
the term "rfc822" is technically outdated by RFC 2822).
|
the term "rfc822" is technically outdated by RFC 2822).
|
||||||
"""
|
"""
|
||||||
MIMENonMultipart.__init__(self, 'message', _subtype)
|
MIMENonMultipart.__init__(self, 'message', _subtype, policy=policy)
|
||||||
if not isinstance(_msg, message.Message):
|
if not isinstance(_msg, message.Message):
|
||||||
raise TypeError('Argument is not an instance of Message')
|
raise TypeError('Argument is not an instance of Message')
|
||||||
# It's convenient to use this base class method. We need to do it
|
# It's convenient to use this base class method. We need to do it
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ class MIMEMultipart(MIMEBase):
|
||||||
"""Base class for MIME multipart/* type messages."""
|
"""Base class for MIME multipart/* type messages."""
|
||||||
|
|
||||||
def __init__(self, _subtype='mixed', boundary=None, _subparts=None,
|
def __init__(self, _subtype='mixed', boundary=None, _subparts=None,
|
||||||
|
*, policy=None,
|
||||||
**_params):
|
**_params):
|
||||||
"""Creates a multipart/* type message.
|
"""Creates a multipart/* type message.
|
||||||
|
|
||||||
|
|
@ -33,7 +34,7 @@ class MIMEMultipart(MIMEBase):
|
||||||
Additional parameters for the Content-Type header are taken from the
|
Additional parameters for the Content-Type header are taken from the
|
||||||
keyword arguments (or passed into the _params argument).
|
keyword arguments (or passed into the _params argument).
|
||||||
"""
|
"""
|
||||||
MIMEBase.__init__(self, 'multipart', _subtype, **_params)
|
MIMEBase.__init__(self, 'multipart', _subtype, policy=policy, **_params)
|
||||||
|
|
||||||
# Initialise _payload to an empty list as the Message superclass's
|
# Initialise _payload to an empty list as the Message superclass's
|
||||||
# implementation of is_multipart assumes that _payload is a list for
|
# implementation of is_multipart assumes that _payload is a list for
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from email.mime.nonmultipart import MIMENonMultipart
|
||||||
class MIMEText(MIMENonMultipart):
|
class MIMEText(MIMENonMultipart):
|
||||||
"""Class for generating text/* type MIME documents."""
|
"""Class for generating text/* type MIME documents."""
|
||||||
|
|
||||||
def __init__(self, _text, _subtype='plain', _charset=None):
|
def __init__(self, _text, _subtype='plain', _charset=None, *, policy=None):
|
||||||
"""Create a text/* type MIME document.
|
"""Create a text/* type MIME document.
|
||||||
|
|
||||||
_text is the string for this message object.
|
_text is the string for this message object.
|
||||||
|
|
@ -38,7 +38,7 @@ class MIMEText(MIMENonMultipart):
|
||||||
if isinstance(_charset, Charset):
|
if isinstance(_charset, Charset):
|
||||||
_charset = str(_charset)
|
_charset = str(_charset)
|
||||||
|
|
||||||
MIMENonMultipart.__init__(self, 'text', _subtype,
|
MIMENonMultipart.__init__(self, 'text', _subtype, policy=policy,
|
||||||
**{'charset': _charset})
|
**{'charset': _charset})
|
||||||
|
|
||||||
self.set_payload(_text, _charset)
|
self.set_payload(_text, _charset)
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ from email.mime.image import MIMEImage
|
||||||
from email.mime.base import MIMEBase
|
from email.mime.base import MIMEBase
|
||||||
from email.mime.message import MIMEMessage
|
from email.mime.message import MIMEMessage
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.nonmultipart import MIMENonMultipart
|
||||||
from email import utils
|
from email import utils
|
||||||
from email import errors
|
from email import errors
|
||||||
from email import encoders
|
from email import encoders
|
||||||
|
|
@ -2062,7 +2063,13 @@ YXNkZg==
|
||||||
--===============0012394164==--""")
|
--===============0012394164==--""")
|
||||||
self.assertEqual(m.get_payload(0).get_payload(), 'YXNkZg==')
|
self.assertEqual(m.get_payload(0).get_payload(), 'YXNkZg==')
|
||||||
|
|
||||||
|
def test_mimebase_default_policy(self):
|
||||||
|
m = MIMEBase('multipart', 'mixed')
|
||||||
|
self.assertIs(m.policy, email.policy.compat32)
|
||||||
|
|
||||||
|
def test_mimebase_custom_policy(self):
|
||||||
|
m = MIMEBase('multipart', 'mixed', policy=email.policy.default)
|
||||||
|
self.assertIs(m.policy, email.policy.default)
|
||||||
|
|
||||||
# Test some badly formatted messages
|
# Test some badly formatted messages
|
||||||
class TestNonConformant(TestEmailBase):
|
class TestNonConformant(TestEmailBase):
|
||||||
|
|
@ -2664,6 +2671,19 @@ message 2
|
||||||
msg = MIMEMultipart()
|
msg = MIMEMultipart()
|
||||||
self.assertTrue(msg.is_multipart())
|
self.assertTrue(msg.is_multipart())
|
||||||
|
|
||||||
|
def test_multipart_default_policy(self):
|
||||||
|
msg = MIMEMultipart()
|
||||||
|
msg['To'] = 'a@b.com'
|
||||||
|
msg['To'] = 'c@d.com'
|
||||||
|
self.assertEqual(msg.get_all('to'), ['a@b.com', 'c@d.com'])
|
||||||
|
|
||||||
|
def test_multipart_custom_policy(self):
|
||||||
|
msg = MIMEMultipart(policy=email.policy.default)
|
||||||
|
msg['To'] = 'a@b.com'
|
||||||
|
with self.assertRaises(ValueError) as cm:
|
||||||
|
msg['To'] = 'c@d.com'
|
||||||
|
self.assertEqual(str(cm.exception),
|
||||||
|
'There may be at most 1 To headers in a message')
|
||||||
|
|
||||||
# A general test of parser->model->generator idempotency. IOW, read a message
|
# A general test of parser->model->generator idempotency. IOW, read a message
|
||||||
# in, parse it into a message object tree, then without touching the tree,
|
# in, parse it into a message object tree, then without touching the tree,
|
||||||
|
|
@ -3313,6 +3333,27 @@ multipart/report
|
||||||
g.flatten(msg, linesep='\r\n')
|
g.flatten(msg, linesep='\r\n')
|
||||||
self.assertEqual(s.getvalue(), msgtxt)
|
self.assertEqual(s.getvalue(), msgtxt)
|
||||||
|
|
||||||
|
def test_mime_classes_policy_argument(self):
|
||||||
|
with openfile('audiotest.au', 'rb') as fp:
|
||||||
|
audiodata = fp.read()
|
||||||
|
with openfile('PyBanner048.gif', 'rb') as fp:
|
||||||
|
bindata = fp.read()
|
||||||
|
classes = [
|
||||||
|
(MIMEApplication, ('',)),
|
||||||
|
(MIMEAudio, (audiodata,)),
|
||||||
|
(MIMEImage, (bindata,)),
|
||||||
|
(MIMEMessage, (Message(),)),
|
||||||
|
(MIMENonMultipart, ('multipart', 'mixed')),
|
||||||
|
(MIMEText, ('',)),
|
||||||
|
]
|
||||||
|
for cls, constructor in classes:
|
||||||
|
with self.subTest(cls=cls.__name__, policy='compat32'):
|
||||||
|
m = cls(*constructor)
|
||||||
|
self.assertIs(m.policy, email.policy.compat32)
|
||||||
|
with self.subTest(cls=cls.__name__, policy='default'):
|
||||||
|
m = cls(*constructor, policy=email.policy.default)
|
||||||
|
self.assertIs(m.policy, email.policy.default)
|
||||||
|
|
||||||
|
|
||||||
# Test the iterator/generators
|
# Test the iterator/generators
|
||||||
class TestIterators(TestEmailBase):
|
class TestIterators(TestEmailBase):
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue 27331: The email.mime classes now all accept an optional policy keyword.
|
||||||
|
|
||||||
- Issue 27988: Fix email iter_attachments incorrect mutation of payload list.
|
- Issue 27988: Fix email iter_attachments incorrect mutation of payload list.
|
||||||
|
|
||||||
- Issue #16113: Add SHA-3 and SHAKE support to hashlib module.
|
- Issue #16113: Add SHA-3 and SHAKE support to hashlib module.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue