diff --git a/.travis.yml b/.travis.yml index 3501212..6d1d0f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,42 +1,51 @@ +version: ~> 1.0 +os: linux language: python -python: '3.5' + +jobs: + # sort by django version, next to by python version + # Django 1.11 support all supported Python interpreter + - env: TOX_ENV=django111-py35 + python: 3.5 + - env: TOX_ENV=django111-py36 + python: 3.6 + # Django 2.0 support 3.5, 3.6 + - env: TOX_ENV=django20-py35 + python: 3.5 + - env: TOX_ENV=django20-py36 + python: 3.6 + + # Django 2.1 support Python 3.5, 3.6, 3.7 + - env: TOX_ENV=django21-py35 + python: 3.5 + - env: TOX_ENV=django21-py36 + python: 3.6 + - env: TOX_ENV=django21-py37 + python: 3.7 + # Django 2.2 support Python 3.5, 3.6, 3.7 + - env: TOX_ENV=django22-py35 + python: 3.5 + - env: TOX_ENV=django22-py36 + python: 3.6 + - env: TOX_ENV=django22-py37 + python: 3.7 + # Django 3.0 (beta) support Python 3.6, 3.7, 3.8 + - env: TOX_ENV=django30-py36 + python: 3.6 + - env: TOX_ENV=django30-py37 + python: 3.7 + - env: TOX_ENV=django30-py38 + python: 3.8 env: - matrix: -# sort by django version, next to by python version -# Django 1.7 support Python 2.7, 3.4 - - TOX_ENV=django17-py27 - - TOX_ENV=django17-py34 -# Django 1.8 support Python 2.7, 3.4, 3.5 - - TOX_ENV=django18-py27 - - TOX_ENV=django18-py34 - - TOX_ENV=django18-py35 -# Django 1.9 support Python 2.7, 3.4, 3.5 - - TOX_ENV=django19-py27 - - TOX_ENV=django19-py34 - - TOX_ENV=django19-py35 -# Django 1.10 support Python 2.7, 3.4, 3.5 - - TOX_ENV=django110-py27 - - TOX_ENV=django110-py34 - - TOX_ENV=django110-py35 -# Django 1.11 support all supported Python interpreter -# Django 2.0 support Python 3.4, 3.5, 3.6 - - TOX_ENV=django111-py34 - - TOX_ENV=django111-py35 - - TOX_ENV=django111-py36 - global: - - secure: aswHU7pQroGM+GHoYlhXzzk2FYfqxXJORjqXPsbgoHAIu4Bssaj8+YAzIcdy3j9kSt4I8VBpjnn8H/wzQXki75JBZOosQrIeMK018+uR+ZMONBLqDYW/N7EJHLgZt9QXxQNKeZygrD4GN/Dc4gLHGvPQC/RfPuuHcnF0Liaahoo= - - secure: RZ6M6984P885GRoyx9n/WCCWGoFAzYpS8sZkXu3e/HK9oPXfaM2IEHjkq03jIC/FcWn/QMtFjOUBqQU94rnqdivFdFkeZHk1WUQgC0hztH3Qhh9zu2PNIrYUDpVD5dJqBpprWbSwFP8yNsJlP9A2RUubTlZblKHuaBhhiuNN+kU= - - secure: gsAAl/RaTodLJDHWOuHZWtooa9/psyXBONF7ElZOTki3WvH+KugtjuXn3pXBGbUhvGqd5qfgPqX7WQOFP9KTdkXBbkU20rCHLh3SV8V2vRkGFAFiGPBTFfSA83zFNMvmgEnTww4OzYsfs4wHTEyxBeQkggnB5bXEvqkFVrHBjuQ= - - secure: mMa7UUt+CQDB52fGM1T3oRL67OzQzRIc+BQCOqUEUhBV7p5g7Y1Hv6NTdVZTvK16x3DsP+5kFNd1v7rsTFw2qzP3hOxIv2BtMPuSzZdnN85Zd/nGwnztxzj/rqw7TMBaYvIdEZZbpRF/K0p0Xr6LJK2s9UkPXPUaLqly7kNi360= + - secure: aswHU7pQroGM+GHoYlhXzzk2FYfqxXJORjqXPsbgoHAIu4Bssaj8+YAzIcdy3j9kSt4I8VBpjnn8H/wzQXki75JBZOosQrIeMK018+uR+ZMONBLqDYW/N7EJHLgZt9QXxQNKeZygrD4GN/Dc4gLHGvPQC/RfPuuHcnF0Liaahoo= + - secure: RZ6M6984P885GRoyx9n/WCCWGoFAzYpS8sZkXu3e/HK9oPXfaM2IEHjkq03jIC/FcWn/QMtFjOUBqQU94rnqdivFdFkeZHk1WUQgC0hztH3Qhh9zu2PNIrYUDpVD5dJqBpprWbSwFP8yNsJlP9A2RUubTlZblKHuaBhhiuNN+kU= + - secure: gsAAl/RaTodLJDHWOuHZWtooa9/psyXBONF7ElZOTki3WvH+KugtjuXn3pXBGbUhvGqd5qfgPqX7WQOFP9KTdkXBbkU20rCHLh3SV8V2vRkGFAFiGPBTFfSA83zFNMvmgEnTww4OzYsfs4wHTEyxBeQkggnB5bXEvqkFVrHBjuQ= + - secure: mMa7UUt+CQDB52fGM1T3oRL67OzQzRIc+BQCOqUEUhBV7p5g7Y1Hv6NTdVZTvK16x3DsP+5kFNd1v7rsTFw2qzP3hOxIv2BtMPuSzZdnN85Zd/nGwnztxzj/rqw7TMBaYvIdEZZbpRF/K0p0Xr6LJK2s9UkPXPUaLqly7kNi360= install: - pip install tox script: - # Update Python 3.6 path - see bug https://github.com/travis-ci/travis-ci/issues/4990 - - if [[ $TOX_ENV = *"py36"* ]]; then echo "Activated PY3.6"; source ~/virtualenv/python3.6/bin/activate; pip install tox; fi - tox -e $TOX_ENV - -sudo: false diff --git a/django_mailbox/admin.py b/django_mailbox/admin.py index c586b40..e9a6ef7 100644 --- a/django_mailbox/admin.py +++ b/django_mailbox/admin.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- """ Model configuration in application ``django_mailbox`` for administration @@ -10,7 +9,7 @@ import logging from django.conf import settings from django.contrib import admin -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django_mailbox.models import MessageAttachment, Message, Mailbox from django_mailbox.signals import message_received @@ -74,7 +73,7 @@ class MessageAdmin(admin.ModelAdmin): def envelope_headers(self, msg): email = msg.get_email_object() return '\n'.join( - [('%s: %s' % (h, v)) for h, v in email.items()] + [('{}: {}'.format(h, v)) for h, v in email.items()] ) inlines = [ diff --git a/django_mailbox/apps.py b/django_mailbox/apps.py index 87eb64b..13b7bf3 100644 --- a/django_mailbox/apps.py +++ b/django_mailbox/apps.py @@ -1,5 +1,5 @@ from django.apps import AppConfig -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ class MailBoxConfig(AppConfig): diff --git a/django_mailbox/migrations/0001_initial.py b/django_mailbox/migrations/0001_initial.py index 0d27460..13bb802 100644 --- a/django_mailbox/migrations/0001_initial.py +++ b/django_mailbox/migrations/0001_initial.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import models, migrations diff --git a/django_mailbox/migrations/0002_add_eml_to_message.py b/django_mailbox/migrations/0002_add_eml_to_message.py index a78cfb4..4204efb 100644 --- a/django_mailbox/migrations/0002_add_eml_to_message.py +++ b/django_mailbox/migrations/0002_add_eml_to_message.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import models, migrations diff --git a/django_mailbox/migrations/0003_auto_20150409_0316.py b/django_mailbox/migrations/0003_auto_20150409_0316.py index 8c3fad9..1b5def0 100644 --- a/django_mailbox/migrations/0003_auto_20150409_0316.py +++ b/django_mailbox/migrations/0003_auto_20150409_0316.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import models, migrations diff --git a/django_mailbox/migrations/0004_bytestring_to_unicode.py b/django_mailbox/migrations/0004_bytestring_to_unicode.py index fedc46a..7716f2f 100644 --- a/django_mailbox/migrations/0004_bytestring_to_unicode.py +++ b/django_mailbox/migrations/0004_bytestring_to_unicode.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import models, migrations diff --git a/django_mailbox/migrations/0005_auto_20160523_2240.py b/django_mailbox/migrations/0005_auto_20160523_2240.py index a639a2c..f4bdae6 100644 --- a/django_mailbox/migrations/0005_auto_20160523_2240.py +++ b/django_mailbox/migrations/0005_auto_20160523_2240.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - from django.db import migrations, models import django_mailbox.utils diff --git a/django_mailbox/migrations/0006_mailbox_last_polling.py b/django_mailbox/migrations/0006_mailbox_last_polling.py index 7979428..5f1524e 100644 --- a/django_mailbox/migrations/0006_mailbox_last_polling.py +++ b/django_mailbox/migrations/0006_mailbox_last_polling.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9.8 on 2016-08-15 22:39 -from __future__ import unicode_literals from django.db import migrations, models diff --git a/django_mailbox/migrations/0007_auto_20180421_0026.py b/django_mailbox/migrations/0007_auto_20180421_0026.py index 4195f70..2e984d0 100644 --- a/django_mailbox/migrations/0007_auto_20180421_0026.py +++ b/django_mailbox/migrations/0007_auto_20180421_0026.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.7 on 2018-04-21 00:26 -from __future__ import unicode_literals from django.db import migrations diff --git a/django_mailbox/models.py b/django_mailbox/models.py index 9f7ffc2..4e5b111 100644 --- a/django_mailbox/models.py +++ b/django_mailbox/models.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- """ Models declaration for application ``django_mailbox``. @@ -8,7 +7,9 @@ import gzip from email.encoders import encode_base64 from email.message import Message as EmailMessage from email.utils import formatdate, parseaddr +from urllib.parse import parse_qs, unquote, urlparse from quopri import encode as encode_quopri +from io import BytesIO import base64 import email import logging @@ -18,17 +19,13 @@ import sys import uuid from tempfile import NamedTemporaryFile -import six -from six.moves.urllib.parse import parse_qs, unquote, urlparse - import django from django.conf import settings as django_settings from django.core.files.base import ContentFile, File from django.core.mail.message import make_msgid from django.db import models -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.utils.timezone import now -from django.utils.encoding import python_2_unicode_compatible from django_mailbox import utils from django_mailbox.signals import message_received @@ -41,20 +38,19 @@ logger = logging.getLogger(__name__) class ActiveMailboxManager(models.Manager): def get_queryset(self): - return super(ActiveMailboxManager, self).get_queryset().filter( + return super().get_queryset().filter( active=True, ) -@python_2_unicode_compatible class Mailbox(models.Model): name = models.CharField( - _(u'Name'), + _('Name'), max_length=255, ) uri = models.CharField( - _(u'URI'), + _('URI'), max_length=255, help_text=(_( "Example: imap+ssl://myusername:mypassword@someserver
" @@ -72,7 +68,7 @@ class Mailbox(models.Model): ) from_email = models.CharField( - _(u'From email'), + _('From email'), max_length=255, help_text=(_( "Example: MailBot <mailbot@yourdomain.com>
" @@ -89,7 +85,7 @@ class Mailbox(models.Model): ) active = models.BooleanField( - _(u'Active'), + _('Active'), help_text=(_( "Check this e-mail inbox for new e-mail messages during polling " "cycles. This checkbox does not have an effect upon whether " @@ -102,7 +98,7 @@ class Mailbox(models.Model): ) last_polling = models.DateTimeField( - _(u"Last polling"), + _("Last polling"), help_text=(_("The time of last successful polling for messages." "It is blank for new mailboxes and is not set for " "mailboxes that only receive messages via a pipe.")), @@ -294,7 +290,7 @@ class Mailbox(models.Model): attachment.document.save( uuid.uuid4().hex + extension, ContentFile( - six.BytesIO( + BytesIO( msg.get_payload(decode=True) ).getvalue() ) @@ -392,7 +388,7 @@ class Mailbox(models.Model): with gzip.GzipFile(fileobj=fp_tmp, mode="w") as fp: fp.write(message.as_string().encode('utf-8')) msg.eml.save( - "%s.eml.gz" % (uuid.uuid4(), ), + "{}.eml.gz".format(uuid.uuid4()), File(fp_tmp), save=False ) @@ -430,41 +426,40 @@ class Mailbox(models.Model): class IncomingMessageManager(models.Manager): def get_queryset(self): - return super(IncomingMessageManager, self).get_queryset().filter( + return super().get_queryset().filter( outgoing=False, ) class OutgoingMessageManager(models.Manager): def get_queryset(self): - return super(OutgoingMessageManager, self).get_queryset().filter( + return super().get_queryset().filter( outgoing=True, ) class UnreadMessageManager(models.Manager): def get_queryset(self): - return super(UnreadMessageManager, self).get_queryset().filter( + return super().get_queryset().filter( read=None ) -@python_2_unicode_compatible class Message(models.Model): mailbox = models.ForeignKey( Mailbox, related_name='messages', - verbose_name=_(u'Mailbox'), + verbose_name=_('Mailbox'), on_delete=models.CASCADE ) subject = models.CharField( - _(u'Subject'), + _('Subject'), max_length=255 ) message_id = models.CharField( - _(u'Message ID'), + _('Message ID'), max_length=255 ) @@ -473,7 +468,7 @@ class Message(models.Model): related_name='replies', blank=True, null=True, - verbose_name=_(u'In reply to'), + verbose_name=_('In reply to'), on_delete=models.CASCADE ) @@ -483,21 +478,21 @@ class Message(models.Model): ) to_header = models.TextField( - _(u'To header'), + _('To header'), ) outgoing = models.BooleanField( - _(u'Outgoing'), + _('Outgoing'), default=False, blank=True, ) body = models.TextField( - _(u'Body'), + _('Body'), ) encoded = models.BooleanField( - _(u'Encoded'), + _('Encoded'), default=False, help_text=_('True if the e-mail body is Base64 encoded'), ) @@ -508,17 +503,17 @@ class Message(models.Model): ) read = models.DateTimeField( - _(u'Read'), + _('Read'), default=None, blank=True, null=True, ) eml = models.FileField( - _(u'Raw message contents'), + _('Raw message contents'), null=True, upload_to="messages", - help_text=_(u'Original full content of message') + help_text=_('Original full content of message') ) objects = models.Manager() unread_messages = UnreadMessageManager() @@ -634,9 +629,9 @@ class Message(models.Model): if encoding and encoding.lower() == 'quoted-printable': # Cannot use `email.encoders.encode_quopri due to # bug 14360: http://bugs.python.org/issue14360 - output = six.BytesIO() + output = BytesIO() encode_quopri( - six.BytesIO( + BytesIO( attachment.document.read() ), output, @@ -688,10 +683,8 @@ class Message(models.Model): no fields existed for storing arbitrary bytes. """ - if six.PY3: - body = body.encode('utf-8') self.encoded = True - self.body = base64.b64encode(body).decode('ascii') + self.body = base64.b64encode(body.encode('utf-8')).decode('ascii') def get_email_object(self): """Returns an `email.message.Message` instance representing the @@ -722,10 +715,7 @@ class Message(models.Model): self.eml.close() else: body = self.get_body() - if six.PY3: - flat = email.message_from_bytes(body) - else: - flat = email.message_from_string(body) + flat = email.message_from_bytes(body) self._email_object = self._rehydrate(flat) return self._email_object @@ -734,7 +724,7 @@ class Message(models.Model): for attachment in self.attachments.all(): # This attachment is attached only to this message. attachment.delete() - return super(Message, self).delete(*args, **kwargs) + return super().delete(*args, **kwargs) def __str__(self): return self.subject @@ -744,7 +734,6 @@ class Message(models.Model): verbose_name_plural = _('E-mail messages') -@python_2_unicode_compatible class MessageAttachment(models.Model): message = models.ForeignKey( Message, @@ -756,30 +745,25 @@ class MessageAttachment(models.Model): ) headers = models.TextField( - _(u'Headers'), + _('Headers'), null=True, blank=True, ) document = models.FileField( - _(u'Document'), + _('Document'), upload_to=utils.get_attachment_save_path, ) def delete(self, *args, **kwargs): """Deletes the attachment.""" self.document.delete() - return super(MessageAttachment, self).delete(*args, **kwargs) + return super().delete(*args, **kwargs) def _get_rehydrated_headers(self): headers = self.headers if headers is None: return EmailMessage() - if sys.version_info < (3, 0): - try: - headers = headers.encode('utf-8') - except UnicodeDecodeError: - headers = headers.decode('utf-8').encode('utf-8') return email.message_from_string(headers) def _set_dehydrated_headers(self, email_object): @@ -798,7 +782,7 @@ class MessageAttachment(models.Model): def get_filename(self): """Returns the original filename of this attachment.""" file_name = self._get_rehydrated_headers().get_filename() - if isinstance(file_name, six.string_types): + if isinstance(file_name, str): result = utils.convert_header_to_unicode(file_name) if result is None: return file_name diff --git a/django_mailbox/south_migrations/0001_initial.py b/django_mailbox/south_migrations/0001_initial.py index 4faa4fa..dcfdf60 100644 --- a/django_mailbox/south_migrations/0001_initial.py +++ b/django_mailbox/south_migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0002_auto__chg_field_mailbox_uri.py b/django_mailbox/south_migrations/0002_auto__chg_field_mailbox_uri.py index 3ff3098..47517b3 100644 --- a/django_mailbox/south_migrations/0002_auto__chg_field_mailbox_uri.py +++ b/django_mailbox/south_migrations/0002_auto__chg_field_mailbox_uri.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0003_auto__add_field_mailbox_active.py b/django_mailbox/south_migrations/0003_auto__add_field_mailbox_active.py index a067e50..30e4354 100644 --- a/django_mailbox/south_migrations/0003_auto__add_field_mailbox_active.py +++ b/django_mailbox/south_migrations/0003_auto__add_field_mailbox_active.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0004_auto__add_field_message_outgoing.py b/django_mailbox/south_migrations/0004_auto__add_field_message_outgoing.py index 20e889a..245c43b 100644 --- a/django_mailbox/south_migrations/0004_auto__add_field_message_outgoing.py +++ b/django_mailbox/south_migrations/0004_auto__add_field_message_outgoing.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0005_rename_fields.py b/django_mailbox/south_migrations/0005_rename_fields.py index 35bc858..72cb437 100644 --- a/django_mailbox/south_migrations/0005_rename_fields.py +++ b/django_mailbox/south_migrations/0005_rename_fields.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0006_auto__add_field_message_in_reply_to.py b/django_mailbox/south_migrations/0006_auto__add_field_message_in_reply_to.py index 7c8b9d7..4287fb2 100644 --- a/django_mailbox/south_migrations/0006_auto__add_field_message_in_reply_to.py +++ b/django_mailbox/south_migrations/0006_auto__add_field_message_in_reply_to.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0007_auto__del_field_message_address__add_field_message_from_header__add_fi.py b/django_mailbox/south_migrations/0007_auto__del_field_message_address__add_field_message_from_header__add_fi.py index 150e53e..cfa7d6f 100644 --- a/django_mailbox/south_migrations/0007_auto__del_field_message_address__add_field_message_from_header__add_fi.py +++ b/django_mailbox/south_migrations/0007_auto__del_field_message_address__add_field_message_from_header__add_fi.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0008_populate_from_to_fields.py b/django_mailbox/south_migrations/0008_populate_from_to_fields.py index 68de935..e047f22 100644 --- a/django_mailbox/south_migrations/0008_populate_from_to_fields.py +++ b/django_mailbox/south_migrations/0008_populate_from_to_fields.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime import email from south.db import db diff --git a/django_mailbox/south_migrations/0009_remove_references_table.py b/django_mailbox/south_migrations/0009_remove_references_table.py index 38afc96..3868585 100644 --- a/django_mailbox/south_migrations/0009_remove_references_table.py +++ b/django_mailbox/south_migrations/0009_remove_references_table.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0010_auto__add_field_mailbox_from_email.py b/django_mailbox/south_migrations/0010_auto__add_field_mailbox_from_email.py index 9261e6d..a988e5e 100644 --- a/django_mailbox/south_migrations/0010_auto__add_field_mailbox_from_email.py +++ b/django_mailbox/south_migrations/0010_auto__add_field_mailbox_from_email.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0011_auto__add_field_message_read.py b/django_mailbox/south_migrations/0011_auto__add_field_message_read.py index b288170..c75db34 100644 --- a/django_mailbox/south_migrations/0011_auto__add_field_message_read.py +++ b/django_mailbox/south_migrations/0011_auto__add_field_message_read.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0012_auto__add_messageattachment.py b/django_mailbox/south_migrations/0012_auto__add_messageattachment.py index 554483e..b62e50e 100644 --- a/django_mailbox/south_migrations/0012_auto__add_messageattachment.py +++ b/django_mailbox/south_migrations/0012_auto__add_messageattachment.py @@ -1,4 +1,3 @@ -# encoding: utf-8 import datetime from south.db import db from south.v2 import SchemaMigration diff --git a/django_mailbox/south_migrations/0013_auto__add_field_messageattachment_message.py b/django_mailbox/south_migrations/0013_auto__add_field_messageattachment_message.py index d1b9b0d..01c80a2 100644 --- a/django_mailbox/south_migrations/0013_auto__add_field_messageattachment_message.py +++ b/django_mailbox/south_migrations/0013_auto__add_field_messageattachment_message.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration @@ -9,33 +8,33 @@ class Migration(SchemaMigration): def forwards(self, orm): # Adding field 'MessageAttachment.message' - db.add_column(u'django_mailbox_messageattachment', 'message', + db.add_column('django_mailbox_messageattachment', 'message', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='attachments', null=True, to=orm['django_mailbox.Message']), keep_default=False) def backwards(self, orm): # Deleting field 'MessageAttachment.message' - db.delete_column(u'django_mailbox_messageattachment', 'message_id') + db.delete_column('django_mailbox_messageattachment', 'message_id') models = { - u'django_mailbox.mailbox': { + 'django_mailbox.mailbox': { 'Meta': {'object_name': 'Mailbox'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) }, - u'django_mailbox.message': { + 'django_mailbox.message': { 'Meta': {'object_name': 'Message'}, - 'attachments': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'messages_old'", 'blank': 'True', 'to': u"orm['django_mailbox.MessageAttachment']"}), + 'attachments': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'messages_old'", 'blank': 'True', 'to': "orm['django_mailbox.MessageAttachment']"}), 'body': ('django.db.models.fields.TextField', [], {}), 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}), - 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['django_mailbox.Mailbox']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}), + 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}), 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), @@ -43,11 +42,11 @@ class Migration(SchemaMigration): 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'to_header': ('django.db.models.fields.TextField', [], {}) }, - u'django_mailbox.messageattachment': { + 'django_mailbox.messageattachment': { 'Meta': {'object_name': 'MessageAttachment'}, 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments_new'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}) + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments_new'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}) } } diff --git a/django_mailbox/south_migrations/0014_migrate_message_attachments.py b/django_mailbox/south_migrations/0014_migrate_message_attachments.py index a4fff5d..b018915 100644 --- a/django_mailbox/south_migrations/0014_migrate_message_attachments.py +++ b/django_mailbox/south_migrations/0014_migrate_message_attachments.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration @@ -21,22 +20,22 @@ class Migration(SchemaMigration): ) models = { - u'django_mailbox.mailbox': { + 'django_mailbox.mailbox': { 'Meta': {'object_name': 'Mailbox'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) }, - u'django_mailbox.message': { + 'django_mailbox.message': { 'Meta': {'object_name': 'Message'}, - 'attachments': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'messages_old'", 'blank': 'True', 'to': u"orm['django_mailbox.MessageAttachment']"}), + 'attachments': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'messages_old'", 'blank': 'True', 'to': "orm['django_mailbox.MessageAttachment']"}), 'body': ('django.db.models.fields.TextField', [], {}), 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}), - 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['django_mailbox.Mailbox']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}), + 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}), 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), @@ -44,11 +43,11 @@ class Migration(SchemaMigration): 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'to_header': ('django.db.models.fields.TextField', [], {}) }, - u'django_mailbox.messageattachment': { + 'django_mailbox.messageattachment': { 'Meta': {'object_name': 'MessageAttachment'}, 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments_new'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}) + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments_new'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}) } } diff --git a/django_mailbox/south_migrations/0015_auto__add_field_messageattachment_headers.py b/django_mailbox/south_migrations/0015_auto__add_field_messageattachment_headers.py index 7531244..71ecfbd 100644 --- a/django_mailbox/south_migrations/0015_auto__add_field_messageattachment_headers.py +++ b/django_mailbox/south_migrations/0015_auto__add_field_messageattachment_headers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration @@ -12,40 +11,40 @@ class Migration(SchemaMigration): db.delete_table('django_mailbox_message_attachments') # Adding field 'MessageAttachment.headers' - db.add_column(u'django_mailbox_messageattachment', 'headers', + db.add_column('django_mailbox_messageattachment', 'headers', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False) def backwards(self, orm): # Adding M2M table for field attachments on 'Message' - db.create_table(u'django_mailbox_message_attachments', ( + db.create_table('django_mailbox_message_attachments', ( ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('message', models.ForeignKey(orm[u'django_mailbox.message'], null=False)), - ('messageattachment', models.ForeignKey(orm[u'django_mailbox.messageattachment'], null=False)) + ('message', models.ForeignKey(orm['django_mailbox.message'], null=False)), + ('messageattachment', models.ForeignKey(orm['django_mailbox.messageattachment'], null=False)) )) - db.create_unique(u'django_mailbox_message_attachments', ['message_id', 'messageattachment_id']) + db.create_unique('django_mailbox_message_attachments', ['message_id', 'messageattachment_id']) # Deleting field 'MessageAttachment.headers' - db.delete_column(u'django_mailbox_messageattachment', 'headers') + db.delete_column('django_mailbox_messageattachment', 'headers') models = { - u'django_mailbox.mailbox': { + 'django_mailbox.mailbox': { 'Meta': {'object_name': 'Mailbox'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) }, - u'django_mailbox.message': { + 'django_mailbox.message': { 'Meta': {'object_name': 'Message'}, 'body': ('django.db.models.fields.TextField', [], {}), 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}), - 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['django_mailbox.Mailbox']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}), + 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}), 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), @@ -53,12 +52,12 @@ class Migration(SchemaMigration): 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'to_header': ('django.db.models.fields.TextField', [], {}) }, - u'django_mailbox.messageattachment': { + 'django_mailbox.messageattachment': { 'Meta': {'object_name': 'MessageAttachment'}, 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 'headers': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}) + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}) } } diff --git a/django_mailbox/south_migrations/0016_auto__add_field_message_encoded.py b/django_mailbox/south_migrations/0016_auto__add_field_message_encoded.py index 8fa5e9d..cd4c678 100644 --- a/django_mailbox/south_migrations/0016_auto__add_field_message_encoded.py +++ b/django_mailbox/south_migrations/0016_auto__add_field_message_encoded.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from south.db import db from south.v2 import SchemaMigration @@ -9,33 +8,33 @@ class Migration(SchemaMigration): def forwards(self, orm): # Adding field 'Message.encoded' - db.add_column(u'django_mailbox_message', 'encoded', + db.add_column('django_mailbox_message', 'encoded', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) def backwards(self, orm): # Deleting field 'Message.encoded' - db.delete_column(u'django_mailbox_message', 'encoded') + db.delete_column('django_mailbox_message', 'encoded') models = { - u'django_mailbox.mailbox': { + 'django_mailbox.mailbox': { 'Meta': {'object_name': 'Mailbox'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) }, - u'django_mailbox.message': { + 'django_mailbox.message': { 'Meta': {'object_name': 'Message'}, 'body': ('django.db.models.fields.TextField', [], {}), 'encoded': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}), - 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['django_mailbox.Mailbox']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}), + 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}), 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), @@ -43,12 +42,12 @@ class Migration(SchemaMigration): 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'to_header': ('django.db.models.fields.TextField', [], {}) }, - u'django_mailbox.messageattachment': { + 'django_mailbox.messageattachment': { 'Meta': {'object_name': 'MessageAttachment'}, 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 'headers': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}) + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}) } } diff --git a/django_mailbox/south_migrations/0017_auto__add_field_message_eml.py b/django_mailbox/south_migrations/0017_auto__add_field_message_eml.py index 9762908..186c8bd 100644 --- a/django_mailbox/south_migrations/0017_auto__add_field_message_eml.py +++ b/django_mailbox/south_migrations/0017_auto__add_field_message_eml.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from south.utils import datetime_utils as datetime from south.db import db from south.v2 import SchemaMigration @@ -9,34 +8,34 @@ class Migration(SchemaMigration): def forwards(self, orm): # Adding field 'Message.eml' - db.add_column(u'django_mailbox_message', 'eml', + db.add_column('django_mailbox_message', 'eml', self.gf('django.db.models.fields.files.FileField')(max_length=100, null=True), keep_default=False) def backwards(self, orm): # Deleting field 'Message.eml' - db.delete_column(u'django_mailbox_message', 'eml') + db.delete_column('django_mailbox_message', 'eml') models = { - u'django_mailbox.mailbox': { + 'django_mailbox.mailbox': { 'Meta': {'object_name': 'Mailbox'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) }, - u'django_mailbox.message': { + 'django_mailbox.message': { 'Meta': {'object_name': 'Message'}, 'body': ('django.db.models.fields.TextField', [], {}), 'eml': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True'}), 'encoded': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}), - 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['django_mailbox.Mailbox']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}), + 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}), 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), @@ -44,12 +43,12 @@ class Migration(SchemaMigration): 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'to_header': ('django.db.models.fields.TextField', [], {}) }, - u'django_mailbox.messageattachment': { + 'django_mailbox.messageattachment': { 'Meta': {'object_name': 'MessageAttachment'}, 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 'headers': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': u"orm['django_mailbox.Message']"}) + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}) } } diff --git a/django_mailbox/tests/base.py b/django_mailbox/tests/base.py index 4884765..b1215c5 100644 --- a/django_mailbox/tests/base.py +++ b/django_mailbox/tests/base.py @@ -2,8 +2,6 @@ import email import os.path import time -import six - from django.conf import settings from django.test import TestCase @@ -57,7 +55,7 @@ class EmailMessageTestCase(TestCase): settings.EMAIL_HOST_USER = self.test_account settings.EMAIL_HOST_PASSWORD = self.test_password settings.EMAIL_USE_TLS = True - super(EmailMessageTestCase, self).setUp() + super().setUp() def _get_new_messages(self, mailbox, condition=None): start_time = time.time() @@ -70,8 +68,7 @@ class EmailMessageTestCase(TestCase): # check if generator contains at least one element message = next(messages) yield message - for message in messages: - yield message + yield from messages return except StopIteration: @@ -92,10 +89,7 @@ class EmailMessageTestCase(TestCase): def _get_email_object(self, name): copy = self._get_email_as_text(name) - if six.PY3: - return email.message_from_bytes(copy) - else: - return email.message_from_string(copy) + return email.message_from_bytes(copy) def _headers_identical(self, left, right, header=None): """ Check if headers are (close enough to) identical. @@ -131,7 +125,7 @@ class EmailMessageTestCase(TestCase): raise AssertionError("Extra header '%s'" % key) if not self._headers_identical(right[key], value, header=key): raise AssertionError( - "Header '%s' unequal:\n%s\n%s" % ( + "Header '{}' unequal:\n{}\n{}".format( key, repr(value), repr(right[key]), @@ -144,7 +138,7 @@ class EmailMessageTestCase(TestCase): raise AssertionError("Extra header '%s'" % key) if not self._headers_identical(left[key], value, header=key): raise AssertionError( - "Header '%s' unequal:\n%s\n%s" % ( + "Header '{}' unequal:\n{}\n{}".format( key, repr(value), repr(right[key]), @@ -175,7 +169,7 @@ class EmailMessageTestCase(TestCase): def _raise_mismatched(self, left, right): raise AssertionError( - "Message payloads do not match:\n%s\n%s" % ( + "Message payloads do not match:\n{}\n{}".format( left.as_string(), right.as_string() ) @@ -183,7 +177,7 @@ class EmailMessageTestCase(TestCase): def assertEqual(self, left, right): # noqa: N802 if not isinstance(left, email.message.Message): - return super(EmailMessageTestCase, self).assertEqual(left, right) + return super().assertEqual(left, right) return self.compare_email_objects(left, right) def tearDown(self): @@ -194,4 +188,4 @@ class EmailMessageTestCase(TestCase): models.TEXT_STORED_MIMETYPES = self._TEXT_STORED_MIMETYPES self.mailbox.delete() - super(EmailMessageTestCase, self).tearDown() + super().tearDown() diff --git a/django_mailbox/tests/test_integration_imap.py b/django_mailbox/tests/test_integration_imap.py index 1110f69..6f875b7 100644 --- a/django_mailbox/tests/test_integration_imap.py +++ b/django_mailbox/tests/test_integration_imap.py @@ -1,7 +1,6 @@ import os import uuid - -from six.moves.urllib import parse +from urllib import parse from django.core.mail import EmailMultiAlternatives @@ -14,7 +13,7 @@ __all__ = ['TestImap'] class TestImap(EmailMessageTestCase): def setUp(self): - super(TestImap, self).setUp() + super().setUp() self.test_imap_server = ( os.environ.get('EMAIL_IMAP_SERVER') diff --git a/django_mailbox/tests/test_message_flattening.py b/django_mailbox/tests/test_message_flattening.py index fd9a9b4..669433e 100644 --- a/django_mailbox/tests/test_message_flattening.py +++ b/django_mailbox/tests/test_message_flattening.py @@ -1,6 +1,6 @@ import copy -import mock +from unittest import mock from django_mailbox import models, utils from django_mailbox.models import Message diff --git a/django_mailbox/tests/test_process_email.py b/django_mailbox/tests/test_process_email.py index 831eeaf..a6dbd04 100644 --- a/django_mailbox/tests/test_process_email.py +++ b/django_mailbox/tests/test_process_email.py @@ -3,8 +3,7 @@ import os.path import sys import copy -import mock -import six +from unittest import mock from django_mailbox.models import Mailbox, Message from django_mailbox.utils import convert_header_to_unicode @@ -54,18 +53,18 @@ class TestProcessEmail(EmailMessageTestCase): attachments = msg.attachments.order_by('pk').all() self.assertEqual( - u'\u041f\u0430\u043a\u0435\u0442 \u043f\u0440\u0435\u0434\u043b' - u'\u043e\u0436\u0435\u043d\u0438\u0439 HSE Career Fair 8 \u0430' - u'\u043f\u0440\u0435\u043b\u044f 2016.pdf', + '\u041f\u0430\u043a\u0435\u0442 \u043f\u0440\u0435\u0434\u043b' + '\u043e\u0436\u0435\u043d\u0438\u0439 HSE Career Fair 8 \u0430' + '\u043f\u0440\u0435\u043b\u044f 2016.pdf', attachments[0].get_filename() ) self.assertEqual( - u'\u0412\u0435\u0434\u043e\u043c\u043e\u0441\u0442\u0438.pdf', + '\u0412\u0435\u0434\u043e\u043c\u043e\u0441\u0442\u0438.pdf', attachments[1].get_filename() ) self.assertEqual( - u'\u041f\u0430\u043a\u0435\u0442 \u043f\u0440\u0435\u0434\u043b' - u'\u043e\u0436\u0435\u043d\u0438\u0439 2016.pptx', + '\u041f\u0430\u043a\u0435\u0442 \u043f\u0440\u0435\u0434\u043b' + '\u043e\u0436\u0435\u043d\u0438\u0439 2016.pptx', attachments[2].get_filename() ) @@ -89,33 +88,6 @@ class TestProcessEmail(EmailMessageTestCase): 'heart.png', ) - def test_message_with_not_decoded_attachment_header(self): - if sys.version_info > (3, 0): - self.skipTest( - "This test is only relevant on Python 2.x." - ) - - email_object = self._get_email_object( - 'message_with_not_decoded_attachment_header.eml', - ) - - mailbox = Mailbox.objects.create() - msg = mailbox.process_incoming_message(email_object) - - expected_count = 1 - actual_count = msg.attachments.count() - - self.assertEqual( - expected_count, - actual_count, - ) - - attachment = msg.attachments.all()[0] - self.assertEqual( - attachment.get_filename(), - u'\xc3\xb0\xcc\x9eo\xce\xb2\xcc\x9ele.png', - ) - def test_message_with_utf8_attachment_header(self): """ Ensure that we properly handle UTF-8 encoded attachment @@ -138,13 +110,13 @@ class TestProcessEmail(EmailMessageTestCase): attachment = msg.attachments.all()[0] self.assertEqual( attachment.get_filename(), - u'pi\u0142kochwyty.jpg' + 'pi\u0142kochwyty.jpg' ) attachment = msg.attachments.all()[1] self.assertEqual( attachment.get_filename(), - u'odpowied\u017a Burmistrza.jpg' + 'odpowied\u017a Burmistrza.jpg' ) def test_message_get_text_body(self): @@ -187,7 +159,7 @@ class TestProcessEmail(EmailMessageTestCase): 'messages/generic_message.eml' ) ) as f: - unicode_body = six.u(f.read()) + unicode_body = f.read() message = Message() message.body = unicode_body @@ -281,10 +253,8 @@ class TestProcessEmail(EmailMessageTestCase): msg = self.mailbox.process_incoming_message(email_object) - expected_text = six.u( - 'This message contains funny UTF16 characters like this one: ' - '"\xc2\xa0" and this one "\xe2\x9c\xbf".' - ) + expected_text = 'This message contains funny UTF16 characters ' + \ + 'like this one: "\xc2\xa0" and this one "\xe2\x9c\xbf".' actual_text = msg.text self.assertEqual( @@ -320,14 +290,12 @@ class TestProcessEmail(EmailMessageTestCase): msg = self.mailbox.process_incoming_message(email_object) actual_text = msg.text - expected_body = six.u( - '\u042d\u0442\u043e ' - '\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 ' - '\u0438\u043c\u0435\u0435\u0442 ' - '\u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d' - '\u0443\u044e ' + expected_body = '\u042d\u0442\u043e ' + \ + '\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 ' + \ + '\u0438\u043c\u0435\u0435\u0442 ' + \ + '\u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d' + \ + '\u0443\u044e ' + \ '\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430.' - ) self.assertEqual( actual_text, @@ -341,23 +309,15 @@ class TestProcessEmail(EmailMessageTestCase): msg = self.mailbox.process_incoming_message(email_object) - expected_subject = six.u( - '\u00D3\u00E7\u00ED\u00E0\u00E9 \u00EA\u00E0\u00EA ' - '\u00E7\u00E0\u00F0\u00E0\u00E1\u00E0\u00F2\u00FB\u00E2' - '\u00E0\u00F2\u00FC \u00EE\u00F2 1000$ \u00E2 ' + expected_subject = '\u00D3\u00E7\u00ED\u00E0\u00E9 \u00EA\u00E0\u00EA ' + \ + '\u00E7\u00E0\u00F0\u00E0\u00E1\u00E0\u00F2\u00FB\u00E2' + \ + '\u00E0\u00F2\u00FC \u00EE\u00F2 1000$ \u00E2 ' + \ '\u00ED\u00E5\u00E4\u00E5\u00EB\u00FE!' - ) actual_subject = msg.subject self.assertEqual(actual_subject, expected_subject) - if sys.version_info >= (3, 3): - # There were various bugfixes in Py3k's email module, - # this is apparently one of them. - expected_from = six.u('test test ') - else: - expected_from = six.u('test test') + expected_from = 'test test ' actual_from = msg.from_header - self.assertEqual(expected_from, actual_from) def test_message_reply(self): @@ -426,15 +386,15 @@ class TestProcessEmail(EmailMessageTestCase): msg = self.mailbox.process_incoming_message(message) - actual_email_object = msg.get_email_object() - self.assertNotEquals(msg.eml, None) self.assertTrue(msg.eml.name.endswith('.eml')) with open(msg.eml.name, 'rb') as f: - self.assertEqual(f.read(), - self._get_email_as_text('generic_message.eml')) + self.assertEqual( + f.read(), + self._get_email_as_text('generic_message.eml') + ) def test_message_saving_ignored(self): message = self._get_email_object('generic_message.eml') diff --git a/django_mailbox/tests/test_processincomingmessage.py b/django_mailbox/tests/test_processincomingmessage.py index 5ec2432..8ba2fb2 100644 --- a/django_mailbox/tests/test_processincomingmessage.py +++ b/django_mailbox/tests/test_processincomingmessage.py @@ -1,5 +1,5 @@ from distutils.version import LooseVersion -import mock +from unittest import mock from django.core.management import call_command, CommandError from django.test import TestCase diff --git a/django_mailbox/tests/test_transports.py b/django_mailbox/tests/test_transports.py index 1d3c68f..403a306 100644 --- a/django_mailbox/tests/test_transports.py +++ b/django_mailbox/tests/test_transports.py @@ -1,5 +1,4 @@ -import mock -import six +from unittest import mock from django.test.utils import override_settings @@ -9,24 +8,22 @@ from django_mailbox.transports import ImapTransport, Pop3Transport FAKE_UID_SEARCH_ANSWER = ( 'OK', [ - six.b( - '18 19 20 21 22 23 24 25 26 27 28 29 ' - '30 31 32 33 34 35 36 37 38 39 40 41 42 43 44' - ) + b'18 19 20 21 22 23 24 25 26 27 28 29 ' + + b'30 31 32 33 34 35 36 37 38 39 40 41 42 43 44' ] ) FAKE_UID_FETCH_SIZES = ( 'OK', [ - six.b('1 (UID 18 RFC822.SIZE 58070000000)'), - six.b('2 (UID 19 RFC822.SIZE 2593)') + b'1 (UID 18 RFC822.SIZE 58070000000)', + b'2 (UID 19 RFC822.SIZE 2593)' ] ) FAKE_UID_FETCH_MSG = ( 'OK', [ ( - six.b('1 (UID 18 RFC822 {5807}'), + b'1 (UID 18 RFC822 {5807}', get_email_as_text('generic_message.eml') ), ] @@ -34,13 +31,13 @@ FAKE_UID_FETCH_MSG = ( FAKE_UID_COPY_MSG = ( 'OK', [ - six.b('[COPYUID 1 2 2] (Success)') + b'[COPYUID 1 2 2] (Success)' ] ) FAKE_LIST_ARCHIVE_FOLDERS_ANSWERS = ( 'OK', [ - six.b('(\\HasNoChildren \\All) "/" "[Gmail]/All Mail"') + b'(\\HasNoChildren \\All) "/" "[Gmail]/All Mail"' ] ) @@ -66,12 +63,12 @@ class IMAPTestCase(EmailMessageTestCase): self.imap_server = mock.Mock() self.imap_server.uid = imap_server_uid_method self.imap_server.list = imap_server_list_method - super(IMAPTestCase, self).setUp() + super().setUp() class TestImapTransport(IMAPTestCase): def setUp(self): - super(TestImapTransport, self).setUp() + super().setUp() self.arbitrary_hostname = 'one.two.three' self.arbitrary_port = 100 self.ssl = False @@ -92,7 +89,7 @@ class TestImapTransport(IMAPTestCase): class TestImapArchivedTransport(TestImapTransport): def setUp(self): - super(TestImapArchivedTransport, self).setUp() + super().setUp() self.archive = 'Archive' self.transport = ImapTransport( self.arbitrary_hostname, @@ -107,7 +104,7 @@ class TestMaxSizeImapTransport(TestImapTransport): @override_settings(DJANGO_MAILBOX_MAX_MESSAGE_SIZE=5807) def setUp(self): - super(TestMaxSizeImapTransport, self).setUp() + super().setUp() self.transport = ImapTransport( self.arbitrary_hostname, @@ -142,7 +139,7 @@ class TestPop3Transport(EmailMessageTestCase): self.ssl ) self.transport.server = None - super(TestPop3Transport, self).setUp() + super().setUp() def test_get_email_message(self): with mock.patch.object(self.transport, 'server') as server: diff --git a/django_mailbox/transports/base.py b/django_mailbox/transports/base.py index d65ad35..a90af9f 100644 --- a/django_mailbox/transports/base.py +++ b/django_mailbox/transports/base.py @@ -1,19 +1,11 @@ import email -import six - # Do *not* remove this, we need to use this in subclasses of EmailTransport -if six.PY3: - from email.errors import MessageParseError # noqa: F401 -else: - from email.Errors import MessageParseError # noqa: F401 +from email.errors import MessageParseError # noqa: F401 -class EmailTransport(object): +class EmailTransport: def get_email_from_bytes(self, contents): - if six.PY3: - message = email.message_from_bytes(contents) - else: - message = email.message_from_string(contents) + message = email.message_from_bytes(contents) return message diff --git a/django_mailbox/transports/generic.py b/django_mailbox/transports/generic.py index 7738b8c..5832fda 100644 --- a/django_mailbox/transports/generic.py +++ b/django_mailbox/transports/generic.py @@ -1,5 +1,4 @@ import sys -import six from .base import EmailTransport @@ -9,13 +8,8 @@ class GenericFileMailbox(EmailTransport): _path = None def __init__(self, path): - super(GenericFileMailbox, self).__init__() - if six.PY2: - self._path = path.encode( - sys.getfilesystemencoding() - ) - else: - self._path = path + super().__init__() + self._path = path def get_instance(self): return self._variant(self._path) diff --git a/django_mailbox/transports/gmail.py b/django_mailbox/transports/gmail.py index 0922f9a..99e8189 100644 --- a/django_mailbox/transports/gmail.py +++ b/django_mailbox/transports/gmail.py @@ -48,7 +48,7 @@ class GmailImapTransport(ImapTransport): ) ) - auth_string = 'user=%s\1auth=Bearer %s\1\1' % ( + auth_string = 'user={}\1auth=Bearer {}\1\1'.format( google_email_address, access_token ) diff --git a/django_mailbox/transports/imap.py b/django_mailbox/transports/imap.py index 2c449c3..2599ada 100644 --- a/django_mailbox/transports/imap.py +++ b/django_mailbox/transports/imap.py @@ -88,7 +88,7 @@ class ImapTransport(EmailTransport): safe_message_ids.append(uid) except ValueError as e: logger.warning( - "ValueError: %s working on %s" % (e, each_msg[0]) + "ValueError: {} working on {}".format(e, each_msg[0]) ) pass return safe_message_ids diff --git a/django_mailbox/transports/pop3.py b/django_mailbox/transports/pop3.py index 4601114..6dbe995 100644 --- a/django_mailbox/transports/pop3.py +++ b/django_mailbox/transports/pop3.py @@ -1,5 +1,3 @@ -import six - from poplib import POP3, POP3_SSL from .base import EmailTransport, MessageParseError @@ -24,9 +22,7 @@ class Pop3Transport(EmailTransport): self.server.pass_(password) def get_message_body(self, message_lines): - if six.PY3: - return six.binary_type('\r\n', 'ascii').join(message_lines) - return '\r\n'.join(message_lines) + return bytes('\r\n', 'ascii').join(message_lines) def get_message(self, condition=None): message_count = len(self.server.list()[1]) diff --git a/django_mailbox/utils.py b/django_mailbox/utils.py index 48e76be..6603612 100644 --- a/django_mailbox/utils.py +++ b/django_mailbox/utils.py @@ -3,8 +3,6 @@ import email.header import logging import os -import six - from django.conf import settings @@ -75,11 +73,8 @@ def get_settings(): def convert_header_to_unicode(header): default_charset = get_settings()['default_charset'] - if six.PY2 and isinstance(header, six.text_type): - return header - def _decode(value, encoding): - if isinstance(value, six.text_type): + if isinstance(value, str): return value if not encoding or encoding == 'unknown-8bit': encoding = default_charset @@ -106,7 +101,7 @@ def get_body_from_message(message, maintype, subtype): """ Fetchs the body message matching main/sub content type. """ - body = six.text_type('') + body = '' for part in message.walk(): if part.get('content-disposition', '').startswith('attachment;'): continue diff --git a/docs/conf.py b/docs/conf.py index 019ae14..335f1d5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # django-mailbox documentation build configuration file, created by # sphinx-quickstart on Tue Jan 22 20:29:12 2013. @@ -40,8 +39,8 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'django-mailbox' -copyright = u'2014, Adam Coddington' +project = 'django-mailbox' +copyright = '2014, Adam Coddington' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -183,8 +182,8 @@ latex_elements = { # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'django-mailbox.tex', u'django-mailbox Documentation', - u'Adam Coddington', 'manual'), + ('index', 'django-mailbox.tex', 'django-mailbox Documentation', + 'Adam Coddington', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -213,8 +212,8 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'django-mailbox', u'django-mailbox Documentation', - [u'Adam Coddington'], 1) + ('index', 'django-mailbox', 'django-mailbox Documentation', + ['Adam Coddington'], 1) ] # If true, show URL addresses after external links. @@ -227,8 +226,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'django-mailbox', u'django-mailbox Documentation', - u'Adam Coddington', 'django-mailbox', 'One line description of project.', + ('index', 'django-mailbox', 'django-mailbox Documentation', + 'Adam Coddington', 'django-mailbox', 'One line description of project.', 'Miscellaneous'), ] @@ -275,18 +274,18 @@ def process_docstring(app, what, name, obj, options, lines): if help_text: # Add the model field to the end of the docstring as a param # using the help text as the description - lines.append(u':param %s: %s' % (field.attname, help_text)) + lines.append(':param {}: {}'.format(field.attname, help_text)) else: # Add the model field to the end of the docstring as a param # using the verbose name as the description - lines.append(u':param %s: %s' % (field.attname, verbose_name)) + lines.append(':param {}: {}'.format(field.attname, verbose_name)) # Add the field's type to the docstring if isinstance(field, models.ForeignKey): to = field.rel.to - lines.append(u':type %s: %s to :class:`~%s.%s`' % (field.attname, type(field).__name__, to.__module__, to.__name__)) + lines.append(':type {}: {} to :class:`~{}.{}`'.format(field.attname, type(field).__name__, to.__module__, to.__name__)) else: - lines.append(u':type %s: %s' % (field.attname, type(field).__name__)) + lines.append(':type {}: {}'.format(field.attname, type(field).__name__)) # Return the extended docstring return lines diff --git a/setup.py b/setup.py index d6e4625..2460dc0 100755 --- a/setup.py +++ b/setup.py @@ -27,24 +27,25 @@ setup( extras_require={ 'gmail-oauth2': gmail_oauth2_require }, + python_requires=">=3", classifiers=[ 'Framework :: Django', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Framework :: Django', - 'Framework :: Django :: 1.7', - 'Framework :: Django :: 1.8', - 'Framework :: Django :: 1.9', - 'Framework :: Django :: 1.10', 'Framework :: Django :: 1.11', + 'Framework :: Django :: 2.0', + 'Framework :: Django :: 2.1', + 'Framework :: Django :: 2.2', + 'Framework :: Django :: 3.0', 'Programming Language :: Python', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Topic :: Communications :: Email', 'Topic :: Communications :: Email :: Post-Office', 'Topic :: Communications :: Email :: Post-Office :: IMAP', diff --git a/tox.ini b/tox.ini index c7d6a2b..2b22134 100644 --- a/tox.ini +++ b/tox.ini @@ -2,29 +2,25 @@ # sort by django version, next by python version envlist= flake8 - py{27,34}-django17 - py{34,35}-django18 - py{27,34,35}-django19 - py{27,34,35}-django110 - py{27,34,35,36}-django111 - py{34,35,36}-django20 + py{35,36}-django111 + py{35,36}-django20 + py{35,36,37}-django21 + py{35,36,37}-django22 + py{36,37,38}-django30 [testenv] passenv=EMAIL_IMAP_SERVER EMAIL_ACCOUNT EMAIL_PASSWORD EMAIL_SMTP_SERVER deps= - django17: django>=1.7,<1.8 - django18: django>=1.8,<1.9 - django19: django>=1.9,<1.10 - django110: django>=1.10,<1.11 - django111: django>=1.11,<2.0 - django20: django>=2.0,<2.1 + django111: django==1.11.* + django20: django==2.0.* + django21: django==2.0.* + django22: django==2.0.* + django30: django==3.0b1 -r{toxinidir}/test_requirements.txt sitepackages=False commands= - django110: python {toxinidir}/manage.py makemigrations --check --dry-run - django111: python {toxinidir}/manage.py makemigrations --check --dry-run - django20: python {toxinidir}/manage.py makemigrations --check --dry-run - python manage.py test -v2 {posargs} + python {toxinidir}/manage.py makemigrations --check --dry-run + python -Wd manage.py test -v2 {posargs} [testenv:flake8] deps=flake8