From 42acf9d64cce3d6cfa73b34459f548ae33389204 Mon Sep 17 00:00:00 2001
From: Kali Kaneko <kali@leap.se>
Date: Mon, 2 Mar 2015 11:49:35 -0400
Subject: [refactor] remove dead code in IMAP implementation

while updating the tests, I found that IMAPMessageCollection was not
actually being used: all the work is done in IMAPMailbox, using directly
the MessageCollection instance. So, this extra level of abstraction was
finally not used.

Releases: 0.9.0
---
 mail/src/leap/mail/imap/mailbox.py         |  11 +-
 mail/src/leap/mail/imap/messages.py        | 250 +----------------------------
 mail/src/leap/mail/imap/tests/test_imap.py | 130 ---------------
 3 files changed, 7 insertions(+), 384 deletions(-)

(limited to 'mail/src')

diff --git a/mail/src/leap/mail/imap/mailbox.py b/mail/src/leap/mail/imap/mailbox.py
index 2653ae4..91c6549 100644
--- a/mail/src/leap/mail/imap/mailbox.py
+++ b/mail/src/leap/mail/imap/mailbox.py
@@ -82,9 +82,9 @@ class IMAPMailbox(object):
     A Soledad-backed IMAP mailbox.
 
     Implements the high-level method needed for the Mailbox interfaces.
-    The low-level database methods are contained in IMAPMessageCollection
-    class, which we instantiate and make accessible in the `messages`
-    attribute.
+    The low-level database methods are contained in the generic
+    MessageCollection class. We receive an instance of it and it is made
+    accessible in the `collection` attribute.
     """
     implements(
         imap4.IMailbox,
@@ -107,14 +107,13 @@ class IMAPMailbox(object):
 
     def __init__(self, collection, rw=1):
         """
-        :param collection: instance of IMAPMessageCollection
-        :type collection: IMAPMessageCollection
+        :param collection: instance of MessageCollection
+        :type collection: MessageCollection
 
         :param rw: read-and-write flag for this mailbox
         :type rw: int
         """
         self.rw = rw
-
         self._uidvalidity = None
         self.collection = collection
 
diff --git a/mail/src/leap/mail/imap/messages.py b/mail/src/leap/mail/imap/messages.py
index b7bb6ee..02aac2e 100644
--- a/mail/src/leap/mail/imap/messages.py
+++ b/mail/src/leap/mail/imap/messages.py
@@ -15,23 +15,20 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
-IMAPMessage and IMAPMessageCollection.
+IMAPMessage implementation.
 """
 import logging
 from twisted.mail import imap4
 from twisted.internet import defer
 from zope.interface import implements
 
-from leap.common.check import leap_assert, leap_assert_type
 from leap.mail.utils import find_charset
 
 
 logger = logging.getLogger(__name__)
 
-# TODO ------------------------------------------------------------
-
+# TODO
 # [ ] Add ref to incoming message during add_msg.
-# [ ] Delete incoming mail only after successful write.
 
 
 class IMAPMessage(object):
@@ -251,246 +248,3 @@ def _format_headers(headers, negate, *names):
         if cond(key):
             _headers[key] = value
     return _headers
-
-
-class IMAPMessageCollection(object):
-    """
-    A collection of messages, surprisingly.
-
-    It is tied to a selected mailbox name that is passed to its constructor.
-    Implements a filter query over the messages contained in a soledad
-    database.
-    """
-
-    messageklass = IMAPMessage
-
-    # TODO
-    # [ ] Add RECENT flags docs to mailbox-doc attributes (list-of-uids)
-    # [ ] move Query for all the headers documents to Collection
-
-    # TODO this should be able to produce a MessageSet methinks
-    # TODO --- reimplement, review and prune documentation below.
-
-    FLAGS_DOC = "FLAGS"
-    HEADERS_DOC = "HEADERS"
-    CONTENT_DOC = "CONTENT"
-    """
-    RECENT_DOC is a document that stores a list of the UIDs
-    with the recent flag for this mailbox. It deserves a special treatment
-    because:
-    (1) it cannot be set by the user
-    (2) it's a flag that we set inmediately after a fetch, which is quite
-        often.
-    (3) we need to be able to set/unset it in batches without doing a single
-        write for each element in the sequence.
-    """
-    RECENT_DOC = "RECENT"
-    """
-    HDOCS_SET_DOC is a document that stores a set of the Document-IDs
-    (the u1db index) for all the headers documents for a given mailbox.
-    We use it to prefetch massively all the headers for a mailbox.
-    This is the second massive query, after fetching all the FLAGS,  that
-    a typical IMAP MUA will do in a case where we do not have local disk cache.
-    """
-    HDOCS_SET_DOC = "HDOCS_SET"
-
-    def __init__(self, collection):
-        """
-        Constructor for IMAPMessageCollection.
-
-        :param collection: an instance of a MessageCollection
-        :type collection: MessageCollection
-        """
-        leap_assert(
-            collection.is_mailbox_collection(),
-            "Need a mailbox name to initialize")
-        mbox_name = collection.mbox_name
-        leap_assert(mbox_name.strip() != "", "mbox cannot be blank space")
-        leap_assert(isinstance(mbox_name, (str, unicode)),
-                    "mbox needs to be a string")
-        self.collection = collection
-
-        # XXX this has to be done in IMAPAccount
-        # (Where the collection must be instantiated and passed to us)
-        # self.mbox = normalize_mailbox(mbox)
-
-    @property
-    def mbox_name(self):
-        """
-        Return the string that identifies this mailbox.
-        """
-        return self.collection.mbox_name
-
-    def add_msg(self, raw, flags=None, date=None):
-        """
-        Creates a new message document.
-
-        :param raw: the raw message
-        :type raw: str
-
-        :param flags: flags
-        :type flags: list
-
-        :param date: the received date for the message
-        :type date: str
-
-        :return: a deferred that will be fired with the message
-                 uid when the adding succeed.
-        :rtype: deferred
-        """
-        if flags is None:
-            flags = tuple()
-        leap_assert_type(flags, tuple)
-        return self.collection.add_msg(raw, flags, date)
-
-    def get_msg_by_uid(self, uid, absolute=True):
-        """
-        Retrieves a IMAPMessage by UID.
-        This is used primarity in the Mailbox fetch and store methods.
-
-        :param uid: the message uid to query by
-        :type uid: int
-
-        :rtype: IMAPMessage
-        """
-        def make_imap_msg(msg):
-            kls = self.messageklass
-            # TODO --- remove ref to collection
-            return kls(msg, self.collection)
-
-        d = self.collection.get_msg_by_uid(uid, absolute=absolute)
-        d.addCalback(make_imap_msg)
-        return d
-
-
-    # TODO -- move this to collection too
-    # Used for the Search (Drafts) queries?
-    def _get_uid_from_msgid(self, msgid):
-        """
-        Return a UID for a given message-id.
-
-        It first gets the headers-doc for that msg-id, and
-        it found it queries the flags doc for the current mailbox
-        for the matching content-hash.
-
-        :return: A UID, or None
-        """
-        return self._get_uid_from_msgidCb(msgid)
-
-    # TODO handle deferreds
-    def set_flags(self, messages, flags, mode):
-        """
-        Set flags for a sequence of messages.
-
-        :param mbox: the mbox this message belongs to
-        :type mbox: str or unicode
-        :param messages: the messages to iterate through
-        :type messages: sequence
-        :flags: the flags to be set
-        :type flags: tuple
-        :param mode: the mode for setting. 1 is append, -1 is remove, 0 set.
-        :type mode: int
-        :param observer: a deferred that will be called with the dictionary
-                         mapping UIDs to flags after the operation has been
-                         done.
-        :type observer: deferred
-        """
-        getmsg = self.get_msg_by_uid
-
-        def set_flags(uid, flags, mode):
-            msg = getmsg(uid)
-            if msg is not None:
-                # XXX IMAPMessage needs access to the collection
-                # to be able to set flags. Better if we make use
-                # of collection... here.
-                return uid, msg.setFlags(flags, mode)
-
-        setted_flags = [set_flags(uid, flags, mode) for uid in messages]
-        result = dict(filter(None, setted_flags))
-        # XXX return gatherResults or something
-        return result
-
-    def count(self):
-        """
-        Return the count of messages for this mailbox.
-
-        :rtype: int
-        """
-        return self.collection.count()
-
-    # headers query
-
-    def all_headers(self):
-        """
-        Return a dict with all the header documents for this
-        mailbox.
-
-        :rtype: dict
-        """
-        # Use self.collection.mbox_indexer
-        # and derive all the doc_ids for the hdocs
-        raise NotImplementedError()
-
-    # unseen messages
-
-    def unseen_iter(self):
-        """
-        Get an iterator for the message UIDs with no `seen` flag
-        for this mailbox.
-
-        :return: iterator through unseen message doc UIDs
-        :rtype: iterable
-        """
-        raise NotImplementedError()
-
-    def count_unseen(self):
-        """
-        Count all messages with the `Unseen` flag.
-
-        :returns: count
-        :rtype: int
-        """
-        return len(list(self.unseen_iter()))
-
-    def get_unseen(self):
-        """
-        Get all messages with the `Unseen` flag
-
-        :returns: a list of LeapMessages
-        :rtype: list
-        """
-        raise NotImplementedError()
-        #return [self.messageklass(self._soledad, doc_id, self.mbox)
-                #for doc_id in self.unseen_iter()]
-
-    # recent messages
-
-    def count_recent(self):
-        """
-        Count all messages with the `Recent` flag.
-        It just retrieves the length of the recent_flags set,
-        which is stored in a specific type of document for
-        this collection.
-
-        :returns: count
-        :rtype: int
-        """
-        raise NotImplementedError()
-
-    # magic
-
-    def __len__(self):
-        """
-        Returns the number of messages on this mailbox.
-        :rtype: int
-        """
-        return self.count()
-
-    def __repr__(self):
-        """
-        Representation string for this object.
-        """
-        return u"<IMAPMessageCollection: mbox '%s' (%s)>" % (
-            self.mbox_name, self.count())
-
-    # TODO implement __iter__ ?
diff --git a/mail/src/leap/mail/imap/tests/test_imap.py b/mail/src/leap/mail/imap/tests/test_imap.py
index 802bc9d..fbe02d4 100644
--- a/mail/src/leap/mail/imap/tests/test_imap.py
+++ b/mail/src/leap/mail/imap/tests/test_imap.py
@@ -38,7 +38,6 @@ from twisted.python import failure
 from twisted import cred
 
 from leap.mail.imap.mailbox import IMAPMailbox
-from leap.mail.imap.messages import IMAPMessageCollection
 from leap.mail.imap.tests.utils import IMAP4HelperMixin
 
 
@@ -70,139 +69,10 @@ class TestRealm:
     def requestAvatar(self, avatarId, mind, *interfaces):
         return imap4.IAccount, self.theAccount, lambda: None
 
-
 #
 # TestCases
 #
 
-# TODO rename to IMAPMessageCollection
-class MessageCollectionTestCase(IMAP4HelperMixin):
-    """
-    Tests for the MessageCollection class
-    """
-    count = 0
-
-    def setUp(self):
-        """
-        setUp method for each test
-        We override mixin method since we are only testing
-        MessageCollection interface in this particular TestCase
-        """
-        # FIXME -- return deferred
-        super(MessageCollectionTestCase, self).setUp()
-
-        # FIXME --- update initialization
-        self.messages = IMAPMessageCollection(
-            "testmbox%s" % (self.count,), self._soledad)
-        MessageCollectionTestCase.count += 1
-
-    def tearDown(self):
-        """
-        tearDown method for each test
-        """
-        del self.messages
-
-    def testEmptyMessage(self):
-        """
-        Test empty message and collection
-        """
-        em = self.messages._get_empty_doc()
-        self.assertEqual(
-            em,
-            {
-                "chash": '',
-                "deleted": False,
-                "flags": [],
-                "mbox": "inbox",
-                "seen": False,
-                "multi": False,
-                "size": 0,
-                "type": "flags",
-                "uid": 1,
-            })
-        self.assertEqual(self.messages.count(), 0)
-
-    def testMultipleAdd(self):
-        """
-        Add multiple messages
-        """
-        mc = self.messages
-        self.assertEqual(self.messages.count(), 0)
-
-        def add_first():
-            d = defer.gatherResults([
-                mc.add_msg('Stuff 1', subject="test1"),
-                mc.add_msg('Stuff 2', subject="test2"),
-                mc.add_msg('Stuff 3', subject="test3"),
-                mc.add_msg('Stuff 4', subject="test4")])
-            return d
-
-        def add_second(result):
-            d = defer.gatherResults([
-                mc.add_msg('Stuff 5', subject="test5"),
-                mc.add_msg('Stuff 6', subject="test6"),
-                mc.add_msg('Stuff 7', subject="test7")])
-            return d
-
-        def check_second(result):
-            return self.assertEqual(mc.count(), 7)
-
-        d1 = add_first()
-        d1.addCallback(add_second)
-        d1.addCallback(check_second)
-
-    def testRecentCount(self):
-        """
-        Test the recent count
-        """
-        mc = self.messages
-        countrecent = mc.count_recent
-        eq = self.assertEqual
-
-        self.assertEqual(countrecent(), 0)
-
-        d = mc.add_msg('Stuff', subject="test1")
-        # For the semantics defined in the RFC, we auto-add the
-        # recent flag by default.
-
-        def add2(_):
-            return mc.add_msg('Stuff', subject="test2",
-                              flags=('\\Deleted',))
-
-        def add3(_):
-            return mc.add_msg('Stuff', subject="test3",
-                              flags=('\\Recent',))
-
-        def add4(_):
-            return mc.add_msg('Stuff', subject="test4",
-                              flags=('\\Deleted', '\\Recent'))
-
-        d.addCallback(lambda r: eq(countrecent(), 1))
-        d.addCallback(add2)
-        d.addCallback(lambda r: eq(countrecent(), 2))
-        d.addCallback(add3)
-        d.addCallback(lambda r: eq(countrecent(), 3))
-        d.addCallback(add4)
-        d.addCallback(lambda r: eq(countrecent(), 4))
-
-    def testFilterByMailbox(self):
-        """
-        Test that queries filter by selected mailbox
-        """
-        mc = self.messages
-        self.assertEqual(self.messages.count(), 0)
-
-        def add_1():
-            d1 = mc.add_msg('msg 1', subject="test1")
-            d2 = mc.add_msg('msg 2', subject="test2")
-            d3 = mc.add_msg('msg 3', subject="test3")
-            d = defer.gatherResults([d1, d2, d3])
-            return d
-
-        add_1().addCallback(lambda ignored: self.assertEqual(
-                            mc.count(), 3))
-
-
 # DEBUG ---
 #from twisted.internet.base import DelayedCall
 #DelayedCall.debug = True
-- 
cgit v1.2.3