Skip to content

Commit

Permalink
Merge pull request #11 from smkent/dev
Browse files Browse the repository at this point in the history
Add tests, organize methods and models
  • Loading branch information
smkent authored Feb 26, 2022
2 parents f5a42ea + 86dd5ff commit 5427093
Show file tree
Hide file tree
Showing 27 changed files with 776 additions and 288 deletions.
23 changes: 21 additions & 2 deletions jmapc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from . import errors, methods
import logging

from . import errors, methods, models
from .client import Client
from .errors import Error
from .models import (
Expand All @@ -8,14 +10,21 @@
EmailBodyPart,
EmailBodyValue,
EmailHeader,
EmailQueryFilter,
EmailQueryFilterCondition,
EmailQueryFilterOperator,
Identity,
ListOrRef,
Mailbox,
MailboxQueryFilter,
MailboxQueryFilterCondition,
MailboxQueryFilterOperator,
Operator,
StrOrRef,
Thread,
ThreadEmail,
)
from .ref import ResultReference
from .serializer import ListOrRef, StrOrRef

__all__ = [
"Client",
Expand All @@ -25,15 +34,25 @@
"EmailBodyPart",
"EmailBodyValue",
"EmailHeader",
"EmailQueryFilter",
"EmailQueryFilterCondition",
"EmailQueryFilterOperator",
"Error",
"Identity",
"ListOrRef",
"Mailbox",
"MailboxQueryFilter",
"MailboxQueryFilterCondition",
"MailboxQueryFilterOperator",
"Operator",
"ResultReference",
"StrOrRef",
"Thread",
"ThreadEmail",
"errors",
"methods",
"models",
]

# Set default logging handler to avoid "No handler found" warnings.
logging.getLogger(__name__).addHandler(logging.NullHandler())
7 changes: 5 additions & 2 deletions jmapc/client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import json
import logging
from typing import Any, Dict, List, Optional, Tuple, Type, Union, cast

import requests
Expand Down Expand Up @@ -61,7 +62,7 @@ def call_method(self, call: Method) -> Any:
using = list(set([constants.JMAP_URN_CORE]).union(call.using()))
result = self._api_call(
{
"using": using,
"using": sorted(using),
"methodCalls": [
[
call.name(),
Expand All @@ -85,7 +86,7 @@ def call_methods(self, calls: Union[list[Method], MethodList]) -> Any:
)
return self._api_call(
{
"using": using,
"using": sorted(using),
"methodCalls": [
[
c[1].name(),
Expand Down Expand Up @@ -113,11 +114,13 @@ def _parse_responses(self, data: dict[str, Any]) -> MethodResponseList:
return responses

def _api_call(self, call: Any) -> Any:
logging.debug(f"Sending JMAP request {json.dumps(call)}")
r = requests.post(
self.session.api_url,
auth=(self._user, self._password),
headers={"Content-Type": "application/json"},
data=json.dumps(call),
)
r.raise_for_status()
logging.debug(f"Received JMAP response {r.text}")
return self._parse_responses(r.json())
21 changes: 2 additions & 19 deletions jmapc/methods/__init__.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
from .base import Method, Response
from .core import CoreEcho, CoreEchoResponse
from .email import (
EmailGet,
EmailGetResponse,
EmailQuery,
EmailQueryFilter,
EmailQueryFilterCondition,
EmailQueryFilterOperator,
EmailQueryResponse,
)
from .email import EmailGet, EmailGetResponse, EmailQuery, EmailQueryResponse
from .identity import IdentityGet, IdentityGetResponse
from .mailbox import (
MailboxGet,
MailboxGetResponse,
MailboxQuery,
MailboxQueryFilter,
MailboxQueryFilterCondition,
MailboxQueryFilterOperator,
MailboxQueryResponse,
)
from .methods import Method, Response
from .thread import ThreadGet, ThreadGetResponse

__all__ = [
Expand All @@ -27,18 +16,12 @@
"EmailGet",
"EmailGetResponse",
"EmailQuery",
"EmailQueryFilter",
"EmailQueryFilterCondition",
"EmailQueryFilterOperator",
"EmailQueryResponse",
"IdentityGet",
"IdentityGetResponse",
"MailboxGet",
"MailboxGetResponse",
"MailboxQuery",
"MailboxQueryFilter",
"MailboxQueryFilterCondition",
"MailboxQueryFilterOperator",
"MailboxQueryResponse",
"Method",
"Response",
Expand Down
4 changes: 2 additions & 2 deletions jmapc/methods/methods.py → jmapc/methods/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from dataclasses import dataclass, field
from typing import List, Optional

from ..models import Comparator
from ..serializer import ListOrRef, Model
from ..models import Comparator, ListOrRef
from ..serializer import Model


@dataclass
Expand Down
2 changes: 1 addition & 1 deletion jmapc/methods/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from dataclasses import dataclass
from typing import Any, Dict, Optional

from .methods import Method, Response
from .base import Method, Response


@dataclass
Expand Down
84 changes: 19 additions & 65 deletions jmapc/methods/email.py
Original file line number Diff line number Diff line change
@@ -1,99 +1,53 @@
from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Optional, Union
from typing import List, Optional

from dataclasses_json import config

from .. import constants
from ..models import Email, Operator
from ..serializer import (
ListOrRef,
Model,
StrOrRef,
datetime_decode,
datetime_encode,
)
from .methods import Get, GetResponse, Query, QueryResponse
from ..models import Email, EmailQueryFilter, ListOrRef
from .base import Get, GetResponse, Query, QueryResponse


@dataclass
class EmailQuery(Query):
class EmailGet(Get):
@classmethod
def name(cls) -> str:
return "Email/query"
return "Email/get"

@classmethod
def using(cls) -> set[str]:
return set([constants.JMAP_URN_MAIL])

filter: Optional[EmailQueryFilter] = None
collapse_threads: Optional[bool] = None


@dataclass
class EmailQueryResponse(QueryResponse):
ids: ListOrRef[str]


@dataclass
class EmailQueryFilterCondition(Model):
in_mailbox: Optional[StrOrRef] = None
in_mailbox_other_than: Optional[ListOrRef] = None
before: Optional[datetime] = field(
default=None,
metadata=config(encoder=datetime_encode, decoder=datetime_decode),
)
after: Optional[datetime] = field(
default=None,
metadata=config(encoder=datetime_encode, decoder=datetime_decode),
)
min_size: Optional[int] = None
max_size: Optional[int] = None
all_in_thread_have_keyword: Optional[StrOrRef] = None
some_in_thread_have_keyword: Optional[StrOrRef] = None
none_in_thread_have_keyword: Optional[StrOrRef] = None
has_keyword: Optional[StrOrRef] = None
not_keyword: Optional[StrOrRef] = None
has_attachment: Optional[bool] = None
text: Optional[StrOrRef] = None
mail_from: Optional[str] = field(
metadata=config(field_name="from"), default=None
body_properties: Optional[List[str]] = None
fetch_text_body_values: Optional[bool] = None
fetch_html_body_values: Optional[bool] = field(
metadata=config(field_name="fetchHTMLBodyValues"), default=None
)
to: Optional[StrOrRef] = None
cc: Optional[StrOrRef] = None
bcc: Optional[StrOrRef] = None
body: Optional[StrOrRef] = None
header: Optional[ListOrRef] = None
fetch_all_body_values: Optional[bool] = None
max_body_value_bytes: Optional[int] = None


@dataclass
class EmailQueryFilterOperator(Model):
operator: Operator
conditions: List[EmailQueryFilter]


EmailQueryFilter = Union[EmailQueryFilterCondition, EmailQueryFilterOperator]
class EmailGetResponse(GetResponse):
data: List[Email] = field(metadata=config(field_name="list"))


@dataclass
class EmailGet(Get):
class EmailQuery(Query):
@classmethod
def name(cls) -> str:
return "Email/get"
return "Email/query"

@classmethod
def using(cls) -> set[str]:
return set([constants.JMAP_URN_MAIL])

body_properties: Optional[List[str]] = None
fetch_text_body_values: Optional[bool] = None
fetch_html_body_values: Optional[bool] = None
fetch_all_body_values: Optional[bool] = None
max_body_value_bytes: Optional[int] = None
filter: Optional[EmailQueryFilter] = None
collapse_threads: Optional[bool] = None


@dataclass
class EmailGetResponse(GetResponse):
data: List[Email] = field(metadata=config(field_name="list"))
class EmailQueryResponse(QueryResponse):
ids: ListOrRef[str]
8 changes: 5 additions & 3 deletions jmapc/methods/identity.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from __future__ import annotations

from dataclasses import dataclass, field
from typing import List
from typing import List, Optional

from dataclasses_json import config

from .. import constants
from ..models import Identity
from .methods import Get, GetResponse
from ..models import Identity, ListOrRef
from .base import Get, GetResponse


@dataclass
Expand All @@ -20,6 +20,8 @@ def name(cls) -> str:
def using(cls) -> set[str]:
return set([constants.JMAP_URN_SUBMISSION])

ids: Optional[ListOrRef[str]] = None


@dataclass
class IdentityGetResponse(GetResponse):
Expand Down
45 changes: 13 additions & 32 deletions jmapc/methods/mailbox.py
Original file line number Diff line number Diff line change
@@ -1,63 +1,44 @@
from __future__ import annotations

from dataclasses import dataclass, field
from typing import List, Optional, Union
from typing import List, Optional

from dataclasses_json import config

from .. import constants
from ..models import Mailbox, Operator
from ..serializer import ListOrRef, Model, StrOrRef
from .methods import Get, GetResponse, Query, QueryResponse
from ..models import ListOrRef, Mailbox, MailboxQueryFilter
from .base import Get, GetResponse, Query, QueryResponse


@dataclass
class MailboxQuery(Query):
class MailboxGet(Get):
@classmethod
def name(cls) -> str:
return "Mailbox/query"
return "Mailbox/get"

@classmethod
def using(cls) -> set[str]:
return set([constants.JMAP_URN_MAIL])

filter: Optional[MailboxQueryFilter] = None


@dataclass
class MailboxQueryResponse(QueryResponse):
ids: ListOrRef[str]


@dataclass
class MailboxQueryFilterCondition(Model):
name: Optional[StrOrRef] = None
role: Optional[StrOrRef] = None
parent_id: Optional[StrOrRef] = None


@dataclass
class MailboxQueryFilterOperator(Model):
operator: Operator
conditions: List[MailboxQueryFilter]


MailboxQueryFilter = Union[
MailboxQueryFilterCondition, MailboxQueryFilterOperator
]
class MailboxGetResponse(GetResponse):
data: List[Mailbox] = field(metadata=config(field_name="list"))


@dataclass
class MailboxGet(Get):
class MailboxQuery(Query):
@classmethod
def name(cls) -> str:
return "Mailbox/get"
return "Mailbox/query"

@classmethod
def using(cls) -> set[str]:
return set([constants.JMAP_URN_MAIL])

filter: Optional[MailboxQueryFilter] = None


@dataclass
class MailboxGetResponse(GetResponse):
data: List[Mailbox] = field(metadata=config(field_name="list"))
class MailboxQueryResponse(QueryResponse):
ids: ListOrRef[str]
2 changes: 1 addition & 1 deletion jmapc/methods/thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from .. import constants
from ..models import Thread
from .methods import Get, GetResponse
from .base import Get, GetResponse


@dataclass
Expand Down
Loading

0 comments on commit 5427093

Please sign in to comment.