diff --git a/Lib/mailbox.py b/Lib/mailbox.py index 520463a..79f8344 100644 --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -31,6 +31,8 @@ __all__ = [ 'Mailbox', 'Maildir', 'mbox', 'MH', 'Babyl', 'MMDF', 'Message', 'MaildirMessage', 'mboxMessage', 'MHMessage', 'BabylMessage', 'MMDFMessage'] +linesep = os.linesep.encode('ascii') + class Mailbox: """A group of messages in a particular place.""" @@ -191,26 +193,26 @@ class Mailbox: # desired encoding and newline setting. """Dump message contents to target file.""" if isinstance(message, email.message.Message): - buffer = io.StringIO() - gen = email.generator.Generator(buffer, mangle_from_, 0) + buffer = io.BytesIO() + gen = email.generator.BytesGenerator(buffer, mangle_from_, 0) gen.flatten(message) buffer.seek(0) data = buffer.read() - ##data = data.replace('\n', os.linesep) + ##data = data.replace('\n', linesep) target.write(data) - elif isinstance(message, str): + elif isinstance(message, bytes): if mangle_from_: - message = message.replace('\nFrom ', '\n>From ') - ##message = message.replace('\n', os.linesep) + message = message.replace(b'\nFrom ', b'\n>From ') + ##message = message.replace(b'\n', linesep) target.write(message) elif hasattr(message, 'read'): while True: line = message.readline() if not line: break - if mangle_from_ and line.startswith('From '): - line = '>From ' + line[5:] - ##line = line.replace('\n', os.linesep) + if mangle_from_ and line.startswith(b'From '): + line = b'>From ' + line[5:] + ##line = line.replace(b'\n', linesep) target.write(line) else: raise TypeError('Invalid message type: %s' % type(message)) @@ -319,7 +321,7 @@ class Maildir(Mailbox): def get_message(self, key): """Return a Message representation or raise a KeyError.""" subpath = self._lookup(key) - f = open(os.path.join(self._path, subpath), 'r', newline='') + f = open(os.path.join(self._path, subpath), 'rb') try: if self._factory: msg = self._factory(f) @@ -336,7 +338,7 @@ class Maildir(Mailbox): def get_string(self, key): """Return a string representation or raise a KeyError.""" - f = open(os.path.join(self._path, self._lookup(key)), 'r', newline='') + f = open(os.path.join(self._path, self._lookup(key)), 'rb') try: return f.read() finally: @@ -344,7 +346,7 @@ class Maildir(Mailbox): def get_file(self, key): """Return a file-like representation or raise a KeyError.""" - f = open(os.path.join(self._path, self._lookup(key)), 'r', newline='') + f = open(os.path.join(self._path, self._lookup(key)), 'rb') return _ProxyFile(f) def iterkeys(self): @@ -534,15 +536,15 @@ class _singlefileMailbox(Mailbox): """Initialize a single-file mailbox.""" Mailbox.__init__(self, path, factory, create) try: - f = open(self._path, 'r+', newline='') + f = open(self._path, 'rb+') except IOError as e: if e.errno == errno.ENOENT: if create: - f = open(self._path, 'w+', newline='') + f = open(self._path, 'wb+') else: raise NoSuchMailboxError(self._path) elif e.errno == errno.EACCES: - f = open(self._path, 'r', newline='') + f = open(self._path, 'rb') else: raise self._file = f @@ -708,9 +710,9 @@ class _mboxMMDF(_singlefileMailbox): """Return a Message representation or raise a KeyError.""" start, stop = self._lookup(key) self._file.seek(start) - from_line = self._file.readline().replace(os.linesep, '') + from_line = self._file.readline().replace(linesep, b'') string = self._file.read(stop - self._file.tell()) - msg = self._message_factory(string.replace(os.linesep, '\n')) + msg = self._message_factory(string.replace(linesep, b'\n')) msg.set_from(from_line[5:]) return msg @@ -721,7 +723,7 @@ class _mboxMMDF(_singlefileMailbox): if not from_: self._file.readline() string = self._file.read(stop - self._file.tell()) - return string.replace(os.linesep, '\n') + return string.replace(linesep, b'\n') def get_file(self, key, from_=False): """Return a file-like representation or raise a KeyError.""" @@ -734,22 +736,23 @@ class _mboxMMDF(_singlefileMailbox): def _install_message(self, message): """Format a message and blindly write to self._file.""" from_line = None - if isinstance(message, str) and message.startswith('From '): - newline = message.find('\n') + if isinstance(message, bytes) and message.startswith(b'From '): + newline = message.find(b'\n') if newline != -1: from_line = message[:newline] message = message[newline + 1:] else: from_line = message - message = '' + message = b'' elif isinstance(message, _mboxMMDFMessage): - from_line = 'From ' + message.get_from() + author = message.get_from() + from_line = b'From ' + author elif isinstance(message, email.message.Message): from_line = message.get_unixfrom() # May be None. if from_line is None: - from_line = 'From MAILER-DAEMON %s' % time.asctime(time.gmtime()) + from_line = b'From MAILER-DAEMON ' + time.asctime(time.gmtime()).encode() start = self._file.tell() - self._file.write(from_line + os.linesep) + self._file.write(from_line + linesep) self._dump_message(message, self._file, self._mangle_from_) stop = self._file.tell() return (start, stop) @@ -768,7 +771,7 @@ class mbox(_mboxMMDF): def _pre_message_hook(self, f): """Called before writing each message to file f.""" if f.tell() != 0: - f.write(os.linesep) + f.write(linesep) def _generate_toc(self): """Generate key-to-(start, stop) table of contents.""" @@ -777,9 +780,9 @@ class mbox(_mboxMMDF): while True: line_pos = self._file.tell() line = self._file.readline() - if line.startswith('From '): + if line.startswith(b'From '): if len(stops) < len(starts): - stops.append(line_pos - len(os.linesep)) + stops.append(line_pos - len(linesep)) starts.append(line_pos) elif not line: stops.append(line_pos) @@ -799,11 +802,11 @@ class MMDF(_mboxMMDF): def _pre_message_hook(self, f): """Called before writing each message to file f.""" - f.write('\001\001\001\001' + os.linesep) + f.write(b'\001\001\001\001' + linesep) def _post_message_hook(self, f): """Called after writing each message to file f.""" - f.write(os.linesep + '\001\001\001\001' + os.linesep) + f.write(linesep + b'\001\001\001\001' + linesep) def _generate_toc(self): """Generate key-to-(start, stop) table of contents.""" @@ -814,14 +817,14 @@ class MMDF(_mboxMMDF): line_pos = next_pos line = self._file.readline() next_pos = self._file.tell() - if line.startswith('\001\001\001\001' + os.linesep): + if line.startswith(b'\001\001\001\001' + linesep): starts.append(next_pos) while True: line_pos = next_pos line = self._file.readline() next_pos = self._file.tell() - if line == '\001\001\001\001' + os.linesep: - stops.append(line_pos - len(os.linesep)) + if line == b'\001\001\001\001' + linesep: + stops.append(line_pos - len(linesep)) break elif not line: stops.append(line_pos) @@ -890,7 +893,7 @@ class MH(Mailbox): """Replace the keyed message; raise KeyError if it doesn't exist.""" path = os.path.join(self._path, str(key)) try: - f = open(path, 'r+', newline='') + f = open(path, 'rb+') except IOError as e: if e.errno == errno.ENOENT: raise KeyError('No message with key: %s' % key) @@ -914,9 +917,9 @@ class MH(Mailbox): """Return a Message representation or raise a KeyError.""" try: if self._locked: - f = open(os.path.join(self._path, str(key)), 'r+', newline='') + f = open(os.path.join(self._path, str(key)), 'rb+') else: - f = open(os.path.join(self._path, str(key)), 'r', newline='') + f = open(os.path.join(self._path, str(key)), 'rb') except IOError as e: if e.errno == errno.ENOENT: raise KeyError('No message with key: %s' % key) @@ -941,9 +944,9 @@ class MH(Mailbox): """Return a string representation or raise a KeyError.""" try: if self._locked: - f = open(os.path.join(self._path, str(key)), 'r+', newline='') + f = open(os.path.join(self._path, str(key)), 'rb+') else: - f = open(os.path.join(self._path, str(key)), 'r', newline='') + f = open(os.path.join(self._path, str(key)), 'rb') except IOError as e: if e.errno == errno.ENOENT: raise KeyError('No message with key: %s' % key) @@ -963,7 +966,7 @@ class MH(Mailbox): def get_file(self, key): """Return a file-like representation or raise a KeyError.""" try: - f = open(os.path.join(self._path, str(key)), 'r', newline='') + f = open(os.path.join(self._path, str(key)), 'rb') except IOError as e: if e.errno == errno.ENOENT: raise KeyError('No message with key: %s' % key) @@ -1041,7 +1044,7 @@ class MH(Mailbox): def get_sequences(self): """Return a name-to-key-list dictionary to define each sequence.""" results = {} - f = open(os.path.join(self._path, '.mh_sequences'), 'r', newline='') + f = open(os.path.join(self._path, '.mh_sequences'), 'r') try: all_keys = set(self.keys()) for line in f: @@ -1067,13 +1070,15 @@ class MH(Mailbox): def set_sequences(self, sequences): """Set sequences using the given name-to-key-list dictionary.""" - f = open(os.path.join(self._path, '.mh_sequences'), 'r+', newline='') + f = open(os.path.join(self._path, '.mh_sequences'), 'r+') try: os.close(os.open(f.name, os.O_WRONLY | os.O_TRUNC)) for name, keys in sequences.items(): if len(keys) == 0: continue - f.write('%s:' % name) + if isinstance(name, bytes): + name = name.decode() + f.write(name + ':') prev = None completing = False for key in sorted(set(keys)): @@ -1168,21 +1173,21 @@ class Babyl(_singlefileMailbox): """Return a Message representation or raise a KeyError.""" start, stop = self._lookup(key) self._file.seek(start) - self._file.readline() # Skip '1,' line specifying labels. - original_headers = io.StringIO() + self._file.readline() # Skip b'1,' line specifying labels. + original_headers = io.BytesIO() while True: line = self._file.readline() - if line == '*** EOOH ***' + os.linesep or not line: + if line == b'*** EOOH ***' + linesep or not line: break - original_headers.write(line.replace(os.linesep, '\n')) - visible_headers = io.StringIO() + original_headers.write(line.replace(linesep, b'\n')) + visible_headers = io.BytesIO() while True: line = self._file.readline() - if line == os.linesep or not line: + if line == linesep or not line: break - visible_headers.write(line.replace(os.linesep, '\n')) - body = self._file.read(stop - self._file.tell()).replace(os.linesep, - '\n') + visible_headers.write(line.replace(linesep, b'\n')) + body = self._file.read(stop - self._file.tell()) + body = body.replace(linesep, b'\n') msg = BabylMessage(original_headers.getvalue() + body) msg.set_visible(visible_headers.getvalue()) if key in self._labels: @@ -1193,25 +1198,25 @@ class Babyl(_singlefileMailbox): """Return a string representation or raise a KeyError.""" start, stop = self._lookup(key) self._file.seek(start) - self._file.readline() # Skip '1,' line specifying labels. - original_headers = io.StringIO() + self._file.readline() # Skip b'1,' line specifying labels. + original_headers = io.BytesIO() while True: line = self._file.readline() - if line == '*** EOOH ***' + os.linesep or not line: + if line == b'*** EOOH ***' + linesep or not line: break - original_headers.write(line.replace(os.linesep, '\n')) + original_headers.write(line.replace(linesep, b'\n')) while True: line = self._file.readline() - if line == os.linesep or not line: + if line == linesep or not line: break - return original_headers.getvalue() + \ - self._file.read(stop - self._file.tell()).replace(os.linesep, - '\n') + headers = original_headers.getvalue() + data = self._file.read(stop - self._file.tell()) + data = data.replace(linesep, b'\n') + return headers + data def get_file(self, key): """Return a file-like representation or raise a KeyError.""" - return io.StringIO(self.get_string(key).replace('\n', - os.linesep)) + return io.BytesIO(self.get_string(key).replace(b'\n', linesep)) def get_labels(self): """Return a list of user-defined labels in the mailbox.""" @@ -1232,19 +1237,19 @@ class Babyl(_singlefileMailbox): line_pos = next_pos line = self._file.readline() next_pos = self._file.tell() - if line == '\037\014' + os.linesep: + if line == b'\037\014' + linesep: if len(stops) < len(starts): - stops.append(line_pos - len(os.linesep)) + stops.append(line_pos - len(linesep)) starts.append(next_pos) labels = [label.strip() for label - in self._file.readline()[1:].split(',') + in self._file.readline()[1:].split(b',') if label.strip()] label_lists.append(labels) - elif line == '\037' or line == '\037' + os.linesep: + elif line == b'\037' or line == b'\037' + linesep: if len(stops) < len(starts): - stops.append(line_pos - len(os.linesep)) + stops.append(line_pos - len(linesep)) elif not line: - stops.append(line_pos - len(os.linesep)) + stops.append(line_pos - len(linesep)) break self._toc = dict(enumerate(zip(starts, stops))) self._labels = dict(enumerate(label_lists)) @@ -1254,17 +1259,21 @@ class Babyl(_singlefileMailbox): def _pre_mailbox_hook(self, f): """Called before writing the mailbox to file f.""" - f.write('BABYL OPTIONS:%sVersion: 5%sLabels:%s%s\037' % - (os.linesep, os.linesep, ','.join(self.get_labels()), - os.linesep)) + babyl = b'BABYL OPTIONS:' + linesep + babyl += b'Version: 5' + linesep + labels = self.get_labels() + labels = (label.encode() for label in labels) + babyl += b'Labels:' + b','.join(labels) + linesep + babyl += b'\037' + f.write(babyl) def _pre_message_hook(self, f): """Called before writing each message to file f.""" - f.write('\014' + os.linesep) + f.write(b'\014' + linesep) def _post_message_hook(self, f): """Called after writing each message to file f.""" - f.write(os.linesep + '\037') + f.write(linesep + b'\037') def _install_message(self, message): """Write message contents and return (start, stop).""" @@ -1277,68 +1286,70 @@ class Babyl(_singlefileMailbox): special_labels.append(label) else: labels.append(label) - self._file.write('1') + self._file.write(b'1') for label in special_labels: - self._file.write(', ' + label) - self._file.write(',,') + label = label.encode() + self._file.write(b', ' + label) + self._file.write(b',,') for label in labels: - self._file.write(' ' + label + ',') - self._file.write(os.linesep) + label = label.encode() + self._file.write(b' ' + label + b',') + self._file.write(linesep) else: - self._file.write('1,,' + os.linesep) + self._file.write(b'1,,' + linesep) if isinstance(message, email.message.Message): - orig_buffer = io.StringIO() - orig_generator = email.generator.Generator(orig_buffer, False, 0) + orig_buffer = io.BytesIO() + orig_generator = email.generator.BytesGenerator(orig_buffer, False, 0) orig_generator.flatten(message) orig_buffer.seek(0) while True: line = orig_buffer.readline() - self._file.write(line.replace('\n', os.linesep)) + self._file.write(line.replace(b'\n', linesep)) if line == '\n' or not line: break - self._file.write('*** EOOH ***' + os.linesep) + self._file.write(b'*** EOOH ***' + linesep) if isinstance(message, BabylMessage): - vis_buffer = io.StringIO() - vis_generator = email.generator.Generator(vis_buffer, False, 0) + vis_buffer = io.BytesIO() + vis_generator = email.generator.BytesGenerator(vis_buffer, False, 0) vis_generator.flatten(message.get_visible()) while True: line = vis_buffer.readline() - self._file.write(line.replace('\n', os.linesep)) - if line == '\n' or not line: + self._file.write(line.replace(b'\n', linesep)) + if line == b'\n' or not line: break else: orig_buffer.seek(0) while True: line = orig_buffer.readline() - self._file.write(line.replace('\n', os.linesep)) - if line == '\n' or not line: + self._file.write(line.replace(b'\n', linesep)) + if line == b'\n' or not line: break while True: buffer = orig_buffer.read(4096) # Buffer size is arbitrary. if not buffer: break - self._file.write(buffer.replace('\n', os.linesep)) - elif isinstance(message, str): - body_start = message.find('\n\n') + 2 + self._file.write(buffer.replace(b'\n', linesep)) + elif isinstance(message, bytes): + body_start = message.find(b'\n\n') + 2 if body_start - 2 != -1: - self._file.write(message[:body_start].replace('\n', - os.linesep)) - self._file.write('*** EOOH ***' + os.linesep) - self._file.write(message[:body_start].replace('\n', - os.linesep)) - self._file.write(message[body_start:].replace('\n', - os.linesep)) + self._file.write(message[:body_start].replace(b'\n', + linesep)) + self._file.write(b'*** EOOH ***' + linesep) + self._file.write(message[:body_start].replace(b'\n', + linesep)) + self._file.write(message[body_start:].replace(b'\n', + linesep)) else: - self._file.write('*** EOOH ***' + os.linesep + os.linesep) - self._file.write(message.replace('\n', os.linesep)) + self._file.write(b'*** EOOH ***' + linesep + linesep) + self._file.write(message.replace(b'\n', linesep)) elif hasattr(message, 'readline'): original_pos = message.tell() first_pass = True while True: line = message.readline() - self._file.write(line.replace('\n', os.linesep)) - if line == '\n' or not line: - self._file.write('*** EOOH ***' + os.linesep) + self._file.write(line.replace(b'\n', linesep)) + if line == b'\n' or not line: + self._file.write(b'*** EOOH ***' + linesep) if first_pass: first_pass = False message.seek(original_pos) @@ -1348,7 +1359,7 @@ class Babyl(_singlefileMailbox): buffer = message.read(4096) # Buffer size is arbitrary. if not buffer: break - self._file.write(buffer.replace('\n', os.linesep)) + self._file.write(buffer.replace(b'\n', linesep)) else: raise TypeError('Invalid message type: %s' % type(message)) stop = self._file.tell() @@ -1364,10 +1375,10 @@ class Message(email.message.Message): self._become_message(copy.deepcopy(message)) if isinstance(message, Message): message._explain_to(self) - elif isinstance(message, str): - self._become_message(email.message_from_string(message)) + elif isinstance(message, bytes): + self._become_message(email.message_from_bytes(message)) elif hasattr(message, "read"): - self._become_message(email.message_from_file(message)) + self._become_message(email.message_from_binary_file(message)) elif message is None: email.message.Message.__init__(self) else: @@ -1468,7 +1479,7 @@ class MaildirMessage(Message): message.add_flag('F') if 'R' in flags: message.add_flag('A') - message.set_from('MAILER-DAEMON', time.gmtime(self.get_date())) + message.set_from(b'MAILER-DAEMON', time.gmtime(self.get_date())) elif isinstance(message, MHMessage): flags = set(self.get_flags()) if 'S' not in flags: @@ -1499,10 +1510,10 @@ class _mboxMMDFMessage(Message): def __init__(self, message=None): """Initialize an mboxMMDFMessage instance.""" - self.set_from('MAILER-DAEMON', True) + self.set_from(b'MAILER-DAEMON', True) if isinstance(message, email.message.Message): unixfrom = message.get_unixfrom() - if unixfrom is not None and unixfrom.startswith('From '): + if unixfrom is not None and unixfrom.startswith(b'From '): self.set_from(unixfrom[5:]) Message.__init__(self, message) @@ -1512,10 +1523,11 @@ class _mboxMMDFMessage(Message): def set_from(self, from_, time_=None): """Set "From " line, formatting and appending time_ if specified.""" + assert isinstance(from_, bytes) if time_ is not None: if time_ is True: time_ = time.gmtime() - from_ += ' ' + time.asctime(time_) + from_ += b' ' + time.asctime(time_).encode('utf-8') self._from = from_ def get_flags(self): @@ -1569,11 +1581,12 @@ class _mboxMMDFMessage(Message): message.add_flag('T') del message['status'] del message['x-status'] - maybe_date = ' '.join(self.get_from().split()[-5:]) + maybe_date = b' '.join(self.get_from().split()[-5:]) try: + maybe_date = maybe_date.decode('utf-8') message.set_date(calendar.timegm(time.strptime(maybe_date, '%a %b %d %H:%M:%S %Y'))) - except (ValueError, OverflowError): + except (ValueError, OverflowError, UnicodeDecodeError): pass elif isinstance(message, _mboxMMDFMessage): message.set_flags(self.get_flags()) @@ -1631,7 +1644,7 @@ class MHMessage(Message): if not sequence in self._sequences: self._sequences.append(sequence) else: - raise TypeError('sequence must be a string: %s' % type(sequence)) + raise TypeError('sequence type must be str: %s' % type(sequence)) def remove_sequence(self, sequence): """Remove sequence from the list of sequences including the message.""" @@ -1791,6 +1804,10 @@ class _ProxyFile: """Read bytes.""" return self._read(size, self._file.read) + def read1(self, size=None): + """Read bytes.""" + return self._read(size, self._file.read1) + def readline(self, size=None): """Read a line.""" return self._read(size, self._file.readline) @@ -1847,6 +1864,22 @@ class _ProxyFile: def __exit__(self, *exc): self.close() + def readable(self): + return self._file.readable() + + def writable(self): + return self._file.writable() + + def seekable(self): + return self._file.seekable() + + def flush(self): + return self._file.flush() + + @property + def closed(self): + return self._file.closed + class _PartialFile(_ProxyFile): """A read-only wrapper of part of a file.""" @@ -1875,7 +1908,7 @@ class _PartialFile(_ProxyFile): """Read size bytes using read_method, honoring start and stop.""" remaining = self._stop - self._pos if remaining <= 0: - return '' + return b'' if size is None or size < 0 or size > remaining: size = remaining return _ProxyFile._read(self, size, read_method) @@ -1942,7 +1975,7 @@ def _create_carefully(path): """Create a file if it doesn't exist and open for reading and writing.""" fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR, 0o666) try: - return open(path, 'r+', newline='') + return open(path, 'rb+') finally: os.close(fd) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py index de6d4bd..fd6bcf0 100644 --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -16,7 +16,6 @@ try: except ImportError: pass - class TestBase(unittest.TestCase): def _check_sample(self, msg): @@ -49,7 +48,10 @@ class TestBase(unittest.TestCase): class TestMailbox(TestBase): _factory = None # Overridden by subclasses to reuse tests - _template = 'From: foo\n\n%s' + + @staticmethod + def _template(arg): + return ('From: foo\n\n%s' % arg).encode('ascii') def setUp(self): self._path = support.TESTFN @@ -63,17 +65,17 @@ class TestMailbox(TestBase): def test_add(self): # Add copies of a sample message keys = [] - keys.append(self._box.add(self._template % 0)) + keys.append(self._box.add(self._template(0))) self.assertEqual(len(self._box), 1) keys.append(self._box.add(mailbox.Message(_sample_message))) self.assertEqual(len(self._box), 2) - keys.append(self._box.add(email.message_from_string(_sample_message))) + keys.append(self._box.add(email.message_from_bytes(_sample_message))) self.assertEqual(len(self._box), 3) - keys.append(self._box.add(io.StringIO(_sample_message))) + keys.append(self._box.add(io.BytesIO(_sample_message))) self.assertEqual(len(self._box), 4) keys.append(self._box.add(_sample_message)) self.assertEqual(len(self._box), 5) - self.assertEqual(self._box.get_string(keys[0]), self._template % 0) + self.assertEqual(self._box.get_string(keys[0]), self._template(0)) for i in (1, 2, 3, 4): self._check_sample(self._box[keys[i]]) @@ -87,21 +89,21 @@ class TestMailbox(TestBase): def _test_remove_or_delitem(self, method): # (Used by test_remove() and test_delitem().) - key0 = self._box.add(self._template % 0) - key1 = self._box.add(self._template % 1) + key0 = self._box.add(self._template(0)) + key1 = self._box.add(self._template(1)) self.assertEqual(len(self._box), 2) method(key0) self.assertEqual(len(self._box), 1) self.assertRaises(KeyError, lambda: self._box[key0]) self.assertRaises(KeyError, lambda: method(key0)) - self.assertEqual(self._box.get_string(key1), self._template % 1) - key2 = self._box.add(self._template % 2) + self.assertEqual(self._box.get_string(key1), self._template(1)) + key2 = self._box.add(self._template(2)) self.assertEqual(len(self._box), 2) method(key2) self.assertEqual(len(self._box), 1) self.assertRaises(KeyError, lambda: self._box[key2]) self.assertRaises(KeyError, lambda: method(key2)) - self.assertEqual(self._box.get_string(key1), self._template % 1) + self.assertEqual(self._box.get_string(key1), self._template(1)) method(key1) self.assertEqual(len(self._box), 0) self.assertRaises(KeyError, lambda: self._box[key1]) @@ -109,8 +111,8 @@ class TestMailbox(TestBase): def test_discard(self, repetitions=10): # Discard messages - key0 = self._box.add(self._template % 0) - key1 = self._box.add(self._template % 1) + key0 = self._box.add(self._template(0)) + key1 = self._box.add(self._template(1)) self.assertEqual(len(self._box), 2) self._box.discard(key0) self.assertEqual(len(self._box), 1) @@ -121,7 +123,7 @@ class TestMailbox(TestBase): def test_get(self): # Retrieve messages using get() - key0 = self._box.add(self._template % 0) + key0 = self._box.add(self._template(0)) msg = self._box.get(key0) self.assertEqual(msg['from'], 'foo') self.assertEqual(msg.get_payload(), '0') @@ -129,14 +131,14 @@ class TestMailbox(TestBase): self.assertIs(self._box.get('foo', False), False) self._box.close() self._box = self._factory(self._path) - key1 = self._box.add(self._template % 1) + key1 = self._box.add(self._template(1)) msg = self._box.get(key1) self.assertEqual(msg['from'], 'foo') self.assertEqual(msg.get_payload(), '1') def test_getitem(self): # Retrieve message using __getitem__() - key0 = self._box.add(self._template % 0) + key0 = self._box.add(self._template(0)) msg = self._box[key0] self.assertEqual(msg['from'], 'foo') self.assertEqual(msg.get_payload(), '0') @@ -146,7 +148,7 @@ class TestMailbox(TestBase): def test_get_message(self): # Get Message representations of messages - key0 = self._box.add(self._template % 0) + key0 = self._box.add(self._template(0)) key1 = self._box.add(_sample_message) msg0 = self._box.get_message(key0) self.assertIsInstance(msg0, mailbox.Message) @@ -156,22 +158,23 @@ class TestMailbox(TestBase): def test_get_string(self): # Get string representations of messages - key0 = self._box.add(self._template % 0) + key0 = self._box.add(self._template(0)) key1 = self._box.add(_sample_message) - self.assertEqual(self._box.get_string(key0), self._template % 0) + self.assertEqual(self._box.get_string(key0), self._template(0)) self.assertEqual(self._box.get_string(key1), _sample_message) def test_get_file(self): # Get file representations of messages - key0 = self._box.add(self._template % 0) + linesep = os.linesep.encode() + key0 = self._box.add(self._template(0)) key1 = self._box.add(_sample_message) with self._box.get_file(key0) as file: data0 = file.read() with self._box.get_file(key1) as file: data1 = file.read() - self.assertEqual(data0.replace(os.linesep, '\n'), - self._template % 0) - self.assertEqual(data1.replace(os.linesep, '\n'), + self.assertEqual(data0.replace(linesep, b'\n'), + self._template(0)) + self.assertEqual(data1.replace(linesep, b'\n'), _sample_message) def test_iterkeys(self): @@ -210,8 +213,8 @@ class TestMailbox(TestBase): self.fail("Not empty") keys, values = [], [] for i in range(repetitions): - keys.append(self._box.add(self._template % i)) - values.append(self._template % i) + keys.append(self._box.add(self._template(i))) + values.append(self._template(i)) if do_keys and not do_values: returned_keys = list(method()) elif do_values and not do_keys: @@ -235,10 +238,10 @@ class TestMailbox(TestBase): def test_contains(self): # Check existence of keys using __contains__() self.assertNotIn('foo', self._box) - key0 = self._box.add(self._template % 0) + key0 = self._box.add(self._template(0)) self.assertIn(key0, self._box) self.assertNotIn('foo', self._box) - key1 = self._box.add(self._template % 1) + key1 = self._box.add(self._template(1)) self.assertIn(key1, self._box) self.assertIn(key0, self._box) self.assertNotIn('foo', self._box) @@ -256,7 +259,7 @@ class TestMailbox(TestBase): keys = [] for i in range(repetitions): self.assertEqual(len(self._box), i) - keys.append(self._box.add(self._template % i)) + keys.append(self._box.add(self._template(i))) self.assertEqual(len(self._box), i + 1) for i in range(repetitions): self.assertEqual(len(self._box), repetitions - i) @@ -265,25 +268,25 @@ class TestMailbox(TestBase): def test_set_item(self): # Modify messages using __setitem__() - key0 = self._box.add(self._template % 'original 0') + key0 = self._box.add(self._template('original 0')) self.assertEqual(self._box.get_string(key0), - self._template % 'original 0') - key1 = self._box.add(self._template % 'original 1') + self._template('original 0')) + key1 = self._box.add(self._template('original 1')) self.assertEqual(self._box.get_string(key1), - self._template % 'original 1') - self._box[key0] = self._template % 'changed 0' + self._template('original 1')) + self._box[key0] = self._template('changed 0') self.assertEqual(self._box.get_string(key0), - self._template % 'changed 0') - self._box[key1] = self._template % 'changed 1' + self._template('changed 0')) + self._box[key1] = self._template('changed 1') self.assertEqual(self._box.get_string(key1), - self._template % 'changed 1') + self._template('changed 1')) self._box[key0] = _sample_message self._check_sample(self._box[key0]) self._box[key1] = self._box[key0] self._check_sample(self._box[key1]) - self._box[key0] = self._template % 'original 0' + self._box[key0] = self._template('original 0') self.assertEqual(self._box.get_string(key0), - self._template % 'original 0') + self._template('original 0')) self._check_sample(self._box[key1]) self.assertRaises(KeyError, lambda: self._box.__setitem__('foo', 'bar')) @@ -294,9 +297,9 @@ class TestMailbox(TestBase): # Remove all messages using clear() keys = [] for i in range(iterations): - self._box.add(self._template % i) + self._box.add(self._template(i)) for i, key in enumerate(keys): - self.assertEqual(self._box.get_string(key), self._template % i) + self.assertEqual(self._box.get_string(key), self._template(i)) self._box.clear() self.assertEqual(len(self._box), 0) for i, key in enumerate(keys): @@ -304,14 +307,14 @@ class TestMailbox(TestBase): def test_pop(self): # Get and remove a message using pop() - key0 = self._box.add(self._template % 0) + key0 = self._box.add(self._template(0)) self.assertIn(key0, self._box) - key1 = self._box.add(self._template % 1) + key1 = self._box.add(self._template(1)) self.assertIn(key1, self._box) self.assertEqual(self._box.pop(key0).get_payload(), '0') self.assertNotIn(key0, self._box) self.assertIn(key1, self._box) - key2 = self._box.add(self._template % 2) + key2 = self._box.add(self._template(2)) self.assertIn(key2, self._box) self.assertEqual(self._box.pop(key2).get_payload(), '2') self.assertNotIn(key2, self._box) @@ -324,7 +327,7 @@ class TestMailbox(TestBase): # Get and remove an arbitrary (key, message) using popitem() keys = [] for i in range(10): - keys.append(self._box.add(self._template % i)) + keys.append(self._box.add(self._template(i))) seen = [] for i in range(10): key, msg = self._box.popitem() @@ -338,37 +341,37 @@ class TestMailbox(TestBase): def test_update(self): # Modify multiple messages using update() - key0 = self._box.add(self._template % 'original 0') - key1 = self._box.add(self._template % 'original 1') - key2 = self._box.add(self._template % 'original 2') - self._box.update({key0: self._template % 'changed 0', + key0 = self._box.add(self._template('original 0')) + key1 = self._box.add(self._template('original 1')) + key2 = self._box.add(self._template('original 2')) + self._box.update({key0: self._template('changed 0'), key2: _sample_message}) self.assertEqual(len(self._box), 3) self.assertEqual(self._box.get_string(key0), - self._template % 'changed 0') + self._template('changed 0')) self.assertEqual(self._box.get_string(key1), - self._template % 'original 1') + self._template('original 1')) self._check_sample(self._box[key2]) - self._box.update([(key2, self._template % 'changed 2'), - (key1, self._template % 'changed 1'), - (key0, self._template % 'original 0')]) + self._box.update([(key2, self._template('changed 2')), + (key1, self._template('changed 1')), + (key0, self._template('original 0'))]) self.assertEqual(len(self._box), 3) self.assertEqual(self._box.get_string(key0), - self._template % 'original 0') + self._template('original 0')) self.assertEqual(self._box.get_string(key1), - self._template % 'changed 1') + self._template('changed 1')) self.assertEqual(self._box.get_string(key2), - self._template % 'changed 2') + self._template('changed 2')) self.assertRaises(KeyError, lambda: self._box.update({'foo': 'bar', - key0: self._template % "changed 0"})) + key0: self._template("changed 0")})) self.assertEqual(len(self._box), 3) self.assertEqual(self._box.get_string(key0), - self._template % "changed 0") + self._template("changed 0")) self.assertEqual(self._box.get_string(key1), - self._template % "changed 1") + self._template("changed 1")) self.assertEqual(self._box.get_string(key2), - self._template % "changed 2") + self._template("changed 2")) def test_flush(self): # Write changes to disk @@ -387,7 +390,7 @@ class TestMailbox(TestBase): self._test_flush_or_close(self._box.close, False) def _test_flush_or_close(self, method, should_call_close): - contents = [self._template % i for i in range(3)] + contents = [self._template(i) for i in range(3)] self._box.add(contents[0]) self._box.add(contents[1]) self._box.add(contents[2]) @@ -404,12 +407,12 @@ class TestMailbox(TestBase): def test_dump_message(self): # Write message representations to disk - for input in (email.message_from_string(_sample_message), - _sample_message, io.StringIO(_sample_message)): - output = io.StringIO() + for input in (email.message_from_bytes(_sample_message), + _sample_message, io.BytesIO(_sample_message)): + output = io.BytesIO() self._box._dump_message(input, output) self.assertEqual(output.getvalue(), _sample_message) - output = io.StringIO() + output = io.BytesIO() self.assertRaises(TypeError, lambda: self._box._dump_message(None, output)) @@ -464,7 +467,7 @@ class TestMaildir(TestMailbox): def test_add_MM(self): # Add a MaildirMessage instance - msg = mailbox.MaildirMessage(self._template % 0) + msg = mailbox.MaildirMessage(self._template(0)) msg.set_subdir('cur') msg.set_info('foo') key = self._box.add(msg) @@ -473,7 +476,7 @@ class TestMaildir(TestMailbox): def test_get_MM(self): # Get a MaildirMessage instance - msg = mailbox.MaildirMessage(self._template % 0) + msg = mailbox.MaildirMessage(self._template(0)) msg.set_subdir('cur') msg.set_flags('RF') key = self._box.add(msg) @@ -484,22 +487,22 @@ class TestMaildir(TestMailbox): def test_set_MM(self): # Set with a MaildirMessage instance - msg0 = mailbox.MaildirMessage(self._template % 0) + msg0 = mailbox.MaildirMessage(self._template(0)) msg0.set_flags('TP') key = self._box.add(msg0) msg_returned = self._box.get_message(key) self.assertEqual(msg_returned.get_subdir(), 'new') self.assertEqual(msg_returned.get_flags(), 'PT') - msg1 = mailbox.MaildirMessage(self._template % 1) + msg1 = mailbox.MaildirMessage(self._template(1)) self._box[key] = msg1 msg_returned = self._box.get_message(key) self.assertEqual(msg_returned.get_subdir(), 'new') self.assertEqual(msg_returned.get_flags(), '') self.assertEqual(msg_returned.get_payload(), '1') - msg2 = mailbox.MaildirMessage(self._template % 2) + msg2 = mailbox.MaildirMessage(self._template(2)) msg2.set_info('2,S') self._box[key] = msg2 - self._box[key] = self._template % 3 + self._box[key] = self._template(3) msg_returned = self._box.get_message(key) self.assertEqual(msg_returned.get_subdir(), 'new') self.assertEqual(msg_returned.get_flags(), 'S') @@ -507,7 +510,7 @@ class TestMaildir(TestMailbox): def test_consistent_factory(self): # Add a message. - msg = mailbox.MaildirMessage(self._template % 0) + msg = mailbox.MaildirMessage(self._template(0)) msg.set_subdir('cur') msg.set_flags('RF') key = self._box.add(msg) @@ -559,11 +562,11 @@ class TestMaildir(TestMailbox): # Open folders self._box.add_folder('foo.bar') folder0 = self._box.get_folder('foo.bar') - folder0.add(self._template % 'bar') + folder0.add(self._template('bar')) self.assertTrue(os.path.isdir(os.path.join(self._path, '.foo.bar'))) folder1 = self._box.get_folder('foo.bar') self.assertEqual(folder1.get_string(folder1.keys()[0]), - self._template % 'bar') + self._template('bar')) def test_add_and_remove_folders(self): # Delete folders @@ -588,10 +591,10 @@ class TestMaildir(TestMailbox): # Remove old files from 'tmp' foo_path = os.path.join(self._path, 'tmp', 'foo') bar_path = os.path.join(self._path, 'tmp', 'bar') - with open(foo_path, 'w') as f: - f.write("@") - with open(bar_path, 'w') as f: - f.write("@") + with open(foo_path, 'wb') as f: + f.write(b"@") + with open(bar_path, 'wb') as f: + f.write(b"@") self._box.clean() self.assertTrue(os.path.exists(foo_path)) self.assertTrue(os.path.exists(bar_path)) @@ -652,13 +655,13 @@ class TestMaildir(TestMailbox): def test_refresh(self): # Update the table of contents self.assertEqual(self._box._toc, {}) - key0 = self._box.add(self._template % 0) - key1 = self._box.add(self._template % 1) + key0 = self._box.add(self._template(0)) + key1 = self._box.add(self._template(1)) self.assertEqual(self._box._toc, {}) self._box._refresh() self.assertEqual(self._box._toc, {key0: os.path.join('new', key0), key1: os.path.join('new', key1)}) - key2 = self._box.add(self._template % 2) + key2 = self._box.add(self._template(2)) self.assertEqual(self._box._toc, {key0: os.path.join('new', key0), key1: os.path.join('new', key1)}) self._box._refresh() @@ -669,7 +672,7 @@ class TestMaildir(TestMailbox): def test_lookup(self): # Look up message subpaths in the TOC self.assertRaises(KeyError, lambda: self._box._lookup('foo')) - key0 = self._box.add(self._template % 0) + key0 = self._box.add(self._template(0)) self.assertEqual(self._box._lookup(key0), os.path.join('new', key0)) os.remove(os.path.join(self._path, 'new', key0)) self.assertEqual(self._box._toc, {key0: os.path.join('new', key0)}) @@ -713,7 +716,7 @@ class TestMaildir(TestMailbox): # Verify that message files are created without execute permissions if not hasattr(os, "stat") or not hasattr(os, "umask"): return - msg = mailbox.MaildirMessage(self._template % 0) + msg = mailbox.MaildirMessage(self._template(0)) orig_umask = os.umask(0) try: key = self._box.add(msg) @@ -766,7 +769,7 @@ class TestMaildir(TestMailbox): # Now, write something into cur and remove it. This changes # the mtime and should cause a re-read. filename = os.path.join(self._path, 'cur', 'stray-file') - f = open(filename, 'w') + f = open(filename, 'wb') f.close() os.unlink(filename) self._box._refresh() @@ -783,19 +786,19 @@ class _TestMboxMMDF(TestMailbox): def test_add_from_string(self): # Add a string starting with 'From ' to the mailbox - key = self._box.add('From foo@bar blah\nFrom: foo\n\n0') - self.assertEqual(self._box[key].get_from(), 'foo@bar blah') + key = self._box.add(b'From foo@bar blah\nFrom: foo\n\n0') + self.assertEqual(self._box[key].get_from(), b'foo@bar blah') self.assertEqual(self._box[key].get_payload(), '0') def test_add_mbox_or_mmdf_message(self): # Add an mboxMessage or MMDFMessage for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): - msg = class_('From foo@bar blah\nFrom: foo\n\n0') + msg = class_(b'From foo@bar blah\nFrom: foo\n\n0') key = self._box.add(msg) def test_open_close_open(self): # Open and inspect previously-created mailbox - values = [self._template % i for i in range(3)] + values = [self._template(i) for i in range(3)] for value in values: self._box.add(value) self._box.close() @@ -811,13 +814,13 @@ class _TestMboxMMDF(TestMailbox): # Verifying that closing a mailbox doesn't change added items self._box.add(_sample_message) for i in range(3): - self._box.add(self._template % i) + self._box.add(self._template(i)) self._box.add(_sample_message) self._box._file.flush() self._box._file.seek(0) contents = self._box._file.read() self._box.close() - with open(self._path, 'r', newline='') as f: + with open(self._path, 'rb') as f: self.assertEqual(contents, f.read()) self._box = self._factory(self._path) @@ -852,7 +855,7 @@ class _TestMboxMMDF(TestMailbox): def test_relock(self): # Test case for bug #1575506: the mailbox class was locking the # wrong file object in its flush() method. - msg = "Subject: sub\n\nbody\n" + msg = b"Subject: sub\n\nbody\n" key1 = self._box.add(msg) self._box.flush() self._box.close() @@ -879,7 +882,7 @@ class TestMbox(_TestMboxMMDF): self._box.close() os.unlink(self._path) self._box = mailbox.mbox(self._path, create=True) - self._box.add('') + self._box.add(b'') self._box.close() finally: os.umask(old_umask) @@ -914,11 +917,11 @@ class TestMH(TestMailbox): new_folder = self._box.add_folder('foo.bar') folder0 = self._box.get_folder('foo.bar') - folder0.add(self._template % 'bar') + folder0.add(self._template('bar')) self.assertTrue(os.path.isdir(os.path.join(self._path, 'foo.bar'))) folder1 = self._box.get_folder('foo.bar') self.assertEqual(folder1.get_string(folder1.keys()[0]), - self._template % 'bar') + self._template('bar')) # Test for bug #1569790: verify that folders returned by .get_folder() # use the same factory function. @@ -947,11 +950,11 @@ class TestMH(TestMailbox): def test_sequences(self): # Get and set sequences self.assertEqual(self._box.get_sequences(), {}) - msg0 = mailbox.MHMessage(self._template % 0) + msg0 = mailbox.MHMessage(self._template(0)) msg0.add_sequence('foo') key0 = self._box.add(msg0) self.assertEqual(self._box.get_sequences(), {'foo':[key0]}) - msg1 = mailbox.MHMessage(self._template % 1) + msg1 = mailbox.MHMessage(self._template(1)) msg1.set_sequences(['bar', 'replied', 'foo']) key1 = self._box.add(msg1) self.assertEqual(self._box.get_sequences(), @@ -965,13 +968,13 @@ class TestMH(TestMailbox): self.assertEqual(self._box.get_sequences(), {'flagged':[key0]}) def test_issue2625(self): - msg0 = mailbox.MHMessage(self._template % 0) + msg0 = mailbox.MHMessage(self._template(0)) msg0.add_sequence('foo') key0 = self._box.add(msg0) refmsg0 = self._box.get_message(key0) def test_issue7627(self): - msg0 = mailbox.MHMessage(self._template % 0) + msg0 = mailbox.MHMessage(self._template(0)) key0 = self._box.add(msg0) self._box.lock() self._box.remove(key0) @@ -979,10 +982,10 @@ class TestMH(TestMailbox): def test_pack(self): # Pack the contents of the mailbox - msg0 = mailbox.MHMessage(self._template % 0) - msg1 = mailbox.MHMessage(self._template % 1) - msg2 = mailbox.MHMessage(self._template % 2) - msg3 = mailbox.MHMessage(self._template % 3) + msg0 = mailbox.MHMessage(self._template(0)) + msg1 = mailbox.MHMessage(self._template(1)) + msg2 = mailbox.MHMessage(self._template(2)) + msg3 = mailbox.MHMessage(self._template(3)) msg0.set_sequences(['foo', 'unseen']) msg1.set_sequences(['foo']) msg2.set_sequences(['foo', 'flagged']) @@ -1039,11 +1042,11 @@ class TestBabyl(TestMailbox): def test_labels(self): # Get labels from the mailbox self.assertEqual(self._box.get_labels(), []) - msg0 = mailbox.BabylMessage(self._template % 0) + msg0 = mailbox.BabylMessage(self._template(0)) msg0.add_label('foo') key0 = self._box.add(msg0) self.assertEqual(self._box.get_labels(), ['foo']) - msg1 = mailbox.BabylMessage(self._template % 1) + msg1 = mailbox.BabylMessage(self._template(1)) msg1.set_labels(['bar', 'answered', 'foo']) key1 = self._box.add(msg1) self.assertEqual(set(self._box.get_labels()), set(['foo', 'bar'])) @@ -1067,7 +1070,7 @@ class TestMessage(TestBase): def test_initialize_with_eMM(self): # Initialize based on email.message.Message instance - eMM = email.message_from_string(_sample_message) + eMM = email.message_from_bytes(_sample_message) msg = self._factory(eMM) self._post_initialize_hook(msg) self._check_sample(msg) @@ -1080,7 +1083,7 @@ class TestMessage(TestBase): def test_initialize_with_file(self): # Initialize based on contents of file - with open(self._path, 'w+') as f: + with open(self._path, 'wb+') as f: f.write(_sample_message) f.seek(0) msg = self._factory(f) @@ -1104,7 +1107,7 @@ class TestMessage(TestBase): def test_become_message(self): # Take on the state of another message - eMM = email.message_from_string(_sample_message) + eMM = email.message_from_bytes(_sample_message) msg = self._factory() msg._become_message(eMM) self._check_sample(msg) @@ -1210,20 +1213,20 @@ class _TestMboxMMDFMessage(TestMessage): def test_initialize_with_unixfrom(self): # Initialize with a message that already has a _unixfrom attribute msg = mailbox.Message(_sample_message) - msg.set_unixfrom('From foo@bar blah') + msg.set_unixfrom(b'From foo@bar blah') msg = mailbox.mboxMessage(msg) - self.assertEqual(msg.get_from(), 'foo@bar blah', msg.get_from()) + self.assertEqual(msg.get_from(), b'foo@bar blah', msg.get_from()) def test_from(self): # Get and set "From " line msg = mailbox.mboxMessage(_sample_message) self._check_from(msg) - msg.set_from('foo bar') - self.assertEqual(msg.get_from(), 'foo bar') - msg.set_from('foo@bar', True) - self._check_from(msg, 'foo@bar') - msg.set_from('blah@temp', time.localtime()) - self._check_from(msg, 'blah@temp') + msg.set_from(b'foo bar') + self.assertEqual(msg.get_from(), b'foo bar') + msg.set_from(b'foo@bar', True) + self._check_from(msg, b'foo@bar') + msg.set_from(b'blah@temp', time.localtime()) + self._check_from(msg, b'blah@temp') def test_flags(self): # Use get_flags(), set_flags(), add_flag(), remove_flag() @@ -1242,9 +1245,9 @@ class _TestMboxMMDFMessage(TestMessage): def _check_from(self, msg, sender=None): # Check contents of "From " line if sender is None: - sender = "MAILER-DAEMON" - self.assertTrue(re.match(sender + r" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:" - r"\d{2} \d{4}", msg.get_from()) is not None) + sender = b"MAILER-DAEMON" + self.assertTrue(re.match(sender + br" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:" + br"\d{2} \d{4}", msg.get_from()) is not None) class TestMboxMessage(_TestMboxMMDFMessage): @@ -1393,8 +1396,8 @@ class TestMessageConversion(TestBase): msg_maildir.set_flags(setting) msg = class_(msg_maildir) self.assertEqual(msg.get_flags(), result) - self.assertEqual(msg.get_from(), 'MAILER-DAEMON %s' % - time.asctime(time.gmtime(0.0))) + self.assertEqual(msg.get_from(), b'MAILER-DAEMON ' + + time.asctime(time.gmtime(0.0)).encode('utf-8')) msg_maildir.set_subdir('cur') self.assertEqual(class_(msg_maildir).get_flags(), 'RODFA') @@ -1425,7 +1428,7 @@ class TestMessageConversion(TestBase): # Convert mboxMessage and MMDFMessage to MaildirMessage for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): msg_mboxMMDF = class_(_sample_message) - msg_mboxMMDF.set_from('foo@bar', time.gmtime(0.0)) + msg_mboxMMDF.set_from(b'foo@bar', time.gmtime(0.0)) pairs = (('R', 'S'), ('O', ''), ('D', 'T'), ('F', 'F'), ('A', 'R'), ('RODFA', 'FRST')) for setting, result in pairs: @@ -1442,11 +1445,11 @@ class TestMessageConversion(TestBase): for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): msg_mboxMMDF = class_(_sample_message) msg_mboxMMDF.set_flags('RODFA') - msg_mboxMMDF.set_from('foo@bar') + msg_mboxMMDF.set_from(b'foo@bar') for class2_ in (mailbox.mboxMessage, mailbox.MMDFMessage): msg2 = class2_(msg_mboxMMDF) self.assertEqual(msg2.get_flags(), 'RODFA') - self.assertEqual(msg2.get_from(), 'foo@bar') + self.assertEqual(msg2.get_from(), b'foo@bar') def test_mboxmmdf_to_mh(self): # Convert mboxMessage and MMDFMessage to MHMessage @@ -1774,8 +1777,8 @@ class TestPartialFile(TestProxyFileBase): ## Start: tests from the original module (for backward compatibility). -FROM_ = "From some.body@dummy.domain Sat Jul 24 13:43:35 2004\n" -DUMMY_MESSAGE = """\ +FROM_ = b"From some.body@dummy.domain Sat Jul 24 13:43:35 2004\n" +DUMMY_MESSAGE = b"""\ From: some.body@dummy.domain To: me@my.domain Subject: Simple Test @@ -1809,7 +1812,7 @@ class MaildirTestCase(unittest.TestCase): filename = ".".join((str(t), str(pid), "myhostname", "mydomain")) tmpname = os.path.join(self._dir, "tmp", filename) newname = os.path.join(self._dir, dir, filename) - with open(tmpname, "w") as fp: + with open(tmpname, "wb") as fp: self._msgfiles.append(tmpname) if mbox: fp.write(FROM_) @@ -1817,7 +1820,7 @@ class MaildirTestCase(unittest.TestCase): if hasattr(os, "link"): os.link(tmpname, newname) else: - with open(newname, "w") as fp: + with open(newname, "wb") as fp: fp.write(DUMMY_MESSAGE) self._msgfiles.append(newname) return tmpname @@ -1861,7 +1864,7 @@ class MaildirTestCase(unittest.TestCase): ## End: tests from the original module (for backward compatibility). -_sample_message = """\ +_sample_message = b"""\ Return-Path: X-Original-To: gkj+person@localhost Delivered-To: gkj+person@localhost