Skip to content

Commit 2ea61c0

Browse files
committed
Use IDs for accounts and mailboxes instead of the names
1 parent 217898a commit 2ea61c0

File tree

10 files changed

+188
-105
lines changed

10 files changed

+188
-105
lines changed

.coveragerc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
[run]
2-
omit = *tests*
2+
source = */mail_devel/*
3+
concurrency = multiprocessing
4+
parallel = True

noxfile.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,20 @@ def clean(session):
1010
@nox.session()
1111
def py3(session):
1212
session.install(
13+
"-e",
14+
".",
1315
"pytest",
1416
"pytest-asyncio",
1517
"pytest-cov",
1618
"pytest-xdist",
1719
"pytest-timeout",
1820
"coverage",
1921
)
20-
session.install(".")
2122
session.run(
2223
"pytest",
2324
"-n=5",
24-
"--cov-append",
2525
"--cov=src/mail_devel",
26+
"--cov-append",
2627
"--asyncio-mode=auto",
2728
"--timeout=5",
2829
)

src/mail_devel/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from .service import Service
22

3-
VERSION = "0.8.2"
3+
VERSION = "0.9.0"

src/mail_devel/http.py

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -96,20 +96,30 @@ async def start(self) -> None:
9696
web.post(r"/api", self._api_post),
9797
web.post(r"/api/upload", self._api_upload),
9898
web.get(r"/api", self._api_index),
99-
web.get(r"/api/{user}", self._api_user),
100-
web.get(r"/api/{user}/{mailbox}", self._api_mailbox),
101-
web.get(r"/api/{user}/{mailbox}/{uid:\d+}", self._api_message),
102-
web.get(r"/api/{user}/{mailbox}/{uid:\d+}/reply", self._api_reply),
99+
web.get(r"/api/{account:\d+}", self._api_account),
100+
web.get(r"/api/{account:\d+}/{mailbox:\d+}", self._api_mailbox),
103101
web.get(
104-
r"/api/{user}/{mailbox}/{uid:\d+}/attachment/{attachment}",
102+
r"/api/{account:\d+}/{mailbox:\d+}/{uid:\d+}",
103+
self._api_message,
104+
),
105+
web.get(
106+
r"/api/{account:\d+}/{mailbox:\d+}/{uid:\d+}/reply",
107+
self._api_reply,
108+
),
109+
web.get(
110+
r"/api/{account:\d+}/{mailbox:\d+}/{uid:\d+}/attachment/{attachment}",
105111
self._api_attachment,
106112
),
107-
web.get(r"/api/{user}/{mailbox}/{uid:\d+}/flags", self._api_flag),
113+
web.get(
114+
r"/api/{account:\d+}/{mailbox:\d+}/{uid:\d+}/flags", self._api_flag
115+
),
108116
web.put(
109-
r"/api/{user}/{mailbox}/{uid:\d+}/flags/{flag}", self._api_flag
117+
r"/api/{account:\d+}/{mailbox:\d+}/{uid:\d+}/flags/{flag}",
118+
self._api_flag,
110119
),
111120
web.delete(
112-
r"/api/{user}/{mailbox}/{uid:\d+}/flags/{flag}", self._api_flag
121+
r"/api/{account:\d+}/{mailbox:\d+}/{uid:\d+}/flags/{flag}",
122+
self._api_flag,
113123
),
114124
]
115125
)
@@ -191,18 +201,22 @@ async def _api_config(self, request: Request) -> Response: # pylint: disable=W0
191201
)
192202

193203
async def _api_index(self, request: Request) -> Response: # pylint: disable=W0613
194-
mailboxes = await self.mailboxes.list()
195-
return web.json_response(mailboxes)
204+
accounts = await self.mailboxes.list()
205+
return web.json_response(
206+
{self.mailboxes.id_of_user(user): user for user in accounts}
207+
)
196208

197-
async def _api_user(self, request: Request) -> Response: # pylint: disable=W0613
209+
async def _api_account(self, request: Request) -> Response: # pylint: disable=W0613
198210
try:
199-
user = request.match_info["user"]
200-
mailbox = self.mailboxes[user]
211+
account_id = int(request.match_info["account"])
212+
account = await self.mailboxes.get_by_id(account_id)
201213
except KeyError as e: # pragma: no cover
202214
raise web.HTTPNotFound() from e
203215

204-
mailboxes = await mailbox.list_mailboxes()
205-
return web.json_response([e.name for e in mailboxes.list()])
216+
mailboxes = await account.list_mailboxes()
217+
return web.json_response(
218+
{account.id_of_mailbox(e.name): e.name for e in mailboxes.list()}
219+
)
206220

207221
async def _api_upload(self, request: Request) -> Response: # pylint: disable=W0613
208222
data = await request.json()
@@ -256,9 +270,10 @@ async def _api_post(self, request: Request) -> Response:
256270

257271
async def _api_mailbox(self, request: Request) -> Response:
258272
try:
259-
user = request.match_info["user"]
260-
name = request.match_info["mailbox"]
261-
mailbox = await self.mailboxes[user].get_mailbox(name)
273+
account_id = int(request.match_info["account"])
274+
account = self.mailboxes.user_mapping[account_id]
275+
mailbox_id = int(request.match_info["mailbox"])
276+
mailbox = await self.mailboxes[account].get_mailbox_by_id(mailbox_id)
262277
except KeyError as e: # pragma: no cover
263278
raise web.HTTPNotFound() from e
264279

@@ -270,10 +285,11 @@ async def _api_mailbox(self, request: Request) -> Response:
270285

271286
async def _api_message(self, request: Request) -> Response:
272287
try:
273-
user = request.match_info["user"]
274-
name = request.match_info["mailbox"]
288+
account_id = int(request.match_info["account"])
289+
account = self.mailboxes.user_mapping[account_id]
290+
mailbox_id = int(request.match_info["mailbox"])
275291
uid = int(request.match_info["uid"])
276-
mailbox = await self.mailboxes[user].get_mailbox(name)
292+
mailbox = await self.mailboxes[account].get_mailbox_by_id(mailbox_id)
277293
except (IndexError, KeyError) as e: # pragma: no cover
278294
raise web.HTTPNotFound() from e
279295

@@ -285,10 +301,11 @@ async def _api_message(self, request: Request) -> Response:
285301

286302
async def _api_reply(self, request: Request) -> Response:
287303
try:
288-
user = request.match_info["user"]
289-
name = request.match_info["mailbox"]
304+
account_id = int(request.match_info["account"])
305+
mailbox_id = int(request.match_info["mailbox"])
290306
uid = int(request.match_info["uid"])
291-
mailbox = await self.mailboxes[user].get_mailbox(name)
307+
account = await self.mailboxes.get_by_id(account_id)
308+
mailbox = await account.get_mailbox_by_id(mailbox_id)
292309
except (IndexError, KeyError) as e: # pragma: no cover
293310
raise web.HTTPNotFound() from e
294311

@@ -314,11 +331,12 @@ async def _api_reply(self, request: Request) -> Response:
314331

315332
async def _api_attachment(self, request: Request) -> Response:
316333
try:
317-
user = request.match_info["user"]
318-
name = request.match_info["mailbox"]
334+
account_id = int(request.match_info["account"])
335+
mailbox_id = int(request.match_info["mailbox"])
319336
uid = int(request.match_info["uid"])
320337
attachment = request.match_info["attachment"]
321-
mailbox = await self.mailboxes[user].get_mailbox(name)
338+
account = await self.mailboxes.get_by_id(account_id)
339+
mailbox = await account.get_mailbox_by_id(mailbox_id)
322340
except (IndexError, KeyError) as e: # pragma: no cover
323341
raise web.HTTPNotFound() from e
324342

@@ -350,9 +368,10 @@ async def _api_attachment(self, request: Request) -> Response:
350368

351369
async def _api_flag(self, request: Request) -> Response:
352370
try:
353-
user = request.match_info["user"]
354-
name = request.match_info["mailbox"]
355-
mailbox = await self.mailboxes[user].get_mailbox(name)
371+
account_id = int(request.match_info["account"])
372+
mailbox_id = int(request.match_info["mailbox"])
373+
account = await self.mailboxes.get_by_id(account_id)
374+
mailbox = await account.get_mailbox_by_id(mailbox_id)
356375
uid = int(request.match_info["uid"])
357376

358377
if request.method in ("DELETE", "PUT"):

src/mail_devel/mailbox.py

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,23 @@
1414
class TestMailboxSet(MailboxSet):
1515
"""This MailboxSet creates the mailboxes automatically"""
1616

17+
def __init__(self):
18+
super().__init__()
19+
self.mailbox_mapping: dict[int, str] = {}
20+
21+
def id_of_mailbox(self, name: str) -> int:
22+
for mailbox_id, mailbox_name in self.mailbox_mapping.items():
23+
if mailbox_name == name:
24+
return mailbox_id
25+
26+
new_id = len(self.mailbox_mapping) + 1
27+
self.mailbox_mapping[new_id] = name
28+
return new_id
29+
30+
async def get_mailbox_by_id(self, mailbox_id: int) -> MailboxData:
31+
mailbox_name = self.mailbox_mapping[mailbox_id]
32+
return await self.get_mailbox(mailbox_name)
33+
1734
async def get_mailbox(self, name: str) -> MailboxData:
1835
if name not in self._set:
1936
await self.add_mailbox(name)
@@ -26,16 +43,26 @@ class TestMailboxDict:
2643
def __init__(
2744
self, config: IMAPConfig, filter_set: FilterSet, multi_user: bool = False
2845
):
29-
self.config = config
30-
self.filter_set = filter_set
31-
self.multi_user = multi_user
46+
self.config: IMAPConfig = config
47+
self.filter_set: FilterSet = filter_set
48+
self.multi_user: bool = multi_user
49+
self.user_mapping: dict[int, str] = {}
3250

3351
def __contains__(self, user: str) -> bool:
3452
return not self.multi_user or user in self.config.set_cache
3553

3654
def __getitem__(self, user: str) -> TestMailboxSet:
3755
return self.config.set_cache[user][0]
3856

57+
def id_of_user(self, name: str) -> int:
58+
for uid, user_name in self.user_mapping.items():
59+
if user_name == name:
60+
return uid
61+
62+
new_id = len(self.user_mapping) + 1
63+
self.user_mapping[new_id] = name
64+
return new_id
65+
3966
async def inbox_stats(self) -> dict[str, int]:
4067
stats = {}
4168
for user, (mset, _fset) in self.config.set_cache.items():
@@ -50,6 +77,13 @@ async def list(self):
5077

5178
return list(self.config.set_cache)
5279

80+
async def get_by_id(self, user_id: int) -> TestMailboxSet:
81+
if not self.multi_user:
82+
return await self.get(self.config.demo_user)
83+
84+
user_name = self.user_mapping[user_id]
85+
return await self.get(user_name)
86+
5387
async def get(self, user: str) -> TestMailboxSet:
5488
"""Get the mailbox for the user or the main mailbox if single user mode"""
5589
if not self.multi_user:

src/mail_devel/resources/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
<thead>
4646
<tr>
4747
<th class="summary">Summary</th>
48-
<th class="date">Date</th>
48+
<th class="date"><span class="ordering"></span> Date</th>
4949
<th class="read">Read</th>
5050
</tr>
5151
</thead>

src/mail_devel/resources/main.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,13 @@ button, .btn {
144144
width: 1px;
145145
white-space: nowrap;
146146
}
147+
#mailbox .ordering {
148+
display: inline-block;
149+
vertical-align: text-top;
150+
width: 12pt;
151+
}
152+
#mailbox .ordering.asc:before {content: "\25B4"}
153+
#mailbox .ordering.desc:before {content: "\25BC"}
147154

148155
#mailbox table th {
149156
border: 1px solid gray;

0 commit comments

Comments
 (0)