| 120 | | EOF = object() |
| 121 | | |
| 122 | | # imaplib has poor handling of 'literals' - it both fails to remove the |
| 123 | | # {size} marker, and fails to keep responses grouped into the same logical |
| 124 | | # 'line'. What we end up with is a list of response 'records', where each |
| 125 | | # record is either a simple string, or tuple of (str_with_lit, literal) - |
| 126 | | # where str_with_lit is a string with the {xxx} marker at its end. Note |
| 127 | | # that each elt of this list does *not* correspond 1:1 with the untagged |
| 128 | | # responses. |
| 129 | | # (http://bugs.python.org/issue5045 also has comments about this) |
| 130 | | # So: we have a special file-like object for each of these records. When |
| 131 | | # a string literal is finally processed, we peek into this file-like object |
| 132 | | # to grab the literal. |
| 133 | | class LiteralHandlingIter: |
| 134 | | def __init__(self, lexer, resp_record): |
| 135 | | self.pushed = None |
| 136 | | self.lexer = lexer |
| 137 | | if isinstance(resp_record, tuple): |
| 138 | | # A 'record' with a string which includes a literal marker, and |
| 139 | | # the literal itself. |
| 140 | | src_text, self.literal = resp_record |
| 141 | | assert src_text.endswith("}"), src_text |
| 142 | | self.src_text = src_text |
| 143 | | else: |
| 144 | | # just a line with no literals. |
| 145 | | self.src_text = resp_record |
| 146 | | self.literal = None |
| 147 | | |
| 148 | | def __iter__(self): |
| 149 | | return iter(self.src_text) |
| 150 | | |
| 151 | | |
| 152 | | class ResponseTokeniser(object): |
| 153 | | def __init__(self, resp_chunks): |
| 154 | | # initialize the lexer with all the chunks we read. |
| 155 | | sources = (LiteralHandlingIter(lex, chunk) for chunk in resp_chunks) |
| 156 | | lex = response_lexer.Lexer(sources) |
| 157 | | self.tok_src = iter(lex) |
| 158 | | self.lex = lex |
| 159 | | |
| 160 | | def __iter__(self): |
| 161 | | return self.tok_src |
| 162 | | |
| 163 | | |