From 965bee2e7b81f85287e8002fc9b13f4c87873524 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Wed, 18 Dec 2024 08:56:34 -0800 Subject: [PATCH] Prepare 0.2.0 release Update Python to 3.13 and update Python dependencies. Add `@override` markers where appropriate. Switch to the new `type` syntax for declaring type aliases. Collect the change log for 0.2.0. --- .github/workflows/ci.yaml | 2 +- .github/workflows/periodic-ci.yaml | 2 +- CHANGELOG.md | 7 ++ Dockerfile | 4 +- changelog.d/20241217_122642_rra_DM_48184.md | 3 - pyproject.toml | 4 +- requirements/dev.in | 1 + requirements/dev.txt | 29 +++++--- requirements/main.txt | 73 ++++++++++----------- requirements/tox.txt | 42 ++++++------ src/wobbly/handlers/service.py | 4 +- src/wobbly/models.py | 7 +- tests/handlers/service_test.py | 6 ++ 13 files changed, 103 insertions(+), 81 deletions(-) delete mode 100644 changelog.d/20241217_122642_rra_DM_48184.md diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 39eae4b..0df4b92 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -5,7 +5,7 @@ env: # reason to support multiple Python versions, so all actions are run with # this version. Quote the version to avoid interpretation as a floating # point number. - PYTHON_VERSION: "3.12" + PYTHON_VERSION: "3.13" "on": merge_group: {} diff --git a/.github/workflows/periodic-ci.yaml b/.github/workflows/periodic-ci.yaml index 65dd8b4..ab121d4 100644 --- a/.github/workflows/periodic-ci.yaml +++ b/.github/workflows/periodic-ci.yaml @@ -10,7 +10,7 @@ env: # reason to support multiple Python versions, so all actions are run with # this version. Quote the version to avoid interpretation as a floating # point number. - PYTHON_VERSION: "3.12" + PYTHON_VERSION: "3.13" "on": schedule: diff --git a/CHANGELOG.md b/CHANGELOG.md index ca4e5b8..b4a0f42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ Find changes for the upcoming release in the project's [changelog.d directory](h + +## 0.2.0 (2024-12-18) + +### New features + +- Add a `wobbly expire` command that deletes all jobs from the database that have passed their destruction time. This is run periodically as a Kubernetes `CronJob`. + ## 0.1.0 (2024-12-12) diff --git a/Dockerfile b/Dockerfile index 43333f6..911f98b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ # - Runs a non-root user. # - Sets up the entrypoint and port. -FROM python:3.12.8-slim-bookworm AS base-image +FROM python:3.13.1-slim-bookworm AS base-image # Update system packages. COPY scripts/install-base-packages.sh . @@ -21,7 +21,7 @@ RUN ./install-base-packages.sh && rm ./install-base-packages.sh FROM base-image AS install-image # Install uv. -COPY --from=ghcr.io/astral-sh/uv:0.5.8 /uv /bin/uv +COPY --from=ghcr.io/astral-sh/uv:0.5.10 /uv /bin/uv # Install system packages only needed for building dependencies. COPY scripts/install-dependency-packages.sh . diff --git a/changelog.d/20241217_122642_rra_DM_48184.md b/changelog.d/20241217_122642_rra_DM_48184.md deleted file mode 100644 index fa84efc..0000000 --- a/changelog.d/20241217_122642_rra_DM_48184.md +++ /dev/null @@ -1,3 +0,0 @@ -### New features - -- Add a `wobbly expire` command that deletes all jobs from the database that have passed their destruction time. This is run periodically as a Kubernetes `CronJob`. diff --git a/pyproject.toml b/pyproject.toml index 1a54473..2c31eef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,13 +11,13 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Intended Audience :: Developers", "Natural Language :: English", "Operating System :: POSIX", "Typing :: Typed", ] -requires-python = ">=3.12" +requires-python = ">=3.13" dependencies = [ "alembic[tz]", "fastapi>=0.100", diff --git a/requirements/dev.in b/requirements/dev.in index 828a9f9..0140fd1 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -18,6 +18,7 @@ pydantic pytest pytest-asyncio pytest-cov +pytest-sugar # Documentation scriv diff --git a/requirements/dev.txt b/requirements/dev.txt index 7ae7090..d3ecf0c 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -16,15 +16,15 @@ asgi-lifespan==2.1.0 \ --hash=sha256:5e2effaf0bfe39829cf2d64e7ecc47c7d86d676a6599f7afba378c31f5e3a308 \ --hash=sha256:ed840706680e28428c01e14afb3875d7d76d3206f3d5b2f2294e059b5c23804f # via -r requirements/dev.in -attrs==24.2.0 \ - --hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \ - --hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2 +attrs==24.3.0 \ + --hash=sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff \ + --hash=sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308 # via # -c requirements/main.txt # scriv -certifi==2024.8.30 \ - --hash=sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8 \ - --hash=sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9 +certifi==2024.12.14 \ + --hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56 \ + --hash=sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db # via # -c requirements/main.txt # httpcore @@ -376,6 +376,7 @@ packaging==24.2 \ # via # -c requirements/main.txt # pytest + # pytest-sugar pluggy==1.5.0 \ --hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \ --hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669 @@ -497,14 +498,19 @@ pytest==8.3.4 \ # -r requirements/dev.in # pytest-asyncio # pytest-cov -pytest-asyncio==0.24.0 \ - --hash=sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b \ - --hash=sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276 + # pytest-sugar +pytest-asyncio==0.25.0 \ + --hash=sha256:8c0610303c9e0442a5db8604505fc0f545456ba1528824842b37b4a626cbf609 \ + --hash=sha256:db5432d18eac6b7e28b46dcd9b69921b55c3b1086e85febfe04e70b18d9e81b3 # via -r requirements/dev.in pytest-cov==6.0.0 \ --hash=sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35 \ --hash=sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0 # via -r requirements/dev.in +pytest-sugar==1.0.0 \ + --hash=sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a \ + --hash=sha256:70ebcd8fc5795dc457ff8b69d266a4e2e8a74ae0c3edc749381c64b5246c8dfd + # via -r requirements/dev.in requests==2.32.3 \ --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 @@ -543,12 +549,15 @@ sniffio==1.3.1 \ # anyio # asgi-lifespan # httpx +termcolor==2.5.0 \ + --hash=sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8 \ + --hash=sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f + # via pytest-sugar typing-extensions==4.12.2 \ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 # via # -c requirements/main.txt - # anyio # mypy # pydantic # pydantic-core diff --git a/requirements/main.txt b/requirements/main.txt index b4e3469..887a92d 100644 --- a/requirements/main.txt +++ b/requirements/main.txt @@ -115,9 +115,9 @@ asyncpg==0.30.0 \ --hash=sha256:fb622c94db4e13137c4c7f98834185049cc50ee01d8f657ef898b6407c7b9c50 \ --hash=sha256:fd4406d09208d5b4a14db9a9dbb311b6d7aeeab57bded7ed2f8ea41aeef39b34 # via safir -attrs==24.2.0 \ - --hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \ - --hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2 +attrs==24.3.0 \ + --hash=sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff \ + --hash=sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308 # via # jsonschema # referencing @@ -129,9 +129,9 @@ casefy==1.0.0 \ --hash=sha256:bc99428475c2089c5f6a21297b4cfe4e83dff132cf3bb06655ddcb90632af1ed \ --hash=sha256:c89f96fb0fbd13691073b7a65c1e668e81453247d647479a3db105e86d7b0df9 # via dataclasses-avroschema -certifi==2024.8.30 \ - --hash=sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8 \ - --hash=sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9 +certifi==2024.12.14 \ + --hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56 \ + --hash=sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db # via # httpcore # httpx @@ -964,18 +964,18 @@ proto-plus==1.25.0 \ --hash=sha256:c91fc4a65074ade8e458e95ef8bac34d4008daa7cce4a12d6707066fca648961 \ --hash=sha256:fbb17f57f7bd05a68b7707e745e26528b0b3c34e378db91eef93912c54982d91 # via google-api-core -protobuf==5.29.1 \ - --hash=sha256:012ce28d862ff417fd629285aca5d9772807f15ceb1a0dbd15b88f58c776c98c \ - --hash=sha256:027fbcc48cea65a6b17028510fdd054147057fa78f4772eb547b9274e5219331 \ - --hash=sha256:1fc55267f086dd4050d18ef839d7bd69300d0d08c2a53ca7df3920cc271a3c34 \ - --hash=sha256:22c1f539024241ee545cbcb00ee160ad1877975690b16656ff87dde107b5f110 \ - --hash=sha256:32600ddb9c2a53dedc25b8581ea0f1fd8ea04956373c0c07577ce58d312522e0 \ - --hash=sha256:50879eb0eb1246e3a5eabbbe566b44b10348939b7cc1b267567e8c3d07213853 \ - --hash=sha256:5a41deccfa5e745cef5c65a560c76ec0ed8e70908a67cc8f4da5fce588b50d57 \ - --hash=sha256:683be02ca21a6ffe80db6dd02c0b5b2892322c59ca57fd6c872d652cb80549cb \ - --hash=sha256:8ee1461b3af56145aca2800e6a3e2f928108c749ba8feccc6f5dd0062c410c0d \ - --hash=sha256:b5ba1d0e4c8a40ae0496d0e2ecfdbb82e1776928a205106d14ad6985a09ec155 \ - --hash=sha256:d473655e29c0c4bbf8b69e9a8fb54645bc289dead6d753b952e7aa660254ae18 +protobuf==5.29.2 \ + --hash=sha256:13d6d617a2a9e0e82a88113d7191a1baa1e42c2cc6f5f1398d3b054c8e7e714a \ + --hash=sha256:2d2e674c58a06311c8e99e74be43e7f3a8d1e2b2fdf845eaa347fbd866f23355 \ + --hash=sha256:36000f97ea1e76e8398a3f02936aac2a5d2b111aae9920ec1b769fc4a222c4d9 \ + --hash=sha256:494229ecd8c9009dd71eda5fd57528395d1eacdf307dbece6c12ad0dd09e912e \ + --hash=sha256:842de6d9241134a973aab719ab42b008a18a90f9f07f06ba480df268f86432f9 \ + --hash=sha256:a0c53d78383c851bfa97eb42e3703aefdc96d2036a41482ffd55dc5f529466eb \ + --hash=sha256:b2cc8e8bb7c9326996f0e160137b0861f1a82162502658df2951209d0cb0309e \ + --hash=sha256:b6b0d416bbbb9d4fbf9d0561dbfc4e324fd522f61f7af0fe0f282ab67b22477e \ + --hash=sha256:c12ba8249f5624300cf51c3d0bfe5be71a60c63e4dcf51ffe9a68771d958c851 \ + --hash=sha256:e621a98c0201a7c8afe89d9646859859be97cb22b8bf1d8eacfd90d5bda2eb19 \ + --hash=sha256:fde4554c0e578a5a0bcc9a276339594848d1e89f9ea47b4427c80e5d72f90181 # via # google-api-core # googleapis-common-protos @@ -1112,9 +1112,9 @@ pydantic-core==2.27.1 \ # pydantic-xml # safir # safir-arq -pydantic-settings==2.6.1 \ - --hash=sha256:7fb0637c786a558d3103436278a7c4f1cfd29ba8973238a50c5bb9a55387da87 \ - --hash=sha256:e0f92546d8a9923cb8941689abf85d6601a8c19a23e97a34b2964a2e3f813ca0 +pydantic-settings==2.7.0 \ + --hash=sha256:ac4bfd4a36831a48dbf8b2d9325425b549a0a6f18cea118436d728eb4f1c4d66 \ + --hash=sha256:e00c05d5fa6cbbb227c84bd7487c5c1065084119b750df7c8c1a554aed236eb5 # via # wobbly (pyproject.toml) # safir @@ -1136,9 +1136,9 @@ python-dotenv==1.0.1 \ # via # pydantic-settings # uvicorn -python-multipart==0.0.19 \ - --hash=sha256:905502ef39050557b7a6af411f454bc19526529ca46ae6831508438890ce12cc \ - --hash=sha256:f8d5b0b9c618575bf9df01c684ded1d94a338839bdd8223838afacfb4bb2082d +python-multipart==0.0.20 \ + --hash=sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104 \ + --hash=sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13 # via safir python-schema-registry-client==2.6.0 \ --hash=sha256:a0688a9cd6e2a616a79fb46a6615c531cd5f9e2a5145f5c95932f792417731cb \ @@ -1326,17 +1326,17 @@ rsa==4.9 \ --hash=sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 \ --hash=sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21 # via google-auth -safir==9.0.1 \ - --hash=sha256:8235503c7198665417e5645d87639d5c79bebfd9bf8d529154677f622915b97e \ - --hash=sha256:e0e4fb1bb42981ddb1ad5dd8843e4aa3c73cde56500152f2cfdbeaf05bd63617 +safir==9.1.0 \ + --hash=sha256:38718de0d2e5f9623eddc511700a15fb56fee88da7bba0e1210dc831276aa9aa \ + --hash=sha256:630b2e59ae87edab25fb2c3d5ccd6ca156c0d525eb543624532bbf4fd3c85536 # via wobbly (pyproject.toml) -safir-arq==9.0.1 \ - --hash=sha256:14fb89cd0182d64feb9fca214a76642a858aea25210b60790058f4542d0d7fd7 \ - --hash=sha256:ddac70f37dcd78e4f816c2d4a9f8c5d21bb5d861b580bcce9a727b0517f4e9ce +safir-arq==9.1.0 \ + --hash=sha256:10a10ceb9ad8c22c316fe79383e8fb019cb08a08ac9e175b5980c30f083d9da5 \ + --hash=sha256:2958806f6af356d6051a67ee4513ea525f0114f1f48636b116a2be7aab2f9f78 # via safir -safir-logging==9.0.1 \ - --hash=sha256:775ab8b2c1a62fe5779f8d4504797df7affb5dbebc70fcad00307cda419d637e \ - --hash=sha256:e5dfdfbdafb0a60dd2b8cdd63f8171cb703830cd5d433d60c27028cc9a4044f1 +safir-logging==9.1.0 \ + --hash=sha256:614cf63ec2f54dec640df8da9ece69d8e5fb43b19f98a943430ceefac7b2f267 \ + --hash=sha256:c486c4406ed9ffc41e3ff977ac8938cb89cd57ba7f20436a03f9b336bf0008e0 # via safir six==1.17.0 \ --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ @@ -1429,7 +1429,6 @@ typing-extensions==4.12.2 \ # via # aiokafka # alembic - # anyio # dataclasses-avroschema # fastapi # faststream @@ -1444,9 +1443,9 @@ urllib3==2.2.3 \ --hash=sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac \ --hash=sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9 # via requests -uvicorn==0.32.1 \ - --hash=sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e \ - --hash=sha256:ee9519c246a72b1c084cea8d3b44ed6026e78a4a309cbedae9c37e4cb9fbb175 +uvicorn==0.34.0 \ + --hash=sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4 \ + --hash=sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9 # via wobbly (pyproject.toml) uvloop==0.21.0 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32' \ --hash=sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0 \ diff --git a/requirements/tox.txt b/requirements/tox.txt index d8d8380..1b08028 100644 --- a/requirements/tox.txt +++ b/requirements/tox.txt @@ -6,9 +6,9 @@ cachetools==5.5.0 \ # via # -c requirements/main.txt # tox -certifi==2024.8.30 \ - --hash=sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8 \ - --hash=sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9 +certifi==2024.12.14 \ + --hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56 \ + --hash=sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db # via # -c requirements/dev.txt # -c requirements/main.txt @@ -230,24 +230,24 @@ urllib3==2.2.3 \ # -c requirements/main.txt # docker # requests -uv==0.5.8 \ - --hash=sha256:0f2bcdd00a49ad1669e217a2787448cac1653c9968d74bfa3732f3c25ca26f69 \ - --hash=sha256:2b3076c79746d4f83257c9dea5ba0833b0711aeff8e6695670eadd140a0cf67f \ - --hash=sha256:2ee40bc9c08fea0e71092838c0fc36df83f741807d8be9acf2fd4c4757b3171e \ - --hash=sha256:365eb6bbb551c5623a73b1ed530f4e69083016f70f0cf5ca1a30ec66413bcda2 \ - --hash=sha256:4a3325af8ed1effa7076967472c063b0000d609fd6f561c7751e43bab30297f1 \ - --hash=sha256:56715389d240ac989af2188cd3bfc2b603d31b42330e915dacfe113b34d8e65b \ - --hash=sha256:5989bbbbca072edc1875036c76aed74ec3dfc4741de7d1f060e181717efea6ac \ - --hash=sha256:8058ab06d2f69355694f6e9a36edc45164474c516b4e2895bd67f8232d9022ed \ - --hash=sha256:84f26ce1736d075d1df34f7c3f6b0b728cecd9a4da3e5160d5d887587830e7ce \ - --hash=sha256:8a8cbe1ffa0ef5c2f1c90622e07211a8f93f48daa2be1bd4592bb8cda52b0285 \ - --hash=sha256:a7956787658fb9253fba49741886409402a48039bee64b1697397d27284919af \ - --hash=sha256:aa03c338e19456d3a6544a94293bd2905837ae22720cc161c83ea0fd13c3b09f \ - --hash=sha256:c56022edc0f61febbdef89e6f699a0e991932c493b7293635b4814e102d040d2 \ - --hash=sha256:c91d0a2b8218af2aa0385b867da8c13a620db22077686793c7231f012cb40619 \ - --hash=sha256:defd5da3685f43f74698634ffc197aaf9b836b8ba0de0e57b34d7bc74d856fa9 \ - --hash=sha256:e146062e4cc39db334cbde38d56d2c6301dd9cf6739ce07ce5a4d71b4cbc2d00 \ - --hash=sha256:f8ade0430b6618ae0e21e52f61f6f3943dd6f3184ef6dc4491087b27940427f9 +uv==0.5.10 \ + --hash=sha256:064e977957e61aaaf7215bbd8f8566bcb22d7662c8adc929d039010fdb686436 \ + --hash=sha256:06eb14988a75cc178241747a9437d23faad7d62e2d9b955db7e8a8098853341a \ + --hash=sha256:253a02e03bf83bc0ec4e17242f54a4af2fef6191fcfb392b2613defd2b2a2f89 \ + --hash=sha256:27f27eba58b9a71c3a7905ca966c69adf5a4a1df1dd14ef4d064c40cbaabc49e \ + --hash=sha256:326603d44454a8856a5660bb406e99194f3c8d2cc4504c97c99871da59575022 \ + --hash=sha256:4e0b91598e67d8c1228b47894a61fffb9d82caf8f1080bb9f21df49530118db6 \ + --hash=sha256:502d9d10f5f139c850b1f6085a0c5719d49dd39d767504ce7c4245b47531f156 \ + --hash=sha256:5890ca6703c371cecc88c2a7bf32fc47187a865fc577df0d40d390fcbdec76f0 \ + --hash=sha256:68a6b992b7ebae9f3fa2f395348c95e6f05745246b067a26e7597a6730fcb690 \ + --hash=sha256:7337ed40bae6f37d9335bf7f83bb43d08b6c141212b1ca3b15a9194c4d438ffe \ + --hash=sha256:87dd4473ebf585fcd78a818bf8735ab39a157bef4f712e8b22e753b7344f6290 \ + --hash=sha256:8bc47bd623b1f8fa883b7afbf480286b946512d9ac7bf23105e7d63ef702ea7b \ + --hash=sha256:936759d8de8f78969756ee2b1558b4e9bd4b059922d0840cdd162a190c95ac50 \ + --hash=sha256:adc0dad56118127b3a1cc0126149a9b8c643fd4e4c5fa37be6af4bd84d33d30c \ + --hash=sha256:b61812ee4765f07db02ff616d4aac9c514857c0648459242a286243fe92d6223 \ + --hash=sha256:d0d0e75a4337076f43936b11d6cc4cb11e261948c719adb8e208b78454a122a0 \ + --hash=sha256:fa8607cc07cc9e666e531a9533b02d45bbb376ae314721434643c328298709b4 # via tox-uv virtualenv==20.28.0 \ --hash=sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0 \ diff --git a/src/wobbly/handlers/service.py b/src/wobbly/handlers/service.py index 091511c..85d3983 100644 --- a/src/wobbly/handlers/service.py +++ b/src/wobbly/handlers/service.py @@ -9,7 +9,7 @@ from typing import Annotated -from fastapi import APIRouter, Depends, Header, Path, Response +from fastapi import APIRouter, Body, Depends, Header, Path, Response from safir.dependencies.gafaelfawr import auth_dependency from safir.models import ErrorLocation from safir.slack.webhook import SlackRouteErrorHandler @@ -140,7 +140,7 @@ async def delete_job( async def patch_job( *, job_id: Annotated[JobIdentifier, Depends(job_identifier_dependency)], - update: JobUpdate, + update: Annotated[JobUpdate, Body()], context: Annotated[RequestContext, Depends(context_dependency)], ) -> SerializedJob: job_service = context.factory.create_job_service() diff --git a/src/wobbly/models.py b/src/wobbly/models.py index 758648e..c990959 100644 --- a/src/wobbly/models.py +++ b/src/wobbly/models.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import Annotated, Self, TypeAlias +from typing import Annotated, Self, override from pydantic import BaseModel, Field from safir.database import DatetimeIdCursor @@ -80,14 +80,17 @@ class JobIdentifier: class JobCursor(DatetimeIdCursor[SerializedJob]): """Cursor for paginated lists of jobs.""" + @override @staticmethod def id_column() -> InstrumentedAttribute: return SQLJob.id + @override @staticmethod def time_column() -> InstrumentedAttribute: return SQLJob.creation_time + @override @classmethod def from_entry( cls, entry: SerializedJob, *, reverse: bool = False @@ -114,7 +117,7 @@ class JobSearch: """Limit the number of jobs returned to at most this count.""" -JobUpdate: TypeAlias = Annotated[ +type JobUpdate = Annotated[ JobUpdateAborted | JobUpdateCompleted | JobUpdateError diff --git a/tests/handlers/service_test.py b/tests/handlers/service_test.py index 36a9867..7702689 100644 --- a/tests/handlers/service_test.py +++ b/tests/handlers/service_test.py @@ -427,6 +427,12 @@ async def test_errors(client: AsyncClient) -> None: r = await client.get("/wobbly/jobs", params={"limit": -1}, headers=headers) assert r.status_code == 422 + # Unsupported updates are rejected. + r = await client.patch( + "/wobbly/jobs/1", json={"phase": "SUSPENDED"}, headers=headers + ) + assert r.status_code == 422 + async def create_jobs( client: AsyncClient, headers: dict[str, str], count: int