diff options
author | Patrick Maia <pmaia@thoughtworks.com> | 2014-09-17 02:02:28 -0300 |
---|---|---|
committer | Patrick Maia <pmaia@thoughtworks.com> | 2014-09-17 13:53:25 -0300 |
commit | 95b0e2e6f834804630bf9d091b156ac68ff20583 (patch) | |
tree | 9bff8ebac2134cf23fd2bcd92f1a9500d8dd5ebf /service | |
parent | c272f64293bb0157eb7eb1ebba899935f8ed2c3a (diff) |
74 - moves move_to_trash logic to PixelatedMailboxes and adds some tests
Diffstat (limited to 'service')
-rw-r--r-- | service/pixelated/adapter/mail_service.py | 11 | ||||
-rw-r--r-- | service/pixelated/adapter/pixelated_mail.py | 42 | ||||
-rw-r--r-- | service/pixelated/adapter/pixelated_mailbox.py | 19 | ||||
-rw-r--r-- | service/pixelated/adapter/pixelated_mailboxes.py | 11 | ||||
-rw-r--r-- | service/pixelated/user_agent.py | 2 | ||||
-rw-r--r-- | service/test/adapter/mail_service_test.py | 8 | ||||
-rw-r--r-- | service/test/adapter/pixelated_mail_test.py | 33 | ||||
-rw-r--r-- | service/test/adapter/pixelated_mailbox_test.py | 21 | ||||
-rw-r--r-- | service/test/adapter/test_tag_service.py | 4 |
9 files changed, 92 insertions, 59 deletions
diff --git a/service/pixelated/adapter/mail_service.py b/service/pixelated/adapter/mail_service.py index 5f651187..6906c431 100644 --- a/service/pixelated/adapter/mail_service.py +++ b/service/pixelated/adapter/mail_service.py @@ -14,7 +14,6 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. from pixelated.adapter.tag_service import TagService -from pixelated.support.id_gen import gen_pixelated_uid class MailService: @@ -38,9 +37,7 @@ class MailService: def update_tags(self, mail_id, new_tags): mail = self.mail(mail_id) - added, removed = mail.update_tags(set(new_tags)) - self.tag_service.notify_tags_updated(added, removed, mail_id) - return new_tags + return mail.update_tags(set(new_tags)) def mail(self, mail_id): return self.mailboxes.mail(mail_id) @@ -73,10 +70,8 @@ class MailService: raise NotImplementedError() def delete_mail(self, mail_id): - mail = self.mailboxes.mail(mail_id) - new_mailbox_tag, old_mailbox_tag = mail.move_to(self.mailboxes.trash()) - self.tag_service.notify_tags_updated([], [old_mailbox_tag], mail_id) - self.tag_service.notify_tags_updated([new_mailbox_tag], [], None) + _mail = self.mailboxes.mail(mail_id) + return self.mailboxes.move_to_trash(_mail) def save_draft(self, draft): raise NotImplementedError() diff --git a/service/pixelated/adapter/pixelated_mail.py b/service/pixelated/adapter/pixelated_mail.py index c732f5a0..af82eb7f 100644 --- a/service/pixelated/adapter/pixelated_mail.py +++ b/service/pixelated/adapter/pixelated_mail.py @@ -15,6 +15,7 @@ # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. from pixelated.adapter.status import Status from pixelated.support.id_gen import gen_pixelated_uid +from pixelated.adapter.tag_service import TagService import json import pixelated.support.date import dateutil.parser as dateparser @@ -32,10 +33,12 @@ class PixelatedMail: self.tags = [] @staticmethod - def from_leap_mail(leap_mail, leap_mailbox=None): + def from_leap_mail(leap_mail, tag_service=TagService.get_instance()): mail = PixelatedMail() + mail.tag_service = tag_service mail.leap_mail = leap_mail - mail.leap_mailbox = leap_mailbox + mail.mailbox_name = leap_mail._mbox + mail.ident = gen_pixelated_uid(leap_mail._mbox, leap_mail.getUID()) mail.body = leap_mail.bdoc.content['raw'] mail.headers = mail._extract_headers() mail.headers['date'] = PixelatedMail._get_date(mail.headers) @@ -48,10 +51,6 @@ class PixelatedMail: def is_recent(self): return Status('recent') in self.status - @property - def ident(self): - return gen_pixelated_uid(self.leap_mailbox.mbox, self.leap_mail.getUID()) - def set_from(self, _from): self.headers['from'] = [_from] @@ -87,13 +86,17 @@ class PixelatedMail: return set(tags) return set(json.loads(tags)) + def remove_all_tags(self): + self.update_tags(set([])) + def update_tags(self, tags): old_tags = self.tags self.tags = tags removed = old_tags.difference(tags) added = tags.difference(old_tags) self._persist_mail_tags(tags) - return added, removed + self.tag_service.notify_tags_updated(added, removed, self.ident) + return self.tags def mark_as_read(self): self.leap_mail.setFlags((Status.PixelatedStatus.SEEN,), 1) @@ -113,27 +116,12 @@ class PixelatedMail: def has_tag(self, tag): return tag in self.tags - def move_to(self, destiny_mailbox): - new_leap_mail = destiny_mailbox.add_mail(self) - self._delete_from_leap_mailbox() - old_mailbox_tag = self.leap_mailbox.mbox.lower() - self._update_leap_references(destiny_mailbox.leap_mailbox, new_leap_mail) - - return destiny_mailbox.mailbox_tag, old_mailbox_tag - - def _delete_from_leap_mailbox(self): - self.leap_mail.setFlags((Status.PixelatedStatus.DELETED,), 1) - self.leap_mailbox.expunge() - - def _update_leap_references(self, new_leap_mailbox, new_leap_mail): - self.leap_mailbox = new_leap_mailbox - self.leap_mail = new_leap_mail - def raw_message(self): - raw_message = ''.join("%s: %s\n" % (key, value) for key, value in self.leap_mail.hdoc.content['headers'].items()) - raw_message += '\n\n' - raw_message += self.leap_mail.bdoc.content['raw'] - return raw_message + mime = MIMEMultipart() + for key, value in self.leap_mail.hdoc.content['headers'].items(): + mime[key] = value + mime.attach(MIMEText(self.leap_mail.bdoc.content['raw'], 'plain')) + return mime.as_string() def as_dict(self): statuses = [status.name for status in self.status] diff --git a/service/pixelated/adapter/pixelated_mailbox.py b/service/pixelated/adapter/pixelated_mailbox.py index 7d2a1fa5..a6dc4116 100644 --- a/service/pixelated/adapter/pixelated_mailbox.py +++ b/service/pixelated/adapter/pixelated_mailbox.py @@ -14,7 +14,9 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. +from pixelated.support.id_gen import gen_pixelated_uid from pixelated.adapter.pixelated_mail import PixelatedMail +from pixelated.adapter.status import Status from pixelated.adapter.tag_service import TagService from crochet import wait_for @@ -45,7 +47,7 @@ class PixelatedMailbox: result = [] for mail in mails: mail._collection = mails - pixelated_mail = PixelatedMail.from_leap_mail(mail, self.leap_mailbox) + pixelated_mail = PixelatedMail.from_leap_mail(mail) self.add_mailbox_tag_if_not_there(pixelated_mail) result.append(pixelated_mail) return result @@ -60,13 +62,18 @@ class PixelatedMailbox: if message.ident == mail_id: return message - def add_mail(self, mail): - original_flags = mail.leap_mail.getFlags() - self.leap_mailbox.addMessage(mail.raw_message(), original_flags) + def add(self, mail): + leap_id = self._do_add_async(mail) + new_id = gen_pixelated_uid(self.leap_mailbox.mbox, leap_id) + return new_id @wait_for(timeout=3.0) - def add(self, mail): - return self.leap_mailbox.messages.add_msg(mail.to_smtp_format()) + def _do_add_async(self, mail): + return self.leap_mailbox.messages.add_msg(mail.raw_message()) + + def remove(self, mail): + mail.leap_mail.setFlags((Status.PixelatedStatus.DELETED,), 1) + self.leap_mailbox.expunge() @classmethod def create(cls, account, mailbox_name='INBOX'): diff --git a/service/pixelated/adapter/pixelated_mailboxes.py b/service/pixelated/adapter/pixelated_mailboxes.py index b5cac602..aa9015e5 100644 --- a/service/pixelated/adapter/pixelated_mailboxes.py +++ b/service/pixelated/adapter/pixelated_mailboxes.py @@ -7,6 +7,7 @@ class PixelatedMailBoxes(): self.account = account def _create_or_get(self, mailbox_name): + mailbox_name = mailbox_name.upper() if mailbox_name not in self.account.mailboxes: self.account.addMailbox(mailbox_name) return PixelatedMailbox.create(self.account, mailbox_name) @@ -35,11 +36,15 @@ class PixelatedMailBoxes(): mail.set_ident(drafts.mailbox_name, draft_id) return mail + def move_to_trash(self, mail): + mail.remove_all_tags() + origin_mailbox = mail.mailbox_name + + self._create_or_get(origin_mailbox).remove(mail) + return self.trash().add(mail) + def mail(self, mail_id): for mailbox in self.mailboxes: mail = mailbox.mail(mail_id) if mail: return mail - - def mailbox_exists(self, name): - return name.upper() in map(lambda x: x.upper(), self.account.mailboxes) diff --git a/service/pixelated/user_agent.py b/service/pixelated/user_agent.py index 54643255..c386c6e6 100644 --- a/service/pixelated/user_agent.py +++ b/service/pixelated/user_agent.py @@ -128,7 +128,7 @@ def mail(mail_id): def mail_tags(mail_id): new_tags = map(lambda tag: tag.lower(), request.get_json()['newtags']) tags = mail_service.update_tags(mail_id, new_tags) - return respond_json(tags) + return respond_json(list(tags)) @app.route('/mail/<mail_id>/read', methods=['POST']) diff --git a/service/test/adapter/mail_service_test.py b/service/test/adapter/mail_service_test.py index 782e891a..517368e2 100644 --- a/service/test/adapter/mail_service_test.py +++ b/service/test/adapter/mail_service_test.py @@ -45,3 +45,11 @@ class TestMailService(unittest.TestCase): self.mail_service.create_draft(mail) verify(self.mailboxes).add_draft(mail) + + def test_delete_mail(self): + mail = mock() + when(self.mailboxes).mail(any()).thenReturn(mail) + + self.mail_service.delete_mail(1) + + verify(self.mailboxes).move_to_trash(mail) diff --git a/service/test/adapter/pixelated_mail_test.py b/service/test/adapter/pixelated_mail_test.py index 4292883c..3ba5e659 100644 --- a/service/test/adapter/pixelated_mail_test.py +++ b/service/test/adapter/pixelated_mail_test.py @@ -14,10 +14,15 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. import unittest +import os import pixelated.support.date -from pixelated.adapter.pixelated_mail import PixelatedMail import test_helper +from pixelated.adapter.pixelated_mail import PixelatedMail +from pixelated.adapter.tag_service import TagService +from pixelated.adapter.tag_index import TagIndex +from pixelated.adapter.tag import Tag +from mock import Mock class TestPixelatedMail(unittest.TestCase): @@ -72,11 +77,10 @@ class TestPixelatedMail(unittest.TestCase): self.assertEqual('date now', mail.headers['date']) - def test_update_tags_return_a_set_for_added_tags_and_a_set_for_removed_ones(self): - pixelated_mail = PixelatedMail.from_leap_mail(test_helper.leap_mail(extra_headers={'X-tags': '["custom_1", "custom_2"]'})) - added, removed = pixelated_mail.update_tags(set(['custom_1', 'custom_3'])) - self.assertEquals(set(['custom_3']), added) - self.assertEquals(set(['custom_2']), removed) + def test_update_tags_return_a_set_with_the_current_tags(self): + pixelated_mail = PixelatedMail.from_leap_mail(test_helper.leap_mail(extra_headers={'X-tags': '["custom_1", "custom_2"]'}), Mock()) + current_tags = pixelated_mail.update_tags(set(['custom_1', 'custom_3'])) + self.assertEquals(set(['custom_3', 'custom_1']), current_tags) def test_to_mime_multipart(self): pixelated.support.date.iso_now = lambda: 'date now' @@ -126,3 +130,20 @@ class TestPixelatedMail(unittest.TestCase): mail.mark_as_not_recent() self.assertEquals(mail.leap_mail.setFlags.call_args[0], (('\\Recent',), -1)) + + def test_remove_all_tags(self): + mail = PixelatedMail.from_leap_mail(test_helper.leap_mail(extra_headers={'X-Tags': '["skinka", "altoids"]'}), Mock()) + self.assertEquals(set(['skinka', 'altoids']), mail.tags) + + mail.remove_all_tags() + self.assertEquals(set([]), mail.tags) + + def test_update_tags_notifies_tag_service(self): + db_path = '/tmp/test_update_tags_notifies_tag_service' + tag_service = TagService(TagIndex(db_path)) + mail = PixelatedMail.from_leap_mail(test_helper.leap_mail(), tag_service) + + mail.update_tags(set(['new_tag'])) + self.assertIn(Tag('new_tag'), tag_service.all_tags()) + + os.remove(db_path + '.db') diff --git a/service/test/adapter/pixelated_mailbox_test.py b/service/test/adapter/pixelated_mailbox_test.py index b4ddb32d..ac9d3f34 100644 --- a/service/test/adapter/pixelated_mailbox_test.py +++ b/service/test/adapter/pixelated_mailbox_test.py @@ -14,10 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. import unittest -from mockito import * -import leap -import os from pixelated.adapter.pixelated_mail import PixelatedMail +from pixelated.adapter.status import Status import test_helper from pixelated.adapter.pixelated_mailbox import PixelatedMailbox from mockito import * @@ -42,13 +40,24 @@ class TestPixelatedMailbox(unittest.TestCase): self.assertNotIn('spam', mailbox.mails()[0].tags) def test_add_message_to_mailbox(self): - PixelatedMail.from_email_address = 'pixel@ted.org' mail = PixelatedMail.from_dict(test_helper.mail_dict()) - mail.to_smtp_format = lambda: 'the mail in smtp format' + mail.raw_message = lambda: 'the mail in smtp format' leap_mailbox_messages = mock() self.mailbox.leap_mailbox.messages = leap_mailbox_messages - self.mailbox.add.wrapped_function(self.mailbox, mail) + self.mailbox._do_add_async.wrapped_function(self.mailbox, mail) verify(leap_mailbox_messages).add_msg('the mail in smtp format') + + def test_remove_message_from_mailbox(self): + mail = PixelatedMail.from_dict(test_helper.mail_dict()) + mail.raw_message = lambda: 'the mail in smtp format' + + mail.leap_mail = mock() + self.mailbox.leap_mailbox = mock() + + self.mailbox.remove(mail) + + verify(mail.leap_mail).setFlags((Status.PixelatedStatus.DELETED,), 1) + verify(self.mailbox.leap_mailbox).expunge() diff --git a/service/test/adapter/test_tag_service.py b/service/test/adapter/test_tag_service.py index b3a68c2b..027e6113 100644 --- a/service/test/adapter/test_tag_service.py +++ b/service/test/adapter/test_tag_service.py @@ -30,8 +30,8 @@ class TagServiceTest(unittest.TestCase): self.tag_service = TagService(tag_index=self.tag_index) def test_index_is_initialized_with_mail_tags_if_empty(self): - mail_one = PixelatedMail.from_leap_mail(test_helper.leap_mail(uid=0, extra_headers={'X-Tags': '["tag_1"]'}), test_helper.leap_mailbox()) - mail_two = PixelatedMail.from_leap_mail(test_helper.leap_mail(uid=1, extra_headers={'X-Tags': '["tag_2"]'}), test_helper.leap_mailbox()) + mail_one = PixelatedMail.from_leap_mail(test_helper.leap_mail(uid=0, extra_headers={'X-Tags': '["tag_1"]'})) + mail_two = PixelatedMail.from_leap_mail(test_helper.leap_mail(uid=1, extra_headers={'X-Tags': '["tag_2"]'})) mails = [mail_one, mail_two] self.tag_service.load_index(mails) |