diff options
-rw-r--r-- | Lib/mailbox.py | 15 | ||||
-rw-r--r-- | Lib/test/test_mailbox.py | 23 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
3 files changed, 38 insertions, 3 deletions
diff --git a/Lib/mailbox.py b/Lib/mailbox.py index 325b9c9..7a29555 100644 --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -1462,9 +1462,10 @@ class Message(email.message.Message): def _become_message(self, message): """Assume the non-format-specific state of message.""" - for name in ('_headers', '_unixfrom', '_payload', '_charset', - 'preamble', 'epilogue', 'defects', '_default_type'): - self.__dict__[name] = message.__dict__[name] + type_specific = getattr(message, '_type_specific_attributes', []) + for name in message.__dict__: + if name not in type_specific: + self.__dict__[name] = message.__dict__[name] def _explain_to(self, message): """Copy format-specific state to message insofar as possible.""" @@ -1477,6 +1478,8 @@ class Message(email.message.Message): class MaildirMessage(Message): """Message with Maildir-specific properties.""" + _type_specific_attributes = ['_subdir', '_info', '_date'] + def __init__(self, message=None): """Initialize a MaildirMessage instance.""" self._subdir = 'new' @@ -1584,6 +1587,8 @@ class MaildirMessage(Message): class _mboxMMDFMessage(Message): """Message with mbox- or MMDF-specific properties.""" + _type_specific_attributes = ['_from'] + def __init__(self, message=None): """Initialize an mboxMMDFMessage instance.""" self.set_from('MAILER-DAEMON', True) @@ -1699,6 +1704,8 @@ class mboxMessage(_mboxMMDFMessage): class MHMessage(Message): """Message with MH-specific properties.""" + _type_specific_attributes = ['_sequences'] + def __init__(self, message=None): """Initialize an MHMessage instance.""" self._sequences = [] @@ -1769,6 +1776,8 @@ class MHMessage(Message): class BabylMessage(Message): """Message with Babyl-specific properties.""" + _type_specific_attributes = ['_labels', '_visible'] + def __init__(self, message=None): """Initialize an BabylMessage instance.""" self._labels = [] diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py index 95f8e0d..0fe4bd9 100644 --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -1330,6 +1330,14 @@ class TestMessage(TestBase, unittest.TestCase): # Initialize with invalid argument self.assertRaises(TypeError, lambda: self._factory(object())) + def test_all_eMM_attribues_exist(self): + # Issue 12537 + eMM = email.message_from_string(_sample_message) + msg = self._factory(_sample_message) + for attr in eMM.__dict__: + self.assertTrue(attr in msg.__dict__, + '{} attribute does not exist'.format(attr)) + def test_become_message(self): # Take on the state of another message eMM = email.message_from_string(_sample_message) @@ -1596,6 +1604,21 @@ class TestMessageConversion(TestBase, unittest.TestCase): for class_ in self.all_mailbox_types: self.assertRaises(TypeError, lambda: class_(False)) + def test_type_specific_attributes_removed_on_conversion(self): + reference = {class_: class_(_sample_message).__dict__ + for class_ in self.all_mailbox_types} + for class1 in self.all_mailbox_types: + for class2 in self.all_mailbox_types: + if class1 is class2: + continue + source = class1(_sample_message) + target = class2(source) + type_specific = [a for a in reference[class1] + if a not in reference[class2]] + for attr in type_specific: + self.assertNotIn(attr, target.__dict__, + "while converting {} to {}".format(class1, class2)) + def test_maildir_to_maildir(self): # Convert MaildirMessage to MaildirMessage msg_maildir = mailbox.MaildirMessage(_sample_message) @@ -19,6 +19,9 @@ Core and Builtins Library ------- +- Issue #12537: The mailbox module no longer depends on knowledge of internal + implementation details of the email package Message object. + - Issue #7978: socketserver now restarts the select() call when EINTR is returned. This avoids crashing the server loop when a signal is received. Patch by Jerzy Kozera. |