Skip to content

Commit 9d94c7b

Browse files
authored
fix: upgrade django version and all deps (#106)
* feat: update django and all deps * feat: add unit test for mail sending feature
1 parent c1272ba commit 9d94c7b

File tree

4 files changed

+222
-189
lines changed

4 files changed

+222
-189
lines changed

pyproject.toml

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ version = "0.1.0"
44
requires-python = "==3.12.*"
55

66
dependencies = [
7-
"Django~=3.2.24",
8-
"django-post-office~=3.8.0",
9-
"djangorestframework~=3.14.0",
10-
"django-rest-knox~=4.2.0",
11-
"drf-spectacular~=0.27.1",
12-
"gunicorn~=20.1.0",
13-
"psycopg2-binary~=2.9.9",
14-
"python-dotenv~=0.19.2",
15-
"whitenoise~=6.6.0",
7+
"Django~=5.2.0",
8+
"django-post-office~=3.10.0",
9+
"djangorestframework~=3.16.0",
10+
"django-rest-knox~=5.0.0",
11+
"drf-spectacular~=0.29.0",
12+
"gunicorn~=23.0.0",
13+
"psycopg2-binary~=2.9.10",
14+
"python-dotenv~=1.0",
15+
"whitenoise~=6.11.0",
1616
"pymemcache>=4.0,<5.0",
1717
]
1818

@@ -25,13 +25,12 @@ packages = ["src/central_command"]
2525

2626
[tool.uv]
2727
dev-dependencies = [
28-
"pre-commit~=4.0",
29-
"ruff~=0.7",
30-
"mypy>=1.7.1",
31-
# TODO: bump django and stubs. these stubs seem to be incompatible with django 3.2
32-
# https://github.com/typeddjango/django-stubs/tree/master?tab=readme-ov-file#version-compatibility
33-
"django-stubs[compatible-mypy]==4.2.7",
34-
"djangorestframework-stubs[compatible-mypy]==3.14.5",
28+
"aiosmtpd~=1.4.5",
29+
"pre-commit~=4.4",
30+
"ruff~=0.14.0",
31+
"mypy>=1.18.0",
32+
"django-stubs[compatible-mypy]==5.2.7",
33+
"djangorestframework-stubs[compatible-mypy]==3.16.5",
3534
]
3635

3736
[tool.ruff]

src/accounts/api/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def post(self, request):
9191
email = serializer.validated_data["email"]
9292
password = serializer.validated_data["password"]
9393

94-
account: Account | None = authenticate(email=email, password=password) # type: ignore[assignment]
94+
account: Account | None = authenticate(email=email, password=password)
9595

9696
if account is None:
9797
return ErrorResponse(

src/tests/test_post_office_smtp.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import os
2+
import socket
3+
import tempfile
4+
5+
from pathlib import Path
6+
7+
from aiosmtpd.controller import Controller
8+
from django.core.management import call_command
9+
from django.test import TestCase, override_settings
10+
from post_office import mail
11+
from post_office.models import STATUS, Email
12+
13+
14+
class _InMemorySMTPHandler:
15+
def __init__(self):
16+
self.envelopes = []
17+
18+
async def handle_DATA(self, server, session, envelope): # noqa: N802 the name is required by aiosmtpd
19+
self.envelopes.append(envelope)
20+
return "250 OK"
21+
22+
23+
def _allocate_port():
24+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
25+
sock.bind(("127.0.0.1", 0))
26+
try:
27+
return sock.getsockname()[1]
28+
finally:
29+
sock.close()
30+
31+
32+
class PostOfficeSMTPIntegrationTest(TestCase):
33+
def setUp(self):
34+
self.smtp_handler = _InMemorySMTPHandler()
35+
self.smtp_port = _allocate_port()
36+
self.smtp_controller = Controller(self.smtp_handler, hostname="127.0.0.1", port=self.smtp_port)
37+
self.smtp_controller.start()
38+
self.addCleanup(self.smtp_controller.stop)
39+
40+
def test_queued_email_is_delivered_via_local_debug_server(self):
41+
recipients = ["[email protected]"]
42+
sender = "[email protected]"
43+
subject = "Queue smoke test"
44+
body = "Hello from the queue"
45+
46+
with override_settings(
47+
EMAIL_BACKEND="post_office.EmailBackend",
48+
EMAIL_HOST="127.0.0.1",
49+
EMAIL_PORT=self.smtp_port,
50+
EMAIL_USE_TLS=False,
51+
EMAIL_HOST_USER="",
52+
EMAIL_HOST_PASSWORD="",
53+
):
54+
mail.send(recipients=recipients, sender=sender, subject=subject, message=body)
55+
56+
self.assertEqual(Email.objects.filter(status=STATUS.queued).count(), 1)
57+
58+
fd, lockfile_path = tempfile.mkstemp()
59+
os.close(fd)
60+
try:
61+
call_command("send_queued_mail", processes=1, lockfile=lockfile_path, verbosity=0)
62+
finally:
63+
Path(lockfile_path).unlink()
64+
65+
sent_emails = Email.objects.filter(status=STATUS.sent)
66+
self.assertEqual(sent_emails.count(), 1)
67+
self.assertEqual(len(self.smtp_handler.envelopes), 1)
68+
envelope = self.smtp_handler.envelopes[0]
69+
self.assertEqual(envelope.mail_from, sender)
70+
self.assertEqual(envelope.rcpt_tos, recipients)
71+
self.assertIn(subject, envelope.content.decode())

0 commit comments

Comments
 (0)