Skip to content

Commit a14c1d4

Browse files
authored
Merge pull request #229 from ttys0dev/async
Migrate to async Django
2 parents bc5d770 + 696ee43 commit a14c1d4

File tree

13 files changed

+919
-881
lines changed

13 files changed

+919
-881
lines changed

.github/workflows/deploy.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
if: (github.event_name == 'pull_request' && github.event.pull_request.merged == true)
1717
runs-on: ubuntu-latest
1818
steps:
19-
- uses: actions/checkout@v4
19+
- uses: actions/checkout@v6
2020
- name: Login to Docker Hub
2121
uses: docker/login-action@v3
2222
with:
@@ -30,12 +30,12 @@ jobs:
3030
needs: build
3131
runs-on: ubuntu-latest
3232
steps:
33-
- uses: actions/checkout@v4
33+
- uses: actions/checkout@v6
3434
- name: Set shortcode
3535
id: vars
3636
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
3737
- name: Configure AWS credentials
38-
uses: aws-actions/configure-aws-credentials@v4
38+
uses: aws-actions/configure-aws-credentials@v5
3939
with:
4040
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
4141
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

.github/workflows/lint.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ jobs:
1010
pre-commit:
1111
runs-on: ubuntu-latest
1212
steps:
13-
- uses: actions/checkout@v4
14-
- uses: actions/setup-python@v5
13+
- uses: actions/checkout@v6
14+
- uses: actions/setup-python@v6
1515
with:
16-
python-version: "3.10"
16+
python-version: "3.12"
1717
- uses: pre-commit/action@v3.0.1

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
build:
1111
runs-on: ubuntu-latest
1212
steps:
13-
- uses: actions/checkout@v4
13+
- uses: actions/checkout@v6
1414

1515
- name: Create the .env settings file
1616
run: cp .env.example .env.dev

.pre-commit-config.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
exclude: migrations
44
repos:
55
- repo: https://github.com/pre-commit/pre-commit-hooks
6-
rev: v4.5.0
6+
rev: v6.0.0
77
hooks:
88
- id: check-added-large-files
99
- id: check-ast
@@ -15,13 +15,11 @@ repos:
1515
- id: debug-statements
1616
- id: detect-private-key
1717
- id: fix-byte-order-marker
18-
- id: fix-encoding-pragma
19-
args: [--remove]
2018
- id: trailing-whitespace
2119
args: [--markdown-linebreak-ext=md]
2220

2321
- repo: https://github.com/astral-sh/ruff-pre-commit
24-
rev: v0.11.8
22+
rev: v0.14.8
2523
hooks:
2624
- id: ruff
2725
args: [ --fix ]

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ The following changes are not yet released, but are code complete:
33

44
## Current
55

6+
- Migrated to async Django 6.0.1
7+
68
**0.3.5 - 2025-11-21** #228
79

810
Features:

docker/Dockerfile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Note: Force M1 to emulate amd64
2-
FROM --platform=linux/amd64 python:3.10
2+
FROM --platform=linux/amd64 python:3.13
33

44
# Install uv
55
# https://docs.astral.sh/uv/guides/integration/docker/#installing-uv
6-
COPY --from=ghcr.io/astral-sh/uv:0.7 /uv /uvx /bin/
6+
COPY --from=ghcr.io/astral-sh/uv:0.9 /uv /uvx /bin/
77

88
# Install apt dependencies
99
# caching: https://docs.docker.com/build/cache/optimize/#use-cache-mounts
@@ -68,8 +68,9 @@ EXPOSE 5050
6868
ARG options
6969
ENV OPTIONS $options
7070

71-
CMD gunicorn $OPTIONS doctor.wsgi:application \
71+
CMD gunicorn $OPTIONS doctor.asgi:application \
7272
--workers ${DOCTOR_WORKERS:-1} \
73+
--worker-class uvicorn.workers.UvicornWorker \
7374
--max-requests 1000 \
7475
--max-requests-jitter 100 \
7576
--timeout 5400 \

doctor/wsgi.py renamed to doctor/asgi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
import os
1111

12-
from django.core.wsgi import get_wsgi_application
12+
from django.core.asgi import get_asgi_application
1313

1414
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "doctor.settings")
1515

16-
application = get_wsgi_application()
16+
application = get_asgi_application()

doctor/lib/utils.py

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
import asyncio
12
import datetime
23
import io
34
import logging
45
import os
56
import re
6-
import subprocess
77
import warnings
88
from collections import namedtuple
99
from decimal import Decimal
@@ -165,7 +165,7 @@ def do_test(self, *args, **kwargs):
165165
return do_test
166166

167167

168-
def make_png_thumbnail_for_instance(filepath, max_dimension):
168+
async def make_png_thumbnail_for_instance(filepath, max_dimension):
169169
"""Abstract function for making a thumbnail for a PDF
170170
171171
See helper functions below for how to use this in a simple way.
@@ -184,14 +184,17 @@ def make_png_thumbnail_for_instance(filepath, max_dimension):
184184
filepath,
185185
"-png",
186186
]
187-
p = subprocess.Popen(
188-
command, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
187+
p = await asyncio.create_subprocess_exec(
188+
*command,
189+
close_fds=True,
190+
stdout=asyncio.subprocess.PIPE,
191+
stderr=asyncio.subprocess.PIPE,
189192
)
190-
stdout, stderr = p.communicate()
193+
stdout, stderr = await p.communicate()
191194
return stdout, stderr.decode("utf-8"), str(p.returncode)
192195

193196

194-
def make_png_thumbnails(filepath, max_dimension, pages, directory):
197+
async def make_png_thumbnails(filepath, max_dimension, pages, directory):
195198
"""Abstract function for making a thumbnail for a PDF
196199
197200
See helper functions below for how to use this in a simple way.
@@ -212,13 +215,13 @@ def make_png_thumbnails(filepath, max_dimension, pages, directory):
212215
"-png",
213216
f"{directory.name}/thumb-{page}",
214217
]
215-
p = subprocess.Popen(
216-
command,
218+
p = await asyncio.create_subprocess_exec(
219+
*command,
217220
close_fds=True,
218-
stdout=subprocess.PIPE,
219-
stderr=subprocess.PIPE,
221+
stdout=asyncio.subprocess.DEVNULL,
222+
stderr=asyncio.subprocess.DEVNULL,
220223
)
221-
p.communicate()
224+
await p.wait()
222225

223226

224227
def pdf_bytes_from_image_array(image_list, output_path) -> None:
@@ -392,17 +395,22 @@ def log_sentry_event(
392395
logger.log(level, message, extra=extra, **kwargs)
393396

394397

395-
def strip_metadata_with_exiftool(path: str) -> bool:
398+
async def strip_metadata_with_exiftool(path: str) -> bool:
396399
"""Strip metadata from a file in place using exiftool
397400
398401
:param path: Temporary file path
399402
:return: True if exiftool succeeded or False if exiftool failed
400403
"""
401-
result = subprocess.run(
402-
["exiftool", "-all=", "-overwrite_original", path],
403-
capture_output=True,
404-
text=True,
404+
process = await asyncio.create_subprocess_exec(
405+
"exiftool",
406+
"-all=",
407+
"-overwrite_original",
408+
path,
409+
close_fds=True,
410+
stdout=asyncio.subprocess.DEVNULL,
411+
stderr=asyncio.subprocess.DEVNULL,
405412
)
413+
result = await process.wait()
406414

407415
# exiftool returns 0 = success
408-
return result.returncode == 0
416+
return result == 0

doctor/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
ALLOWED_HOSTS = ["doctor", "0.0.0.0", "localhost"]
2525
INSTALLED_APPS = []
2626
ROOT_URLCONF = "doctor.urls"
27-
WSGI_APPLICATION = "doctor.wsgi.application"
27+
ASGI_APPLICATION = "doctor.asgi.application"
2828

2929

3030
SENTRY_DSN = env("SENTRY_DSN", default="")

0 commit comments

Comments
 (0)