Changeset 91:cd7e6ad6d118

Show
Ignore:
Timestamp:
28/12/09 18:37:09 (2 years ago)
Author:
msmits@…
Branch:
default
Message:

Backslash escaped double quotes in folder names now handled correctly

Also extracted the common code for list_folders and
list_sub_folders. The tests act on that directly.

Location:
imapclient
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • imapclient/imapclient.py

    r90 r91  
    6464 
    6565    re_sep = re.compile('^\(\("[^"]*" "([^"]+)"\)\)') 
    66     re_folder = re.compile('\([^)]*\) "[^"]+" "?([^"]+)"?') 
     66#     re_folder = re.compile('\([^)]*\) "[^"]+" "?([^"]+)"?') 
     67    re_folder = re.compile(r'\([^)]*\) "[^"]+" (?P<qqq>"?)(?P<folder>.+)(?P=qqq)') 
    6768    re_status = re.compile(r'^\s*"?(?P<folder>[^"]+)"?\s+' 
    6869                           r'\((?P<status_items>.*)\)$') 
     
    160161        typ, data = self._imap.list(directory, pattern) 
    161162        self._checkok('list', typ, data) 
    162  
     163        return self._proc_folder_list(data) 
     164 
     165 
     166    def list_sub_folders(self, directory="", pattern="*"): 
     167        """Get a listing of subscribed folders on the server. 
     168 
     169        The default behaviour (no args) will list all subscribed folders for the 
     170        logged in user. 
     171 
     172        @param directory: The base directory to look for folders from. 
     173        @param pattern: A pattern to match against folder names. Only folder 
     174            names matching this pattern will be returned. Wildcards accepted. 
     175        @return: A list of folder names. As per the return of list_folders(). 
     176        """ 
     177        typ, data = self._imap.lsub(directory, pattern) 
     178        self._checkok('lsub', typ, data) 
     179        return self._proc_folder_list(data) 
     180 
     181 
     182    def _proc_folder_list(self, folder_data): 
    163183        folders = [] 
    164         for line in data: 
     184        for line in folder_data: 
    165185            #TODO can the FetchParser code be adapted for use here? 
    166186            folder_text = None 
     
    170190                match = self.re_folder.match(line) 
    171191                if match: 
    172                     folder_text = match.group(1) 
     192                    folder_text = match.group('folder') 
     193                    folder_text = folder_text.replace(r'\"', '"') 
    173194            if folder_text is not None: 
    174195                folders.append(self._decode_folder_name(folder_text)) 
    175196        return folders 
    176  
    177  
    178     def list_sub_folders(self, directory="", pattern="*"): 
    179         """Get a listing of subscribed folders on the server. 
    180  
    181         The default behaviour (no args) will list all subscribed folders for the 
    182         logged in user. 
    183  
    184         @param directory: The base directory to look for folders from. 
    185         @param pattern: A pattern to match against folder names. Only folder 
    186             names matching this pattern will be returned. Wildcards accepted. 
    187         @return: A list of folder names. As per the return of list_folders(). 
    188         """ 
    189         typ, data = self._imap.lsub(directory, pattern) 
    190         self._checkok('lsub', typ, data) 
    191  
    192         folders = [] 
    193         for line in data: 
    194             if line: 
    195                 m = self.re_folder.match(line) 
    196                 if m: 
    197                     folders.append(self._decode_folder_name(m.group(1))) 
    198         return folders 
    199  
     197         
    200198 
    201199    def select_folder(self, folder): 
  • imapclient/test/test_IMAPClient.py

    r87 r91  
    66from imapclient.fixed_offset import FixedOffset 
    77from imapclient.imapclient import datetime_to_imap 
    8 from imapclient.test.mock import patch, sentinel 
     8from imapclient.test.mock import patch, sentinel, Mock 
    99from imapclient.test.testable_imapclient import TestableIMAPClient as IMAPClient 
    1010import unittest 
     
    1919class TestListFolders(IMAPClientTest): 
    2020 
    21     def test_simple(self): 
    22         self.client._imap.list.return_value = ('OK', ['(\\HasNoChildren) "/" "A"', 
    23                                                       '(\\HasNoChildren) "/" "Foo Bar"', 
    24                                                       ]) 
     21    def test_list_folders(self): 
     22        self.client._imap.list.return_value = ('OK', sentinel.folder_data) 
     23        self.client._proc_folder_list = Mock(return_value=sentinel.folder_list) 
    2524 
    2625        folders = self.client.list_folders(sentinel.dir, sentinel.pattern) 
    2726 
    2827        self.assert_(self.client._imap.list.call_args == ((sentinel.dir, sentinel.pattern), {})) 
    29         self.assert_(folders == ['A', 'Foo Bar']) 
     28        self.assert_(self.client._proc_folder_list.call_args == ((sentinel.folder_data,), {})) 
     29        self.assert_(folders is sentinel.folder_list) 
     30 
     31         
     32    def test_list_sub_folders(self): 
     33        self.client._imap.lsub.return_value = ('OK', sentinel.folder_data) 
     34        self.client._proc_folder_list = Mock(return_value=sentinel.folder_list) 
     35 
     36        folders = self.client.list_sub_folders(sentinel.dir, sentinel.pattern) 
     37 
     38        self.assert_(self.client._imap.lsub.call_args == ((sentinel.dir, sentinel.pattern), {})) 
     39        self.assert_(self.client._proc_folder_list.call_args == ((sentinel.folder_data,), {})) 
     40        self.assert_(folders is sentinel.folder_list) 
    3041 
    3142 
    32     def test_NO(self): 
     43    def test_list_folders_NO(self): 
    3344        self.client._imap.list.return_value = ('NO', ['badness']) 
    3445        self.assertRaises(IMAPClient.Error, self.client.list_folders) 
    3546 
    3647 
     48    def test_list_sub_folders_NO(self): 
     49        self.client._imap.list.return_value = ('NO', ['badness']) 
     50        self.assertRaises(IMAPClient.Error, self.client.list_folders) 
     51 
     52 
     53    def test_simple(self): 
     54        folders = self.client._proc_folder_list(['(\\HasNoChildren) "/" "A"', 
     55                                                 '(\\HasNoChildren) "/" "Foo Bar"', 
     56                                                 ]) 
     57        self.assert_(folders == ['A', 'Foo Bar']) 
     58 
     59 
     60 
     61 
    3762    def test_without_quotes(self): 
    38         self.client._imap.list.return_value = ('OK', ['(\\HasNoChildren) "/" A', 
    39                                                       '(\\HasNoChildren) "/" B', 
    40                                                       '(\\HasNoChildren) "/" C', 
    41                                                       ]) 
    42  
    43         folders = self.client.list_folders() 
     63        folders = self.client._proc_folder_list(['(\\HasNoChildren) "/" A', 
     64                                                 '(\\HasNoChildren) "/" B', 
     65                                                 '(\\HasNoChildren) "/" C', 
     66                                                 ]) 
    4467        self.assert_(folders == ['A', 'B', 'C'], 'got %r' % folders) 
    4568 
    4669 
    4770    def test_mixed(self): 
    48         self.client._imap.list.return_value = ('OK', ['(\\HasNoChildren) "/" Alpha', 
    49                                                       '(\\HasNoChildren) "/" "Foo Bar"', 
    50                                                       '(\\HasNoChildren) "/" C', 
    51                                                       ]) 
    52  
    53         folders = self.client.list_folders() 
     71        folders = self.client._proc_folder_list(['(\\HasNoChildren) "/" Alpha', 
     72                                                 '(\\HasNoChildren) "/" "Foo Bar"', 
     73                                                 '(\\HasNoChildren) "/" C', 
     74                                                 ]) 
    5475        self.assert_(folders == ['Alpha', 'Foo Bar', 'C'], 'got %r' % folders) 
    5576 
    5677 
    5778    def test_funky_characters(self): 
    58         self.client._imap.list.return_value = ('OK', 
    59                                                [('(\\NoInferiors \\UnMarked) "/" {5}', 'bang\xff'), 
    60                                                 '', 
    61                                                 '(\\HasNoChildren \\UnMarked) "/" "INBOX"']) 
     79        folders = self.client._proc_folder_list([('(\\NoInferiors \\UnMarked) "/" {5}', 'bang\xff'), 
     80                                                 '', 
     81                                                 '(\\HasNoChildren \\UnMarked) "/" "INBOX"']) 
     82        self.assert_(folders == ['bang\xff', 'INBOX'], 'got %r' % folders) 
    6283 
    63         folders = self.client.list_folders() 
    64         self.assert_(folders == ['bang\xff', 'INBOX'], 'got %r' % folders) 
     84 
     85    def test_escaped_quotes(self): 
     86        folders = self.client._proc_folder_list(['(\\HasNoChildren) "/" "Test \"Folder\""', 
     87                                                 '(\\HasNoChildren) "/" "Left\"Right"', 
     88                                                 ]) 
     89        self.assert_(folders == ['Test "Folder"', 'Left\"Right'], 'got %r' % folders) 
     90 
     91 
     92    def test_other_escaping(self): 
     93        self.fail("what other escapes are allowed?") 
    6594 
    6695