aboutsummaryrefslogtreecommitdiff
path: root/ctec/imap_response.py
blob: 23ca94396c149dda0d11513c80155df9b6c41d6d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
45
46
# this should really be in the stdlib imo
from dataclasses import dataclass
from typing import List as ListT, Union, ClassVar

from .parse_utils import ParseResult, Parser, take_while1, tag, delimited, take_n, alt, map_parser, separated_many0, separated_triple, all_consuming

__all__ = [
    'List',
]

atom: Parser[str] = take_while1(lambda c: c.isalnum() or c in r'\/')

number: Parser[int] = map_parser(take_while1(str.isnumeric), int)

def literal_string(text: str) -> ParseResult[str]:
    delimited_result = delimited(tag('{'), number, tag('}\r\n'))(text)
    if delimited_result is None:
        return None
    count, text = delimited_result
    return take_n(count)(text)

quoted_string: Parser[str] = delimited(tag('"'), take_while1(lambda c: c not in '\r\n"'), tag('"'))

string: Parser[str] = alt(literal_string, quoted_string)

astring: Parser[str] = alt(atom, string)

data_item: Parser[Union[int, str]] = alt(number, atom, string)

ParensList = ListT[Union[int, str, 'ParensList']]
def parens_list(text: str) -> ParseResult[ParensList]:
    return delimited(tag('('), separated_many0(alt(data_item, parens_list), tag(' ')), tag(')'))(text)

@dataclass
class List:
    attributes: ListT[str]
    delimiter: str
    name: str

    @staticmethod
    def parse(response: bytes) -> 'List':
        response = response.decode('ASCII')
        print(response)
        parser = all_consuming(separated_triple(parens_list, tag(' '), string, tag(' '), astring), debug=True)
        (attributes, delimiter, name), _ = parser(response)
        return List(attributes, delimiter, name)