From a3873053431e0b4afcd13203eeae5877f191a2f2 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 16 Jul 2026 14:07:00 -0500 Subject: [PATCH 1/4] Update pydantic --- pyproject.toml | 2 +- uv.lock | 138 +++++++++++++++++++++++++------------------------ 2 files changed, 72 insertions(+), 68 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 697a23d0e..f07bc8ff3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ dependencies = [ "typing_extensions>=4.14.1", "typed-argparse>=0.3.1", - "pydantic~=2.12", + "pydantic~=2.13", # needed by pydantic EmailStr "email-validator~=2.3.0", diff --git a/uv.lock b/uv.lock index 724d63fa7..0ec4bbefe 100644 --- a/uv.lock +++ b/uv.lock @@ -1914,7 +1914,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.12.5" +version = "2.13.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -1922,80 +1922,84 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, ] [[package]] name = "pydantic-core" -version = "2.41.5" +version = "2.46.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, - { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, - { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, - { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, - { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, - { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, - { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, - { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, - { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, - { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, - { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, - { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, - { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, - { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, - { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, - { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, - { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, - { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, - { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, - { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, - { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, - { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, - { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, - { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, - { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, - { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, - { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, - { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, - { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, - { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, - { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, - { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, - { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, - { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, - { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, - { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, - { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, - { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, - { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, - { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, - { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, - { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, - { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, - { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, - { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, - { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, - { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, - { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, - { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, - { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, - { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, - { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, - { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, - { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, - { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, - { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, - { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, - { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, - { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, - { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, + { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, + { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, + { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, + { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, + { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, ] [[package]] @@ -2493,7 +2497,7 @@ requires-dist = [ { name = "packaging", specifier = ">=25" }, { name = "paramiko", specifier = ">=3.5.1" }, { name = "psycopg2", marker = "extra == 'postgres'", specifier = ">=2.9.10,<3" }, - { name = "pydantic", specifier = "~=2.12" }, + { name = "pydantic", specifier = "~=2.13" }, { name = "pygments", specifier = ">=2.6.1,<3" }, { name = "pymbolic", specifier = ">=2024.2.2" }, { name = "pymemcache", marker = "extra == 'memcache'", specifier = "~=4.0" }, From 9336502fbd62504f4c862ebedb41988c9b320baa Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 16 Jul 2026 14:07:36 -0500 Subject: [PATCH 2/4] Update ruff --- pyproject.toml | 2 +- uv.lock | 44 ++++++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f07bc8ff3..fae24caa6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,7 +84,7 @@ relate = "relate.bin.relate:main" [dependency-groups] dev = [ "factory_boy>=3.3.1,<4", - "ruff>=0.12.3,<1", + "ruff>=0.15.22,<1", "django-types", "basedpyright>=1.30.1", "pytest>=9.0.3,<10", diff --git a/uv.lock b/uv.lock index 0ec4bbefe..f41cb83f4 100644 --- a/uv.lock +++ b/uv.lock @@ -2531,7 +2531,7 @@ dev = [ { name = "pytest-factoryboy", specifier = ">=2.6.0,<3" }, { name = "pytest-pudb", git = "https://github.com/ndhansen/pytest-pudb.git?rev=c29b32a7c93e9a2d40ae1d8594c1fcb3dfd26e06" }, { name = "pytest-xdist", specifier = ">=3.0,<4" }, - { name = "ruff", specifier = ">=0.12.3,<1" }, + { name = "ruff", specifier = ">=0.15.22,<1" }, { name = "safety", specifier = ">=3.2.11,<4" }, { name = "sphinx", specifier = ">=8.1.3,<10" }, { name = "sphinx-copybutton", specifier = ">=0.5.2,<0.6" }, @@ -2631,27 +2631,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/06/04/eab13a954e763b0606f460443fcbf6bb5a0faf06890ea3754ff16523dce5/ruff-0.15.2.tar.gz", hash = "sha256:14b965afee0969e68bb871eba625343b8673375f457af4abe98553e8bbb98342", size = 4558148, upload-time = "2026-02-19T22:32:20.271Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/70/3a4dc6d09b13cb3e695f28307e5d889b2e1a66b7af9c5e257e796695b0e6/ruff-0.15.2-py3-none-linux_armv6l.whl", hash = "sha256:120691a6fdae2f16d65435648160f5b81a9625288f75544dc40637436b5d3c0d", size = 10430565, upload-time = "2026-02-19T22:32:41.824Z" }, - { url = "https://files.pythonhosted.org/packages/71/0b/bb8457b56185ece1305c666dc895832946d24055be90692381c31d57466d/ruff-0.15.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a89056d831256099658b6bba4037ac6dd06f49d194199215befe2bb10457ea5e", size = 10820354, upload-time = "2026-02-19T22:32:07.366Z" }, - { url = "https://files.pythonhosted.org/packages/2d/c1/e0532d7f9c9e0b14c46f61b14afd563298b8b83f337b6789ddd987e46121/ruff-0.15.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e36dee3a64be0ebd23c86ffa3aa3fd3ac9a712ff295e192243f814a830b6bd87", size = 10170767, upload-time = "2026-02-19T22:32:13.188Z" }, - { url = "https://files.pythonhosted.org/packages/47/e8/da1aa341d3af017a21c7a62fb5ec31d4e7ad0a93ab80e3a508316efbcb23/ruff-0.15.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9fb47b6d9764677f8c0a193c0943ce9a05d6763523f132325af8a858eadc2b9", size = 10529591, upload-time = "2026-02-19T22:32:02.547Z" }, - { url = "https://files.pythonhosted.org/packages/93/74/184fbf38e9f3510231fbc5e437e808f0b48c42d1df9434b208821efcd8d6/ruff-0.15.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f376990f9d0d6442ea9014b19621d8f2aaf2b8e39fdbfc79220b7f0c596c9b80", size = 10260771, upload-time = "2026-02-19T22:32:36.938Z" }, - { url = "https://files.pythonhosted.org/packages/05/ac/605c20b8e059a0bc4b42360414baa4892ff278cec1c91fff4be0dceedefd/ruff-0.15.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2dcc987551952d73cbf5c88d9fdee815618d497e4df86cd4c4824cc59d5dd75f", size = 11045791, upload-time = "2026-02-19T22:32:31.642Z" }, - { url = "https://files.pythonhosted.org/packages/fd/52/db6e419908f45a894924d410ac77d64bdd98ff86901d833364251bd08e22/ruff-0.15.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42a47fd785cbe8c01b9ff45031af875d101b040ad8f4de7bbb716487c74c9a77", size = 11879271, upload-time = "2026-02-19T22:32:29.305Z" }, - { url = "https://files.pythonhosted.org/packages/3e/d8/7992b18f2008bdc9231d0f10b16df7dda964dbf639e2b8b4c1b4e91b83af/ruff-0.15.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbe9f49354866e575b4c6943856989f966421870e85cd2ac94dccb0a9dcb2fea", size = 11303707, upload-time = "2026-02-19T22:32:22.492Z" }, - { url = "https://files.pythonhosted.org/packages/d7/02/849b46184bcfdd4b64cde61752cc9a146c54759ed036edd11857e9b8443b/ruff-0.15.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7a672c82b5f9887576087d97be5ce439f04bbaf548ee987b92d3a7dede41d3a", size = 11149151, upload-time = "2026-02-19T22:32:44.234Z" }, - { url = "https://files.pythonhosted.org/packages/70/04/f5284e388bab60d1d3b99614a5a9aeb03e0f333847e2429bebd2aaa1feec/ruff-0.15.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:72ecc64f46f7019e2bcc3cdc05d4a7da958b629a5ab7033195e11a438403d956", size = 11091132, upload-time = "2026-02-19T22:32:24.691Z" }, - { url = "https://files.pythonhosted.org/packages/fa/ae/88d844a21110e14d92cf73d57363fab59b727ebeabe78009b9ccb23500af/ruff-0.15.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:8dcf243b15b561c655c1ef2f2b0050e5d50db37fe90115507f6ff37d865dc8b4", size = 10504717, upload-time = "2026-02-19T22:32:26.75Z" }, - { url = "https://files.pythonhosted.org/packages/64/27/867076a6ada7f2b9c8292884ab44d08fd2ba71bd2b5364d4136f3cd537e1/ruff-0.15.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dab6941c862c05739774677c6273166d2510d254dac0695c0e3f5efa1b5585de", size = 10263122, upload-time = "2026-02-19T22:32:10.036Z" }, - { url = "https://files.pythonhosted.org/packages/e7/ef/faf9321d550f8ebf0c6373696e70d1758e20ccdc3951ad7af00c0956be7c/ruff-0.15.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1b9164f57fc36058e9a6806eb92af185b0697c9fe4c7c52caa431c6554521e5c", size = 10735295, upload-time = "2026-02-19T22:32:39.227Z" }, - { url = "https://files.pythonhosted.org/packages/2f/55/e8089fec62e050ba84d71b70e7834b97709ca9b7aba10c1a0b196e493f97/ruff-0.15.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:80d24fcae24d42659db7e335b9e1531697a7102c19185b8dc4a028b952865fd8", size = 11241641, upload-time = "2026-02-19T22:32:34.617Z" }, - { url = "https://files.pythonhosted.org/packages/23/01/1c30526460f4d23222d0fabd5888868262fd0e2b71a00570ca26483cd993/ruff-0.15.2-py3-none-win32.whl", hash = "sha256:fd5ff9e5f519a7e1bd99cbe8daa324010a74f5e2ebc97c6242c08f26f3714f6f", size = 10507885, upload-time = "2026-02-19T22:32:15.635Z" }, - { url = "https://files.pythonhosted.org/packages/5c/10/3d18e3bbdf8fc50bbb4ac3cc45970aa5a9753c5cb51bf9ed9a3cd8b79fa3/ruff-0.15.2-py3-none-win_amd64.whl", hash = "sha256:d20014e3dfa400f3ff84830dfb5755ece2de45ab62ecea4af6b7262d0fb4f7c5", size = 11623725, upload-time = "2026-02-19T22:32:04.947Z" }, - { url = "https://files.pythonhosted.org/packages/6d/78/097c0798b1dab9f8affe73da9642bb4500e098cb27fd8dc9724816ac747b/ruff-0.15.2-py3-none-win_arm64.whl", hash = "sha256:cabddc5822acdc8f7b5527b36ceac55cc51eec7b1946e60181de8fe83ca8876e", size = 10941649, upload-time = "2026-02-19T22:32:18.108Z" }, +version = "0.15.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/06/ae069393fc66e8ff33036d4b368003833bf6e88ccf182e17e7a2f1c754fd/ruff-0.15.22.tar.gz", hash = "sha256:3f15175b1fb580126f58285a5dae6b2ea89000136d980c64499211f116b54809", size = 4785063, upload-time = "2026-07-16T15:14:13.244Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/18/ee54b7ae1e121be7a28ea6da4b67564ebb0530e183a54415ab7e3bcd2c4e/ruff-0.15.22-py3-none-linux_armv6l.whl", hash = "sha256:44423e73493737f5e7c5b41d475483898ff37afcdae38bc3da5085e29af1c2d8", size = 10781258, upload-time = "2026-07-16T15:13:19.452Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d2/2520cb14761ddbeaf57642a76942fc36adcbdbe53b4532241995f6fc485c/ruff-0.15.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b82c6482946e9eda7ff2e091d25b8bad3f718684e1916d41bd56873cee05b697", size = 10999477, upload-time = "2026-07-16T15:13:23.318Z" }, + { url = "https://files.pythonhosted.org/packages/c9/10/74e53572aa758dfaa678c2a2646b5c5515d884b7ca56be4d2ce03ca4b560/ruff-0.15.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:11c1c715af53a09f714e011106bffc419751ec8232fcb5da42173284ea3fec6f", size = 10466716, upload-time = "2026-07-16T15:13:26.162Z" }, + { url = "https://files.pythonhosted.org/packages/1e/cc/44eaaf0844e028182f2d0a8f2190d0f359159aed0a9e5ab861d892f1ae2a/ruff-0.15.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:742a29cf29bddb7c8327895d6a10e0e6c5b38a96dd407af9b5d0857f809c0576", size = 10892644, upload-time = "2026-07-16T15:13:29.229Z" }, + { url = "https://files.pythonhosted.org/packages/9f/21/8edf559014d2b0f82beea19cfb713993ad802ccda16868769979c6090a84/ruff-0.15.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72af58b951b0ae395935ae79763dc349bc0eb706319d28f7a33ad2cfb3cfc178", size = 10576719, upload-time = "2026-07-16T15:13:32.35Z" }, + { url = "https://files.pythonhosted.org/packages/bf/1e/3a13abd392a3b50b62e5938a831f9ab6e588358cacad5c18545b716d2182/ruff-0.15.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d425005c1835eb24e2ee4161cb90e8db263415f4a71c8c72c33abaa6c0c224", size = 11376494, upload-time = "2026-07-16T15:13:35.958Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3e/422d3d95bcf04dd78e1aeac22184d4f9a8fb2c01865d39d44618484a0317/ruff-0.15.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8b9b3f8779a4f08c969defc3c8c35abffaa757e601ed5ae66d6d1db6519969a", size = 12208370, upload-time = "2026-07-16T15:13:39.185Z" }, + { url = "https://files.pythonhosted.org/packages/1e/91/5d065a0e0a02bf4813f5119ad278462eed081d2b832eb7c021ade0ec9e65/ruff-0.15.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e0dd1b2e4d3d585f897a0d137cbf4eaf6223bef4e8ce34d6bb12556c5f9249e", size = 11581098, upload-time = "2026-07-16T15:13:42.132Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f9/a0d4871d12fae702eb1f41b686caf05f1f8b124dc6db6f784f53d74918fa/ruff-0.15.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:365523eb91d9224e1bcb03b022fbf0facb8f9e23792a2c53d9d4b3924bdbdebb", size = 11399422, upload-time = "2026-07-16T15:13:45.2Z" }, + { url = "https://files.pythonhosted.org/packages/18/80/c843a5176cddbceb0b7e8dd41cf9993490796c1c469348d384f5a5c13c56/ruff-0.15.22-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:fabfd168afdf29fee5be98b831efa9683c94d7c5a3b58b9ce5a2e38444589a74", size = 11381683, upload-time = "2026-07-16T15:13:48.46Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/8485de0ae92239438a36cfc51350db9b9e85c9ebdfaea91b18e422706662/ruff-0.15.22-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:225dbf095a87f1d9f90f5fd7924d2613ee452a75a4308c63a8f50f761787aa7c", size = 10850295, upload-time = "2026-07-16T15:13:51.655Z" }, + { url = "https://files.pythonhosted.org/packages/fa/91/24977ec2ec72eaf15e4394ace2959fdff2dd1e14f03e005e838023407169/ruff-0.15.22-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1877d63b9d24ed278744f1523fd11b85540566d54641f97c566d7d9dc5ca5296", size = 10579640, upload-time = "2026-07-16T15:13:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/9c/47/9b51216951974df1f263ac19da550d34252e0ed7218c25f10c5ef9ed7517/ruff-0.15.22-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a1606c510bd7215680d32efab38965f7cdec3ef69f5170a3f4791404ffdd5262", size = 11105077, upload-time = "2026-07-16T15:13:57.915Z" }, + { url = "https://files.pythonhosted.org/packages/c2/47/20e9d4a3b8016778acea5fc32bb50d35d207500a17ddb529ffa6996feef8/ruff-0.15.22-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:630479b18625f5ffc373f77603a22a9f8ac0acd7ff0501178b5db28ec71e9c64", size = 11490980, upload-time = "2026-07-16T15:14:01.032Z" }, + { url = "https://files.pythonhosted.org/packages/4d/76/3f72d8fc38c1cb77b38c56a70da9d0c17700cc1cc50f9649c9d3c8f5ba71/ruff-0.15.22-py3-none-win32.whl", hash = "sha256:e5ba0e4a13fd14abbed2a77b517a3911290c6c6c59ef67784328d1668fab76cf", size = 10789165, upload-time = "2026-07-16T15:14:04.16Z" }, + { url = "https://files.pythonhosted.org/packages/cb/46/4965251734c2b6fcdca1b1b187d20bcac3af0ee5b083b89c910bb961ce3a/ruff-0.15.22-py3-none-win_amd64.whl", hash = "sha256:9be63ba1eb936acd2d1342fb8337c356353706fce233b2a15a09a97037e6acde", size = 11938297, upload-time = "2026-07-16T15:14:07.316Z" }, + { url = "https://files.pythonhosted.org/packages/57/c9/e69b1ff4c8b69093ef08b8919ab767af0569666865b39c30a8795d88d3c6/ruff-0.15.22-py3-none-win_arm64.whl", hash = "sha256:e1168075b72158510839f250027659cdd78476f40507dd517892304c41318661", size = 11298172, upload-time = "2026-07-16T15:14:10.51Z" }, ] [[package]] From acaaf10be19891863edb4b5e08289de9a22d9aa6 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 16 Jul 2026 14:11:28 -0500 Subject: [PATCH 3/4] Switch to ruff:ignore --- accounts/tests.py | 2 +- course/analytics.py | 1 - course/apps.py | 2 +- course/auth.py | 4 +- course/content.py | 14 +- course/enrollment.py | 12 +- course/grades.py | 2 +- course/grading.py | 6 +- course/im.py | 8 +- course/migrations/0113_merge_20190919_1408.py | 4 +- course/models.py | 4 +- course/page/base.py | 5 +- course/page/choice.py | 4 +- course/page/code_run_backend.py | 8 +- course/page/inline.py | 10 +- course/page/static.py | 2 +- course/tests.py | 2 +- course/validation.py | 2 +- doc/conf.py | 2 +- local_settings_example.py | 4 +- prairietest/admin.py | 4 +- relate/__init__.py | 2 +- relate/checks.py | 20 +-- relate/settings.py | 8 +- relate/utils.py | 2 +- tests/base_test_mixins.py | 148 +++++++++--------- tests/conftest.py | 3 +- tests/constants.py | 2 +- tests/test_admin.py | 4 +- tests/test_analytics.py | 2 +- tests/test_auth.py | 18 +-- tests/test_checks.py | 2 +- tests/test_content.py | 4 +- tests/test_enrollment.py | 10 +- tests/test_flow/test_flow.py | 6 +- tests/test_grades/test_csv.py | 14 +- tests/test_grades/test_generic.py | 6 +- tests/test_grades/test_grades.py | 8 +- tests/test_misc.py | 8 +- tests/test_pages/test_choice.py | 22 +-- tests/test_pages/test_code.py | 12 +- tests/test_pages/test_text.py | 4 +- tests/test_postgres.py | 6 +- tests/test_sandbox.py | 16 +- tests/test_utils.py | 8 +- tests/test_versioning.py | 6 +- tests/test_views.py | 2 +- tests/utils.py | 6 +- 48 files changed, 234 insertions(+), 217 deletions(-) diff --git a/accounts/tests.py b/accounts/tests.py index 52f585306..38028810c 100644 --- a/accounts/tests.py +++ b/accounts/tests.py @@ -1,4 +1,4 @@ -from django.test import TestCase # noqa +from django.test import TestCase # ruff:ignore[unused-import, missing-required-import] # Create your tests here. diff --git a/course/analytics.py b/course/analytics.py index aeb2ffe06..f3bd4e20a 100644 --- a/course/analytics.py +++ b/course/analytics.py @@ -53,7 +53,6 @@ from collections.abc import Callable from course.page.base import PageBase - from course.utils import CoursePageContext # {{{ flow list diff --git a/course/apps.py b/course/apps.py index 1354cf59e..0dfe2f9aa 100644 --- a/course/apps.py +++ b/course/apps.py @@ -14,7 +14,7 @@ class CourseConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" def ready(self): - import course.receivers # noqa + import course.receivers # ruff:ignore[unused-import] # register all checks register_startup_checks() diff --git a/course/auth.py b/course/auth.py index b3a08ab78..03b784af4 100644 --- a/course/auth.py +++ b/course/auth.py @@ -585,7 +585,7 @@ def reset_password(request: RelateHttpRequest, field: str = "email"): _("self-registration is not enabled")) # return form class by string of class name - ResetPasswordForm = globals()["ResetPasswordFormBy" + field.title()] # noqa + ResetPasswordForm = globals()["ResetPasswordFormBy" + field.title()] # ruff:ignore[non-lowercase-variable-in-function] if request.method == "POST": form = ResetPasswordForm(request.POST) user = None @@ -617,7 +617,7 @@ def reset_password(request: RelateHttpRequest, field: str = "email"): "contact site staff.")) else: if user is None: - FIELD_DICT = { # noqa + FIELD_DICT = { # ruff:ignore[non-lowercase-variable-in-function] "email": _("email address"), "instid": _("institutional ID") } diff --git a/course/content.py b/course/content.py index 1411042fb..03d57d3ec 100644 --- a/course/content.py +++ b/course/content.py @@ -30,7 +30,9 @@ import html.parser as html_parser import os import re -from collections.abc import Set as AbstractSet +from collections.abc import ( + Set as AbstractSet, # ruff:ignore[typing-only-standard-library-import] +) from dataclasses import dataclass, field from itertools import starmap from pathlib import Path @@ -73,8 +75,8 @@ FlowSessionExpirationMode, GradeAggregationStrategy, ) -from course.datespec import Datespec # noqa: TC001 -from course.page.base import PageBase # noqa: TC001 +from course.datespec import Datespec # ruff:ignore[typing-only-first-party-import] +from course.page.base import PageBase # ruff:ignore[typing-only-first-party-import] from course.repo import ( CACHE_KEY_ROOT, PYTHON_CLASS_REPO_PREFIX, @@ -107,7 +109,7 @@ if TYPE_CHECKING: - from collections.abc import Callable, Collection, Mapping, Set as AbstractSet + from collections.abc import Callable, Collection, Mapping from course.models import Course, Participation from course.repo import Repo_ish @@ -1513,7 +1515,7 @@ def __init__(self, self.commit_sha = commit_sha self.reverse_func = reverse_func - def extendMarkdown(self, md): # noqa + def extendMarkdown(self, md): # ruff:ignore[invalid-function-name] md.treeprocessors.register( LinkFixerTreeprocessor(md, self.course, self.commit_sha, reverse_func=self.reverse_func), @@ -1857,7 +1859,7 @@ def is_commit_sha_valid(repo: Repo_ish, commit_sha: RevisionID_ish) -> bool: if repo is not None: preview_sha_valid = is_commit_sha_valid(repo, preview_sha) else: - with get_course_repo(course) as repo: # noqa: PLR1704 + with get_course_repo(course) as repo: # ruff:ignore[redefined-argument-from-local] preview_sha_valid = is_commit_sha_valid(repo, preview_sha) if preview_sha_valid: diff --git a/course/enrollment.py b/course/enrollment.py index c0c230247..61648d1af 100644 --- a/course/enrollment.py +++ b/course/enrollment.py @@ -38,7 +38,11 @@ from django.core.exceptions import PermissionDenied, SuspiciousOperation from django.db import IntegrityError, transaction from django.db.models import Q -from django.shortcuts import get_object_or_404, redirect, render # noqa +from django.shortcuts import ( # ruff:ignore[unused-import] + get_object_or_404, + redirect, + render, +) from django.urls import reverse from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _, pgettext @@ -416,13 +420,13 @@ def send_enrollment_decision( def approve_enrollment(modeladmin, request, queryset): decide_enrollment(True, modeladmin, request, queryset) -approve_enrollment.short_description = pgettext("Admin", "Approve enrollment") # type:ignore # noqa +approve_enrollment.short_description = pgettext("Admin", "Approve enrollment") # type:ignore # ruff:ignore[blank-lines-after-function-or-class] def deny_enrollment(modeladmin, request, queryset): decide_enrollment(False, modeladmin, request, queryset) -deny_enrollment.short_description = _("Deny enrollment") # type:ignore # noqa +deny_enrollment.short_description = _("Deny enrollment") # type:ignore # ruff:ignore[blank-lines-after-function-or-class] # }}} @@ -841,7 +845,7 @@ def query_participations(pctx): if form.is_valid(): parsed_query = None try: - for lineno, q in enumerate( # noqa: B007 + for lineno, q in enumerate( # ruff:ignore[unused-loop-control-variable] form.cleaned_data["queries"].split("\n")): q = q.strip() diff --git a/course/grades.py b/course/grades.py index c8b1d0f9b..2bd02ca17 100644 --- a/course/grades.py +++ b/course/grades.py @@ -1514,7 +1514,7 @@ def download_all_submissions(pctx: CoursePageContext, flow_id: str): access_rules_tags = flow_desc.rules.tags - ALL_SESSION_TAG = string_concat("<<<", _("ALL"), ">>>") # noqa + ALL_SESSION_TAG = string_concat("<<<", _("ALL"), ">>>") # ruff:ignore[non-lowercase-variable-in-function] session_tag_choices = [ (tag, tag) for tag in access_rules_tags] + [(ALL_SESSION_TAG, diff --git a/course/grading.py b/course/grading.py index 6fe50814e..c176fa1a0 100644 --- a/course/grading.py +++ b/course/grading.py @@ -33,7 +33,11 @@ PermissionDenied, SuspiciousOperation, ) -from django.shortcuts import get_object_or_404, redirect, render # noqa +from django.shortcuts import ( # ruff:ignore[unused-import] + get_object_or_404, + redirect, + render, +) from django.utils.translation import gettext as _ from pytools import not_none diff --git a/course/im.py b/course/im.py index 8032fda56..c2b52d7a9 100644 --- a/course/im.py +++ b/course/im.py @@ -30,12 +30,16 @@ from django import forms from django.contrib import messages from django.core.exceptions import PermissionDenied -from django.shortcuts import get_object_or_404, redirect, render # noqa +from django.shortcuts import ( # ruff:ignore[unused-import] + get_object_or_404, + redirect, + render, +) from django.utils.translation import gettext as _, pgettext_lazy from course.constants import ParticipationPermission as PPerm from course.models import ( - Course, # noqa + Course, # ruff:ignore[unused-import] InstantMessage, ) from course.utils import course_view, render_course_page diff --git a/course/migrations/0113_merge_20190919_1408.py b/course/migrations/0113_merge_20190919_1408.py index 6851f725a..f98919a44 100644 --- a/course/migrations/0113_merge_20190919_1408.py +++ b/course/migrations/0113_merge_20190919_1408.py @@ -1,6 +1,6 @@ # Generated by Django 2.2.4 on 2019-09-19 19:08 -from typing import Any, List +from typing import Any from django.db import migrations @@ -12,4 +12,4 @@ class Migration(migrations.Migration): ('course', '0112_add_use_git_endpoint_permission'), ] - operations = [] # type: List[Any] + operations: list[Any] = [] diff --git a/course/models.py b/course/models.py index 5dd21944a..4c72d30ba 100644 --- a/course/models.py +++ b/course/models.py @@ -41,7 +41,7 @@ from pytools import not_none from typing_extensions import override -from course.constants import ( # noqa +from course.constants import ( # ruff:ignore[unused-import] COURSE_ID_REGEX, EVENT_KIND_REGEX, EXAM_TICKET_STATE_CHOICES, @@ -352,7 +352,7 @@ def clean(self) -> None: super().clean() try: - self.course # noqa: B018 + self.course # ruff:ignore[useless-expression] except ObjectDoesNotExist: raise ValidationError( {"course": diff --git a/course/page/base.py b/course/page/base.py index 70c872cb0..7c47bedb2 100644 --- a/course/page/base.py +++ b/course/page/base.py @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -import builtins +import builtins # ruff:ignore[typing-only-standard-library-import] from abc import ABC, abstractmethod from dataclasses import dataclass from inspect import isabstract @@ -73,7 +73,6 @@ if TYPE_CHECKING: - import builtins from collections.abc import Callable, Sequence, Set as AbstractSet from course.models import Course, FlowSession @@ -445,7 +444,7 @@ def __pydantic_init_subclass__(cls, **kwargs: object): # The following will create a new type adapter every time a new subclass # is created. Somewhat suboptimal, but there aren't very many. PageBase._discriminating_type_adapter = TypeAdapter( - Annotated[Union[tuple(PageBase._subclasses.values())], # noqa: UP007 # pyright: ignore[reportDeprecated] + Annotated[Union[tuple(PageBase._subclasses.values())], # ruff:ignore[non-pep604-annotation-union] # pyright: ignore[reportDeprecated] Field(discriminator="type")]) # emphasize that this should be fully defined at this point diff --git a/course/page/choice.py b/course/page/choice.py index a0e6b794b..a5f62dda4 100644 --- a/course/page/choice.py +++ b/course/page/choice.py @@ -116,7 +116,7 @@ def normalize_from_str(cls, data: Any) -> Any: try: data = str(data) - except Exception: # noqa: S110 + except Exception: # ruff:ignore[try-except-pass] pass else: choice_mode, choice_text = mode_from_prefix(data) @@ -152,7 +152,7 @@ def normalize_from_str(cls, data: Any) -> Any: try: data = str(data) - except Exception: # noqa: S110 + except Exception: # ruff:ignore[try-except-pass] pass else: choice_mode, choice_text = mode_from_prefix(data) diff --git a/course/page/code_run_backend.py b/course/page/code_run_backend.py index aeb327042..529e7f40a 100644 --- a/course/page/code_run_backend.py +++ b/course/page/code_run_backend.py @@ -99,7 +99,7 @@ def substitute_correct_code_into_test_code( return test_code import re - CORRECT_CODE_TAG = re.compile(r"^(\s*)###CORRECT_CODE###\s*$") # noqa + CORRECT_CODE_TAG = re.compile(r"^(\s*)###CORRECT_CODE###\s*$") # ruff:ignore[non-lowercase-variable-in-function] new_test_code_lines: list[str] = [] for line in test_code.split("\n"): @@ -136,7 +136,7 @@ def user_code_thread( user_ctx: dict[str, object], exc_info: list[ExcInfo]) -> None: try: - exec(user_code, user_ctx) # noqa: S102 + exec(user_code, user_ctx) # ruff:ignore[exec-builtin] except Exception: tp, val, tb = sys.exc_info() assert tp is not None @@ -214,7 +214,7 @@ def output_html(s: str): if setup_code is not None: try: - exec(setup_code, maint_ctx) # noqa: S102 + exec(setup_code, maint_ctx) # ruff:ignore[exec-builtin] except BaseException: return package_exception("setup_error") @@ -293,7 +293,7 @@ def output_html(s: str): if test_code is not None: try: - exec(test_code, maint_ctx) # noqa: S102 + exec(test_code, maint_ctx) # ruff:ignore[exec-builtin] except GradingComplete: pass except BaseException: diff --git a/course/page/inline.py b/course/page/inline.py index 98336769b..1030531b7 100644 --- a/course/page/inline.py +++ b/course/page/inline.py @@ -57,8 +57,10 @@ PageData, markup_to_html, ) -from course.page.choice import SingleChoiceDesc # noqa: TC001 -from course.page.text import Matcher # noqa: TC001 +from course.page.choice import ( + SingleChoiceDesc, # ruff:ignore[typing-only-first-party-import] +) +from course.page.text import Matcher # ruff:ignore[typing-only-first-party-import] from course.validation import ( CSSDimension, CSSDimensionMax, @@ -146,7 +148,7 @@ def clean(self): for name in list(cleaned_data.keys()): answer = self.answers[name] if isinstance(answer, ShortAnswer): - for i, validator in enumerate(answer.correct_answer): # pragma: no branch # noqa + for i, validator in enumerate(answer.correct_answer): # pragma: no branch # ruff:ignore[line-too-long] try: validator.validate_text(cleaned_data[name]) except forms.ValidationError as e: @@ -747,7 +749,7 @@ def page_correct_answer(self, else: snippets.append(t_or_b) - CA_PATTERN = string_concat(_("A correct answer is"), ": %s") # noqa + CA_PATTERN = string_concat(_("A correct answer is"), ": %s") # ruff:ignore[non-lowercase-variable-in-function] result = CA_PATTERN % ("".join(snippets)) diff --git a/course/page/static.py b/course/page/static.py index 9c0d468bd..5415e1a21 100644 --- a/course/page/static.py +++ b/course/page/static.py @@ -36,7 +36,7 @@ PageData, markup_to_html, ) -from course.validation import Markup # noqa: TC001 +from course.validation import Markup # ruff:ignore[typing-only-first-party-import] if TYPE_CHECKING: diff --git a/course/tests.py b/course/tests.py index 52f585306..38028810c 100644 --- a/course/tests.py +++ b/course/tests.py @@ -1,4 +1,4 @@ -from django.test import TestCase # noqa +from django.test import TestCase # ruff:ignore[unused-import, missing-required-import] # Create your tests here. diff --git a/course/validation.py b/course/validation.py index a7e1d50c0..6af4ece0b 100644 --- a/course/validation.py +++ b/course/validation.py @@ -419,7 +419,7 @@ def normalize_to_dict(cls, data: Any, info: ValidationInfo) -> Any: else: try: data = float(data) - except Exception: # noqa: S110 + except Exception: # ruff:ignore[try-except-pass] pass if isinstance(data, (int, float)): diff --git a/doc/conf.py b/doc/conf.py index de8caf4d0..85082d9e6 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -63,4 +63,4 @@ def setup(app): - app.connect("missing-reference", process_autodoc_missing_reference) # noqa: F821 + app.connect("missing-reference", process_autodoc_missing_reference) # ruff:ignore[undefined-name] diff --git a/local_settings_example.py b/local_settings_example.py index d20091314..49d86cb14 100644 --- a/local_settings_example.py +++ b/local_settings_example.py @@ -1,6 +1,6 @@ # See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/ -import os # noqa: F401 # pyright: ignore[reportUnusedImport] +import os # ruff:ignore[unused-import] # pyright: ignore[reportUnusedImport] from os import path @@ -20,7 +20,7 @@ # Configure the following as url as above. RELATE_BASE_URL = "http://YOUR/RELATE/SITE/DOMAIN" -from django.utils.translation import gettext_noop # noqa +from django.utils.translation import gettext_noop # ruff:ignore[unused-import, unsorted-imports] # Uncomment this to configure the site name of your relate instance. # If not configured, "RELATE" will be used as default value. diff --git a/prairietest/admin.py b/prairietest/admin.py index 8e193f3e4..db731ef35 100644 --- a/prairietest/admin.py +++ b/prairietest/admin.py @@ -32,7 +32,7 @@ from django.utils.safestring import mark_safe from typing_extensions import override -from accounts.models import User +from accounts.models import User # ruff:ignore[typing-only-first-party-import] from course.constants import ParticipationPermission as PPerm from prairietest.models import AllowEvent, DenyEvent, Facility, MostRecentDenyEvent @@ -40,8 +40,6 @@ if TYPE_CHECKING: from django.db.models import QuerySet - from accounts.models import User - class FacilityAdminForm(forms.ModelForm): class Meta: diff --git a/relate/__init__.py b/relate/__init__.py index 0ac756bf9..619d3cc5a 100644 --- a/relate/__init__.py +++ b/relate/__init__.py @@ -6,4 +6,4 @@ if "RELATE_COMMAND_LINE" not in os.environ: # This will make sure the app is always imported when # Django starts so that shared_task will use this app. - from .celery import app as celery_app # noqa + from .celery import app as celery_app # ruff:ignore[unused-import] diff --git a/relate/checks.py b/relate/checks.py index d5b781408..d967c6be5 100644 --- a/relate/checks.py +++ b/relate/checks.py @@ -195,7 +195,7 @@ def check_relate_settings(app_configs, **kwargs): msg=( INSTANCE_ERROR_PATTERN % {"location": - f"'ip_ranges' in facility `{facilities}` in {RELATE_FACILITIES}", # noqa: E501 + f"'ip_ranges' in facility `{facilities}` in {RELATE_FACILITIES}", # ruff:ignore[line-too-long] "types": "list or tuple"}), id="relate_facilities.E004") ) @@ -210,7 +210,7 @@ def check_relate_settings(app_configs, **kwargs): % { "location": "'ip_ranges' in " - f"facility `{facility}` in {RELATE_FACILITIES}", # noqa: E501 + f"facility `{facility}` in {RELATE_FACILITIES}", # ruff:ignore[line-too-long] "error_type": type(e).__name__, "error_str": str(e) }), @@ -220,7 +220,7 @@ def check_relate_settings(app_configs, **kwargs): if not callable(relate_facilities_conf): errors.append(Warning( msg=( - f"Faclity `{facility}` in {RELATE_FACILITIES} is an open facility " # noqa: E501 + f"Faclity `{facility}` in {RELATE_FACILITIES} is an open facility " # ruff:ignore[line-too-long] "as it has no configured `ip_ranges`" ), id="relate_facilities.W001" @@ -271,7 +271,7 @@ def check_relate_settings(app_configs, **kwargs): if relate_session_restart_cooldown_seconds < 0: errors.append(RelateCriticalCheckMessage( msg=( - f"{RELATE_SESSION_RESTART_COOLDOWN_SECONDS} must be a positive number, " # noqa: E501 + f"{RELATE_SESSION_RESTART_COOLDOWN_SECONDS} must be a positive number, " # ruff:ignore[line-too-long] f"got {relate_session_restart_cooldown_seconds} instead"), id="relate_session_restart_cooldown_seconds.E002") ) @@ -293,7 +293,7 @@ def check_relate_settings(app_configs, **kwargs): if relate_ticket_minutes_valid_after_use < 0: errors.append(RelateCriticalCheckMessage( msg=( - f"{RELATE_TICKET_MINUTES_VALID_AFTER_USE} must be a positive number, " # noqa: E501 + f"{RELATE_TICKET_MINUTES_VALID_AFTER_USE} must be a positive number, " # ruff:ignore[line-too-long] f"got {relate_ticket_minutes_valid_after_use} instead"), id="relate_ticket_minutes_valid_after_use.E002") ) @@ -360,7 +360,7 @@ def check_relate_settings(app_configs, **kwargs): if not isinstance(relate_disable_codehilite_markdown_extension, bool): errors.append( Warning( - msg=f"{RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION} is not a Boolean value: `{relate_disable_codehilite_markdown_extension!r}`, " # noqa: E501 + msg=f"{RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION} is not a Boolean value: `{relate_disable_codehilite_markdown_extension!r}`, " # ruff:ignore[line-too-long] "assuming True", id="relate_disable_codehilite_markdown_extension.W001")) elif not relate_disable_codehilite_markdown_extension: @@ -409,7 +409,7 @@ def check_relate_settings(app_configs, **kwargs): errors.extend(Warning( msg=( "Duplicate language entries were found in " - f"settings.LANGUAGES for '{lang_code}', '{options_dict[lang_code]}' will be used " # noqa: E501 + f"settings.LANGUAGES for '{lang_code}', '{options_dict[lang_code]}' will be used " # ruff:ignore[line-too-long] "as its language_description"), id="relate_languages.W001" ) @@ -431,7 +431,7 @@ def check_relate_settings(app_configs, **kwargs): if not isinstance(site_name, str): errors.append(RelateCriticalCheckMessage( msg=(INSTANCE_ERROR_PATTERN - % {"location": f"{RELATE_SITE_NAME}/{RELATE_CUSTOMIZED_SITE_NAME}", # noqa: E501 + % {"location": f"{RELATE_SITE_NAME}/{RELATE_CUSTOMIZED_SITE_NAME}", # ruff:ignore[line-too-long] "types": "string"}), id="relate_site_name.E003")) elif not site_name.strip(): @@ -464,12 +464,12 @@ def check_relate_settings(app_configs, **kwargs): if any(not isinstance(directory, str) for directory in relate_override_templates_dirs): errors.append(RelateCriticalCheckMessage( - msg=(f"'{RELATE_OVERRIDE_TEMPLATES_DIRS}' must contain only string of paths."), # noqa: E501 + msg=(f"'{RELATE_OVERRIDE_TEMPLATES_DIRS}' must contain only string of paths."), # ruff:ignore[line-too-long] id="relate_override_templates_dirs.E002")) else: errors.extend(Warning( msg=( - f"Invalid Templates Dirs item '{directory}' in '{RELATE_OVERRIDE_TEMPLATES_DIRS}', " # noqa: E501 + f"Invalid Templates Dirs item '{directory}' in '{RELATE_OVERRIDE_TEMPLATES_DIRS}', " # ruff:ignore[line-too-long] "it will be ignored."), id="relate_override_templates_dirs.W001" ) diff --git a/relate/settings.py b/relate/settings.py index c91ebfb36..7356e5973 100644 --- a/relate/settings.py +++ b/relate/settings.py @@ -42,9 +42,9 @@ local_settings_module_name, ext = ( os.path.splitext(os.path.split(_local_settings_file)[-1])) assert ext == ".py" -exec(f"import {local_settings_module_name} as local_settings_module") # noqa: S102 +exec(f"import {local_settings_module_name} as local_settings_module") # ruff:ignore[exec-builtin] -local_settings = local_settings_module.__dict__ # type: ignore # noqa +local_settings = local_settings_module.__dict__ # type: ignore # ruff:ignore[undefined-name] # {{{ django: apps @@ -322,8 +322,8 @@ if "CELERY_RESULT_BACKEND" not in globals(): if ( "CACHES" in globals() - and "LocMem" not in CACHES["default"]["BACKEND"] # type:ignore # noqa - and "Dummy" not in CACHES["default"]["BACKEND"] # type:ignore # noqa + and "LocMem" not in CACHES["default"]["BACKEND"] # type:ignore # ruff:ignore[undefined-name] + and "Dummy" not in CACHES["default"]["BACKEND"] # type:ignore # ruff:ignore[undefined-name] ): # If possible, we would like to use an external cache as a # result backend--because then the progress bars work, because diff --git a/relate/utils.py b/relate/utils.py index c30e9df6f..53da2bfa6 100644 --- a/relate/utils.py +++ b/relate/utils.py @@ -286,7 +286,7 @@ def _retry_transaction( sleep(uniform(0.05, 0.2)) -class retry_transaction_decorator: # noqa +class retry_transaction_decorator: # ruff:ignore[invalid-class-name] def __init__(self, max_tries: int | None = None, serializable: bool | None = None) -> None: self.max_tries: int | None = max_tries diff --git a/tests/base_test_mixins.py b/tests/base_test_mixins.py index c539fe059..d5cffcd50 100644 --- a/tests/base_test_mixins.py +++ b/tests/base_test_mixins.py @@ -201,7 +201,7 @@ class CourseCreateFailure(Exception): pass -class classmethod_with_client: # noqa: N801 +class classmethod_with_client: # ruff:ignore[invalid-class-name] """This acts like Python's built-in ``classmethod``, with one change: When called on an instance (i.e. not a class), it automatically supplies ``self.client`` as the first argument. @@ -240,7 +240,7 @@ def get_response_context_value_by_name(self, response, context_name): else: return value - def assertResponseHasNoContext(self, response, context_name): # noqa + def assertResponseHasNoContext(self, response, context_name): # ruff:ignore[invalid-function-name] has_context = True try: response.context[context_name] @@ -249,7 +249,7 @@ def assertResponseHasNoContext(self, response, context_name): # noqa if has_context: self.fail(f"{context_name} unexpectedly exist in given response") - def assertResponseContextIsNone(self, resp, context_name): # noqa + def assertResponseContextIsNone(self, resp, context_name): # ruff:ignore[invalid-function-name] try: value = self.get_response_context_value_by_name(resp, context_name) except AssertionError: @@ -258,11 +258,11 @@ def assertResponseContextIsNone(self, resp, context_name): # noqa else: self.assertIsNone(value) - def assertResponseContextIsNotNone(self, resp, context_name, msg=""): # noqa + def assertResponseContextIsNotNone(self, resp, context_name, msg=""): # ruff:ignore[invalid-function-name] value = self.get_response_context_value_by_name(resp, context_name) self.assertIsNotNone(value, msg) - def assertResponseContextEqual(self, resp, context_name, expected_value): # noqa + def assertResponseContextEqual(self, resp, context_name, expected_value): # ruff:ignore[invalid-function-name] value = self.get_response_context_value_by_name(resp, context_name) try: self.assertTrue(abs(float(value) - float(expected_value)) <= 1e-04) @@ -270,7 +270,7 @@ def assertResponseContextEqual(self, resp, context_name, expected_value): # noq except Exception: self.assertEqual(value, expected_value) - def assertResponseContextContains(self, resp, # noqa + def assertResponseContextContains(self, resp, # ruff:ignore[invalid-function-name] context_name, expected_value, html=False, in_bulk=False): value = self.get_response_context_value_by_name(resp, context_name) @@ -289,7 +289,7 @@ def assertResponseContextContains(self, resp, # noqa else: self.assertInHTML(expected_value, value) - def assertResponseContextRegex( # noqa + def assertResponseContextRegex( # ruff:ignore[invalid-function-name] self, resp, context_name, expected_value_regex): value = self.get_response_context_value_by_name(resp, context_name) @@ -314,7 +314,7 @@ def get_response_context_answer_feedback_string(self, response, return answer_feedback.bulk_feedback return answer_feedback.feedback + answer_feedback.bulk_feedback - def assertResponseContextAnswerFeedbackContainsFeedback( # noqa + def assertResponseContextAnswerFeedbackContainsFeedback( # ruff:ignore[invalid-function-name] self, response, expected_feedback, include_bulk_feedback=True, html=False): feedback_str = self.get_response_context_answer_feedback_string( @@ -325,7 +325,7 @@ def assertResponseContextAnswerFeedbackContainsFeedback( # noqa else: self.assertInHTML(expected_feedback, feedback_str) - def assertResponseContextAnswerFeedbackNotContainsFeedback( # noqa + def assertResponseContextAnswerFeedbackNotContainsFeedback( # ruff:ignore[invalid-function-name] self, response, expected_feedback, include_bulk_feedback=True, html=False): @@ -337,7 +337,7 @@ def assertResponseContextAnswerFeedbackNotContainsFeedback( # noqa else: self.assertInHTML(expected_feedback, feedback_str, count=0) - def assertResponseContextAnswerFeedbackCorrectnessEquals( # noqa + def assertResponseContextAnswerFeedbackCorrectnessEquals( # ruff:ignore[invalid-function-name] self, response, expected_correctness): answer_feedback = self.get_response_context_answer_feedback(response) if expected_correctness is None: @@ -349,11 +349,11 @@ def assertResponseContextAnswerFeedbackCorrectnessEquals( # noqa self.assertIsNone(answer_feedback.correctness) else: if answer_feedback.correctness is None: - return self.fail(f"The returned correctness is None, not {expected_correctness}") # noqa: E501 + return self.fail(f"The returned correctness is None, not {expected_correctness}") # ruff:ignore[line-too-long] self.assertTrue( abs(float(answer_feedback.correctness) - float(str(expected_correctness))) < CORRECTNESS_ATOL, - f"{str(answer_feedback.correctness)[:5]} does not equal {str(expected_correctness)[:5]}") # noqa: E501 + f"{str(answer_feedback.correctness)[:5]} does not equal {str(expected_correctness)[:5]}") # ruff:ignore[line-too-long] def get_response_body(self, response): return self.get_response_context_value_by_name(response, "body") @@ -442,11 +442,11 @@ def get_sign_up_view_url(cls): return reverse("relate-sign_up") @classmethod_with_client - def get_sign_up(cls, client, *, follow=True): # noqa: N805 + def get_sign_up(cls, client, *, follow=True): # ruff:ignore[invalid-first-argument-name-for-method] return client.get(cls.get_sign_up_view_url(), follow=follow) @classmethod_with_client - def post_sign_up(cls, client, data, *, follow=True): # noqa: N805 + def post_sign_up(cls, client, data, *, follow=True): # ruff:ignore[invalid-first-argument-name-for-method] return client.post(cls.get_sign_up_view_url(), data, follow=follow) @classmethod @@ -454,11 +454,11 @@ def get_profile_view_url(cls): return reverse("relate-user_profile") @classmethod_with_client - def get_profile(cls, client, *, follow=True): # noqa: N805 + def get_profile(cls, client, *, follow=True): # ruff:ignore[invalid-first-argument-name-for-method] return client.get(cls.get_profile_view_url(), follow=follow) @classmethod_with_client - def post_profile(cls, client, data, *, follow=True): # noqa: N805 + def post_profile(cls, client, data, *, follow=True): # ruff:ignore[invalid-first-argument-name-for-method] data.update({"submit_user": [""]}) return client.post(cls.get_profile_view_url(), data, follow=follow) @@ -475,11 +475,11 @@ def get_stop_impersonate_view_url(cls): return reverse("relate-stop_impersonating") @classmethod_with_client - def get_impersonate_view(cls, client): # noqa: N805 + def get_impersonate_view(cls, client): # ruff:ignore[invalid-first-argument-name-for-method] return client.get(cls.get_impersonate_view_url()) @classmethod_with_client - def post_impersonate_view(cls, client, # noqa: N805 + def post_impersonate_view(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] impersonatee, *, follow=True): data = {"add_impersonation_header": ["on"], "submit": [""], @@ -488,11 +488,11 @@ def post_impersonate_view(cls, client, # noqa: N805 return client.post(cls.get_impersonate_view_url(), data, follow=follow) @classmethod_with_client - def get_stop_impersonate(cls, client, *, follow=True): # noqa: N805 + def get_stop_impersonate(cls, client, *, follow=True): # ruff:ignore[invalid-first-argument-name-for-method] return client.get(cls.get_stop_impersonate_view_url(), follow=follow) @classmethod_with_client - def post_stop_impersonate(cls, client, *, # noqa: N805 + def post_stop_impersonate(cls, client, *, # ruff:ignore[invalid-first-argument-name-for-method] data=None, follow=True): if not data: data = {"stop_impersonating": ""} @@ -521,11 +521,11 @@ def get_reset_password_url(cls, use_instid=False): return reverse("relate-reset_password", kwargs=kwargs) @classmethod_with_client - def get_reset_password(cls, client, *, use_instid=False): # noqa: N805 + def get_reset_password(cls, client, *, use_instid=False): # ruff:ignore[invalid-first-argument-name-for-method] return client.get(cls.get_reset_password_url(use_instid)) @classmethod_with_client - def post_reset_password(cls, client, data, *, use_instid=False): # noqa: N805 + def post_reset_password(cls, client, data, *, use_instid=False): # ruff:ignore[invalid-first-argument-name-for-method] return client.post(cls.get_reset_password_url(use_instid), data=data) @@ -552,14 +552,14 @@ def get_fake_time_url(cls): return reverse("relate-set_fake_time") @classmethod_with_client - def get_set_fake_time(cls, client): # noqa: N805 + def get_set_fake_time(cls, client): # ruff:ignore[invalid-first-argument-name-for-method] return client.get(cls.get_fake_time_url()) @classmethod_with_client - def post_set_fake_time(cls, client, data, *, follow=True): # noqa: N805 + def post_set_fake_time(cls, client, data, *, follow=True): # ruff:ignore[invalid-first-argument-name-for-method] return client.post(cls.get_fake_time_url(), data, follow=follow) - def assertSessionFakeTimeEqual(self, session, expected_date_time): # noqa + def assertSessionFakeTimeEqual(self, session, expected_date_time): # ruff:ignore[invalid-function-name] fake_time_timestamp = session.get("relate_fake_time", None) if fake_time_timestamp is None: faked_time = None @@ -570,7 +570,7 @@ def assertSessionFakeTimeEqual(self, session, expected_date_time): # noqa faked_time = datetime.datetime.fromtimestamp(fake_time_timestamp) self.assertEqual(faked_time, expected_date_time) - def assertSessionFakeTimeIsNone(self, session): # noqa + def assertSessionFakeTimeIsNone(self, session): # ruff:ignore[invalid-function-name] self.assertSessionFakeTimeEqual(session, None) @classmethod @@ -578,11 +578,11 @@ def get_set_pretend_facilities_url(cls): return reverse("relate-set_pretend_facilities") @classmethod_with_client - def get_set_pretend_facilities(cls, client): # noqa: N805 + def get_set_pretend_facilities(cls, client): # ruff:ignore[invalid-first-argument-name-for-method] return client.get(cls.get_set_pretend_facilities_url()) @classmethod_with_client - def post_set_pretend_facilities(cls, client, data, *, # noqa: N805 + def post_set_pretend_facilities(cls, client, data, *, # ruff:ignore[invalid-first-argument-name-for-method] follow=True): return client.post(cls.get_set_pretend_facilities_url(), data, follow=follow) @@ -596,7 +596,7 @@ def force_remove_all_course_dir(cls): for c in Course.objects.all(): force_remove_path(get_course_repo_path(c)) - def assertSessionPretendFacilitiesContains(self, session, expected_facilities): # noqa + def assertSessionPretendFacilitiesContains(self, session, expected_facilities): # ruff:ignore[invalid-function-name] pretended = session.get("relate_pretend_facilities", None) if expected_facilities is None: return self.assertIsNone(pretended) @@ -610,11 +610,11 @@ def assertSessionPretendFacilitiesContains(self, session, expected_facilities): else: self.assertTrue(expected_facilities in pretended) - def assertSessionPretendFacilitiesIsNone(self, session): # noqa + def assertSessionPretendFacilitiesIsNone(self, session): # ruff:ignore[invalid-function-name] pretended = session.get("relate_pretend_facilities", None) self.assertIsNone(pretended) - def assertFormErrorLoose(self, response, errors, form_name="form"): # noqa + def assertFormErrorLoose(self, response, errors, form_name="form"): # ruff:ignore[invalid-function-name] """Assert that errors is found in response.context['form'] errors""" import itertools if errors is None: @@ -815,7 +815,7 @@ def create_participation( return participation @classmethod_with_client - def post_create_course(cls, client, create_course_kwargs, *, # noqa: N805 + def post_create_course(cls, client, create_course_kwargs, *, # ruff:ignore[invalid-first-argument-name-for-method] raise_error=True, login_superuser=True): # To speed up, use create_course instead, this is better used for tests if login_superuser: @@ -860,7 +860,7 @@ def post_create_course(cls, client, create_course_kwargs, *, # noqa: N805 return resp @classmethod_with_client - def create_course(cls, client, create_course_kwargs, *, # noqa: N805 + def create_course(cls, client, create_course_kwargs, *, # ruff:ignore[invalid-first-argument-name-for-method] raise_error=True): return cls.post_create_course( client, create_course_kwargs, raise_error=raise_error) @@ -881,7 +881,7 @@ def get_set_up_new_course_url(cls): return reverse("relate-set_up_new_course") @classmethod_with_client - def get_set_up_new_course(cls, client): # noqa: N805 + def get_set_up_new_course(cls, client): # ruff:ignore[invalid-first-argument-name-for-method] return client.get(cls.get_update_course_url) @classmethod @@ -891,13 +891,13 @@ def get_edit_course_url(cls, course_identifier=None): return cls.get_course_view_url("relate-edit_course", course_identifier) @classmethod_with_client - def post_edit_course(cls, client, data, *, course=None): # noqa: N805 + def post_edit_course(cls, client, data, *, course=None): # ruff:ignore[invalid-first-argument-name-for-method] course = course or cls.get_default_course() edit_course_url = cls.get_edit_course_url(course.identifier) return client.post(edit_course_url, data) @classmethod_with_client - def get_edit_course(cls, client, *, course=None): # noqa: N805 + def get_edit_course(cls, client, *, course=None): # ruff:ignore[invalid-first-argument-name-for-method] course = course or cls.get_default_course() return client.get(cls.get_edit_course_url(course.identifier)) @@ -929,7 +929,7 @@ def get_my_grades_url(cls, course_identifier=None): return cls._get_grades_url(args=[course_identifier]) @classmethod_with_client - def get_my_grades_view(cls, client, *, course_identifier=None): # noqa: N805 + def get_my_grades_view(cls, client, *, course_identifier=None): # ruff:ignore[invalid-first-argument-name-for-method] return client.get(cls.get_my_grades_url(course_identifier)) @classmethod @@ -942,7 +942,7 @@ def get_participant_grades_url(cls, participation_id, course_identifier=None): @classmethod_with_client def get_participant_grades_view( - cls, client, participation_id, *, # noqa: N805 + cls, client, participation_id, *, # ruff:ignore[invalid-first-argument-name-for-method] course_identifier=None, force_login_instructor=True): course_identifier = ( course_identifier or cls.get_default_course_identifier()) @@ -1001,7 +1001,7 @@ def get_gradebook_by_opp_url( @classmethod_with_client def get_gradebook_by_opp_view( - cls, client, gopp_identifier, *, # noqa: N805 + cls, client, gopp_identifier, *, # ruff:ignore[invalid-first-argument-name-for-method] view_page_grades=False, course_identifier=None, force_login_instructor=True): course_identifier = ( @@ -1017,7 +1017,7 @@ def get_gradebook_by_opp_view( @classmethod_with_client def post_gradebook_by_opp_view( - cls, client, gopp_identifier, post_data, *, # noqa: N805 + cls, client, gopp_identifier, post_data, *, # ruff:ignore[invalid-first-argument-name-for-method] view_page_grades=False, course_identifier=None, force_login_instructor=True): @@ -1054,7 +1054,7 @@ def get_reopen_session_url(cls, gopp_identifier, flow_session_id=None, return reverse("relate-view_reopen_session", kwargs=kwargs) @classmethod_with_client - def get_reopen_session_view(cls, client, # noqa: N805 + def get_reopen_session_view(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] gopp_identifier, *, flow_session_id=None, course_identifier=None, force_login_instructor=True): @@ -1071,7 +1071,7 @@ def get_reopen_session_view(cls, client, # noqa: N805 gopp_identifier, flow_session_id, course_identifier)) @classmethod_with_client - def post_reopen_session_view(cls, client, # noqa: N805 + def post_reopen_session_view(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] gopp_identifier, data, *, flow_session_id=None, course_identifier=None, force_login_instructor=True): @@ -1102,7 +1102,7 @@ def get_single_grade_url(cls, participation_id, opp_id, return reverse("relate-view_single_grade", kwargs=kwargs) @classmethod_with_client - def get_view_single_grade(cls, client, # noqa: N805 + def get_view_single_grade(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] participation, gopp, *, course_identifier=None, force_login_instructor=True): @@ -1123,7 +1123,7 @@ def get_view_single_grade(cls, client, # noqa: N805 participation.pk, opp_id, course_identifier)) @classmethod_with_client - def post_view_single_grade(cls, client, # noqa: N805 + def post_view_single_grade(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] participation, gopp, data, *, course_identifier=None, force_login_instructor=True): @@ -1145,7 +1145,7 @@ def post_view_single_grade(cls, client, # noqa: N805 data=data) @classmethod_with_client - def get_logged_in_user(cls, client): # noqa: N805 + def get_logged_in_user(cls, client): # ruff:ignore[invalid-first-argument-name-for-method] try: logged_in_user_id = client.session["_auth_user_id"] from django.contrib.auth import get_user_model @@ -1156,7 +1156,7 @@ def get_logged_in_user(cls, client): # noqa: N805 return logged_in_user @classmethod_with_client - def temporarily_switch_to_user(cls, client, switch_to): # noqa: N805 + def temporarily_switch_to_user(cls, client, switch_to): # ruff:ignore[invalid-first-argument-name-for-method] return _ClientUserSwitcher( client, cls.get_logged_in_user(client), switch_to) @@ -1220,7 +1220,7 @@ def get_view_start_flow_url(cls, flow_id, course_identifier=None): return reverse("relate-view_start_flow", kwargs=kwargs) @classmethod_with_client - def start_flow(cls, client, flow_id, *, # noqa: N805 + def start_flow(cls, client, flow_id, *, # ruff:ignore[invalid-first-argument-name-for-method] course_identifier=None, ignore_cool_down=True, assume_success=True): """ @@ -1250,7 +1250,7 @@ def start_flow(cls, client, flow_id, *, # noqa: N805 return resp @classmethod_with_client - def end_flow(cls, client, *, # noqa: N805 + def end_flow(cls, client, *, # ruff:ignore[invalid-first-argument-name-for-method] course_identifier=None, flow_session_id=None, post_parameter="submit"): if not course_identifier or not flow_session_id: @@ -1361,7 +1361,7 @@ def get_page_grading_url_by_page_id( page_ordinal, course_identifier, flow_session_id) @classmethod_with_client - def post_answer_by_ordinal(cls, client, # noqa: N805 + def post_answer_by_ordinal(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] page_ordinal, answer_data, *, course_identifier=None, flow_session_id=None, visit_id=None): submit_data = answer_data @@ -1373,7 +1373,7 @@ def post_answer_by_ordinal(cls, client, # noqa: N805 @classmethod_with_client def post_answer_by_page_id( - cls, client, page_id, answer_data, *, # noqa: N805 + cls, client, page_id, answer_data, *, # ruff:ignore[invalid-first-argument-name-for-method] course_identifier=None, flow_session_id=None, visit_id=None): page_ordinal = cls.get_page_ordinal_via_page_id( page_id, course_identifier, flow_session_id) @@ -1383,7 +1383,7 @@ def post_answer_by_page_id( flow_session_id=flow_session_id, visit_id=visit_id) @classmethod_with_client - def post_answer_by_ordinal_class(cls, client, # noqa: N805 + def post_answer_by_ordinal_class(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] page_ordinal, answer_data, course_identifier, flow_session_id): submit_data = answer_data @@ -1397,14 +1397,14 @@ def post_answer_by_ordinal_class(cls, client, # noqa: N805 return client.post(page_url, submit_data) @classmethod_with_client - def post_answer_by_page_id_class(cls, client, # noqa: N805 + def post_answer_by_page_id_class(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] page_id, answer_data, course_identifier, flow_session_id): page_ordinal = get_flow_page_ordinal_from_page_id(flow_session_id, page_id) return cls.post_answer_by_ordinal_class(page_ordinal, answer_data, course_identifier, flow_session_id) @classmethod_with_client - def post_grade_by_ordinal(cls, client, # noqa: N805 + def post_grade_by_ordinal(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] page_ordinal, grade_data, *, course_identifier=None, flow_session_id=None, force_login_instructor=True): @@ -1426,7 +1426,7 @@ def post_grade_by_ordinal(cls, client, # noqa: N805 follow=True) @classmethod_with_client - def post_grade_by_page_id(cls, client, # noqa: N805 + def post_grade_by_page_id(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] page_id, grade_data, *, course_identifier=None, flow_session_id=None, force_login_instructor=True): @@ -1440,7 +1440,7 @@ def post_grade_by_page_id(cls, client, # noqa: N805 force_login_instructor=force_login_instructor) @classmethod - def assertSessionScoreEqual( # noqa + def assertSessionScoreEqual( # ruff:ignore[invalid-function-name] cls, expected_score, course_identifier=None, flow_session_id=None): if flow_session_id is None: flow_params = cls.get_flow_params(course_identifier, flow_session_id) @@ -1477,7 +1477,7 @@ def get_page_grade_history_url_by_ordinal( @classmethod_with_client def get_page_submit_history_by_ordinal( - cls, client, page_ordinal, *, # noqa: N805 + cls, client, page_ordinal, *, # ruff:ignore[invalid-first-argument-name-for-method] course_identifier=None, flow_session_id=None): return client.get( cls.get_page_submit_history_url_by_ordinal( @@ -1486,14 +1486,14 @@ def get_page_submit_history_by_ordinal( @classmethod_with_client def get_page_grade_history_by_ordinal( - cls, client, page_ordinal, *, # noqa: N805 + cls, client, page_ordinal, *, # ruff:ignore[invalid-first-argument-name-for-method] course_identifier=None, flow_session_id=None): return client.get( cls.get_page_grade_history_url_by_ordinal( page_ordinal, course_identifier, flow_session_id), HTTP_X_REQUESTED_WITH="XMLHttpRequest") - def assertSubmitHistoryItemsCount( # noqa + def assertSubmitHistoryItemsCount( # ruff:ignore[invalid-function-name] self, page_ordinal, expected_count, course_identifier=None, flow_session_id=None): resp = self.get_page_submit_history_by_ordinal( @@ -1508,7 +1508,7 @@ def assertSubmitHistoryItemsCount( # noqa assert count == expected_count - def assertGradeHistoryItemsCount( # noqa + def assertGradeHistoryItemsCount( # ruff:ignore[invalid-function-name] self, page_ordinal, expected_count, course_identifier=None, flow_session_id=None, @@ -1548,7 +1548,7 @@ def get_course_commit_sha(cls, participation, course=None): return get_course_commit_sha(course, participation) @classmethod_with_client - def post_update_course_content(cls, client: Client, commit_sha, *, # noqa: N805 + def post_update_course_content(cls, client: Client, commit_sha, *, # ruff:ignore[invalid-first-argument-name-for-method] prevent_discarding_revisions=True, force_login_instructor=True, course: Course | None = None, @@ -1631,7 +1631,7 @@ def download_all_submissions_url(cls, flow_id, course_identifier): return reverse("relate-download_all_submissions", kwargs=params) @classmethod_with_client - def get_download_all_submissions(cls, client, flow_id, *, # noqa: N805 + def get_download_all_submissions(cls, client, flow_id, *, # ruff:ignore[invalid-first-argument-name-for-method] course_identifier=None): if course_identifier is None: course_identifier = cls.get_default_course_identifier() @@ -1641,7 +1641,7 @@ def get_download_all_submissions(cls, client, flow_id, *, # noqa: N805 @classmethod_with_client def post_download_all_submissions_by_group_page_id( - cls, client, # noqa: N805 + cls, client, # ruff:ignore[invalid-first-argument-name-for-method] group_page_id, flow_id, *, course_identifier=None, **kwargs): """ :param group_page_id: format: group_id/page_id @@ -1689,7 +1689,7 @@ def get_flow_page_analytics_url(cls, flow_id, group_id, page_id, return url @classmethod_with_client - def get_flow_page_analytics(cls, client, # noqa: N805 + def get_flow_page_analytics(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] flow_id, group_id, page_id, *, course_identifier=None, force_login_instructor=True, @@ -2110,7 +2110,7 @@ class SingleCourseQuizPageTestMixin(SingleCoursePageTestMixin): skip_code_question = True @classmethod_with_client - def ensure_grading_ui_get(cls, client, page_id): # noqa: N805 + def ensure_grading_ui_get(cls, client, page_id): # ruff:ignore[invalid-first-argument-name-for-method] with cls.temporarily_switch_to_user( client, cls.instructor_participation.user): url = cls.get_page_grading_url_by_page_id(page_id) @@ -2118,7 +2118,7 @@ def ensure_grading_ui_get(cls, client, page_id): # noqa: N805 assert resp.status_code == 200 @classmethod_with_client - def ensure_analytic_page_get(cls, client, group_id, page_id): # noqa: N805 + def ensure_analytic_page_get(cls, client, group_id, page_id): # ruff:ignore[invalid-first-argument-name-for-method] with cls.temporarily_switch_to_user( client, cls.instructor_participation.user): resp = cls.get_flow_page_analytics( @@ -2129,7 +2129,7 @@ def ensure_analytic_page_get(cls, client, group_id, page_id): # noqa: N805 @classmethod_with_client def ensure_download_submission( - cls, client, group_id, page_id, *, # noqa: N805 + cls, client, group_id, page_id, *, # ruff:ignore[invalid-first-argument-name-for-method] dl_file_extension=None, file_with_ext_count=None): with cls.temporarily_switch_to_user( client, cls.instructor_participation.user): @@ -2174,7 +2174,7 @@ def ensure_download_submission( @classmethod_with_client def submit_page_answer_by_ordinal_and_test( - cls, client, page_ordinal, *, # noqa: N805 + cls, client, page_ordinal, *, # ruff:ignore[invalid-first-argument-name-for-method] use_correct_answer=True, answer_data=None, skip_code_question=True, expected_grades=None, expected_post_answer_status_code=200, @@ -2222,7 +2222,7 @@ def submit_page_answer_by_ordinal_and_test( @classmethod_with_client def submit_page_answer_by_page_id_and_test( - cls, client, page_id, *, # noqa: N805 + cls, client, page_id, *, # ruff:ignore[invalid-first-argument-name-for-method] use_correct_answer=True, answer_data=None, skip_code_question=True, expected_grades=None, expected_post_answer_status_code=200, @@ -2376,7 +2376,7 @@ def default_submit_page_answer_by_page_id_and_test(self, page_id, @classmethod_with_client def submit_page_human_grading_by_page_id_and_test( - cls, client, page_id, *, # noqa: N805 + cls, client, page_id, *, # ruff:ignore[invalid-first-argument-name-for-method] expected_post_grading_status_code=200, grade_data=None, expected_grades=None, @@ -2477,7 +2477,7 @@ def _get_added_messages(self, join=True): return "; ".join(msgs) return msgs - def assertAddMessageCallCount(self, expected_call_count, reset=False): # noqa + def assertAddMessageCallCount(self, expected_call_count, reset=False): # ruff:ignore[invalid-function-name] fail_msg = ( "%s is unexpectedly called %d times, instead of %d times." % (self._fake_add_message_path, self._mock_add_message.call_count, @@ -2490,7 +2490,7 @@ def assertAddMessageCallCount(self, expected_call_count, reset=False): # noqa if reset: self._mock_add_message.reset_mock() - def assertAddMessageCalledWith(self, expected_messages, reset=True): # noqa + def assertAddMessageCalledWith(self, expected_messages, reset=True): # ruff:ignore[invalid-function-name] joined_msgs = self._get_added_messages() if not isinstance(expected_messages, list): @@ -2506,7 +2506,7 @@ def assertAddMessageCalledWith(self, expected_messages, reset=True): # noqa if reset: self._mock_add_message.reset_mock() - def assertAddMessageNotCalledWith(self, expected_messages, reset=False): # noqa + def assertAddMessageNotCalledWith(self, expected_messages, reset=False): # ruff:ignore[invalid-function-name] joined_msgs = self._get_added_messages() if not isinstance(expected_messages, list): @@ -2828,7 +2828,7 @@ def get_current_page_ids(self): raise ValueError("Page_ids for that commit_sha doesn't exist") - def assertGradeInfoEqual(self, resp, expected_grade_info_dict=None): # noqa + def assertGradeInfoEqual(self, resp, expected_grade_info_dict=None): # ruff:ignore[invalid-function-name] grade_info = resp.context["grade_info"] assert isinstance(grade_info, GradeInfo) @@ -2843,7 +2843,7 @@ def assertGradeInfoEqual(self, resp, expected_grade_info_dict=None): # noqa assert isinstance(expected_grade_info_dict, dict) grade_info_dict = grade_info.__dict__ - not_match_infos = [f"'{k}' is expected to be {expected_grade_info_dict[k]!s}, while got {grade_info_dict[k]!s}" for k in grade_info_dict if grade_info_dict[k] != expected_grade_info_dict[k]] # noqa: E501 + not_match_infos = [f"'{k}' is expected to be {expected_grade_info_dict[k]!s}, while got {grade_info_dict[k]!s}" for k in grade_info_dict if grade_info_dict[k] != expected_grade_info_dict[k]] # ruff:ignore[line-too-long] if not_match_infos: self.fail("\n".join(not_match_infos)) diff --git a/tests/conftest.py b/tests/conftest.py index 1e94d0219..81db770b8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,12 +10,11 @@ @pytest.fixture def admin_user(): - user = UserFactory.create( + yield UserFactory.create( username="admin", is_staff=True, is_superuser=True, ) - yield user def pytest_addoption(parser): diff --git a/tests/constants.py b/tests/constants.py index a2df54947..f66063893 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -4,7 +4,7 @@ from collections import namedtuple from relate.utils import ( - HTML5_DATETIME_FORMAT as DATE_TIME_PICKER_TIME_FORMAT, # noqa: F401 + HTML5_DATETIME_FORMAT as DATE_TIME_PICKER_TIME_FORMAT, # ruff:ignore[unused-import] ) diff --git a/tests/test_admin.py b/tests/test_admin.py index 9312f3c4e..64bf85e67 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -66,13 +66,13 @@ def navigate_admin_view_by_model( if with_add_view: resp = self.client.get( self.get_admin_course_add_view_url(model_class.__name__)) - self.assertIn(resp.status_code, [200, 403]) # 403 for not implemented # noqa + self.assertIn(resp.status_code, [200, 403]) # 403 for not implemented # ruff:ignore[line-too-long] if with_change_view: resp = self.client.get( self.get_admin_course_change_view_url( model_class.__name__, args=[1])) - self.assertIn(resp.status_code, [200, 302]) # 302 for no objects # noqa + self.assertIn(resp.status_code, [200, 302]) # 302 for no objects def list_filter_result(self, model_class, model_admin_class, expected_counts_dict): diff --git a/tests/test_analytics.py b/tests/test_analytics.py index b430cc1d1..b380388a1 100644 --- a/tests/test_analytics.py +++ b/tests/test_analytics.py @@ -462,7 +462,7 @@ def test_flow_id_does_not_exist(self): resp = self.get_flow_analytics_view(flow_id=self.flow_id) self.assertEqual(resp.status_code, 404) self.assertAddMessageCalledWith( - f"Flow '{self.flow_id}' was not found in the repository, but it exists in " # noqa: E501 + f"Flow '{self.flow_id}' was not found in the repository, but it exists in " # ruff:ignore[line-too-long] "the database--maybe it was deleted?") # vim: fdm=marker diff --git a/tests/test_auth.py b/tests/test_auth.py index 267eedd6c..433f68d34 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -493,14 +493,14 @@ def setUp(self): def get_sign_in_data(self): return self._user_create_kwargs.copy() - def assertNewUserCreated(self, count=1): # noqa + def assertNewUserCreated(self, count=1): # ruff:ignore[invalid-function-name] self.assertEqual(get_user_model().objects.count(), self.existing_user_count + count) - def assertNoNewUserCreated(self): # noqa + def assertNoNewUserCreated(self): # ruff:ignore[invalid-function-name] self.assertEqual(self.existing_user_count, get_user_model().objects.count()) - def assertURLEqual(self, url, expected, parse_qs=False): # noqa + def assertURLEqual(self, url, expected, parse_qs=False): # ruff:ignore[invalid-function-name] """ Given two URLs, make sure all their components (the ones given by urlparse) are equal, only comparing components that are present in both @@ -562,10 +562,10 @@ def do_test_security_check(self, url_name): self.assertIn(good_url, response.url, f"{good_url} should be allowed") - def assertSessionHasUserLoggedIn(self): # noqa + def assertSessionHasUserLoggedIn(self): # ruff:ignore[invalid-function-name] self.assertIn(SESSION_KEY, self.client.session) - def assertSessionHasNoUserLoggedIn(self): # noqa + def assertSessionHasNoUserLoggedIn(self): # ruff:ignore[invalid-function-name] self.assertNotIn(SESSION_KEY, self.client.session) def concatenate_redirect_url(self, url, redirect_to=None): @@ -1038,7 +1038,7 @@ def test_signup_existing_email(self): expected_msg = ( "That email address is already in use. " "Would you like to " - "reset your password instead?".format(reverse("relate-reset_password"))) # noqa: E501 + "reset your password instead?".format(reverse("relate-reset_password"))) # ruff:ignore[line-too-long] data = self.get_sign_up_user_dict() data["email"] = self.test_user.email @@ -1531,7 +1531,7 @@ def test_profile_page_hide_institutional_id_or_editor_mode(self): field_div_with_id_pattern = ( r".*(]*id\s*=\s*['\"]div_id_%s['\"][^>]*\/?>).*") - def assertFieldDiv(field_name, exist=True): # noqa + def assertFieldDiv(field_name, exist=True): # ruff:ignore[invalid-function-name] resp = self.get_profile_by_request_factory() self.assertEqual(resp.status_code, 200) pattern = field_div_with_id_pattern % field_name @@ -1751,10 +1751,10 @@ def setUp(self): self.client.logout() self.user.refresh_from_db() - def assertHasUserLoggedIn(self, user): # noqa + def assertHasUserLoggedIn(self, user): # ruff:ignore[invalid-function-name] self.assertEqual(self.get_logged_in_user(), user) - def assertHasNoUserLoggedIn(self): # noqa + def assertHasNoUserLoggedIn(self): # ruff:ignore[invalid-function-name] self.assertIsNone(self.get_logged_in_user()) @override_settings(RELATE_REGISTRATION_ENABLED=False) diff --git a/tests/test_checks.py b/tests/test_checks.py index 5a26f1212..132243925 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -47,7 +47,7 @@ def func(self): def msg_id_prefix(self): raise NotImplementedError() - def assertCheckMessages(self, # noqa + def assertCheckMessages(self, # ruff:ignore[invalid-function-name] expected_ids=None, expected_msgs=None, length=None, filter_message_id_prefixes=None, ignore_order=False): """ diff --git a/tests/test_content.py b/tests/test_content.py index 46a4e19a7..ad1a9a2e7 100644 --- a/tests/test_content.py +++ b/tests/test_content.py @@ -68,7 +68,7 @@ def setUpTestData(cls): def test_disable_cache(self, mock_cache): from django.core.exceptions import ImproperlyConfigured with self.assertRaises(ImproperlyConfigured): - from django.core.cache import cache # noqa + from django.core.cache import cache # ruff:ignore[unused-import] def test_view_flow_with_cache(self): resp = self.client.get(self.get_page_url_by_ordinal(0)) @@ -390,7 +390,7 @@ def test(self): ## object data -""" # noqa +""" # ruff:ignore[line-too-long] class TagProcessingHTMLParserAndLinkFixerTreeprocessorTest( diff --git a/tests/test_enrollment.py b/tests/test_enrollment.py index 36cfd3847..66cfcfc1e 100644 --- a/tests/test_enrollment.py +++ b/tests/test_enrollment.py @@ -30,7 +30,7 @@ from django.contrib.auth import get_user_model from django.core import mail from django.test import RequestFactory, TestCase -from django.test.utils import override_settings # noqa +from django.test.utils import override_settings # ruff:ignore[unused-import] from django.urls import reverse from course import constants, enrollment @@ -164,7 +164,7 @@ def get_test_preapproval(self, **kwargs): return factories.ParticipationPreapprovalFactory(**defaults) - def assertParticipationStatusCallCount(self, expected_counts): # noqa + def assertParticipationStatusCallCount(self, expected_counts): # ruff:ignore[invalid-function-name] from collections import OrderedDict d = OrderedDict() counts = [] @@ -1253,7 +1253,7 @@ def test_create_preapproval_inst_id_handle_pending_require_verified(self): course=self.course, user=user1, status=PStatus.requested) factories.ParticipationFactory( course=self.course, user=user2, status=PStatus.requested) - approval_data = f"{user1.institutional_id.upper()}\n \ncde \n {user2.institutional_id}\n" # noqa: E501 + approval_data = f"{user1.institutional_id.upper()}\n \ncde \n {user2.institutional_id}\n" # ruff:ignore[line-too-long] resp = self.post_preapproval( "institutional_id", @@ -1302,7 +1302,7 @@ def test_create_preapproval_inst_id_handle_pending(self): course=self.course, user=user1, status=PStatus.requested) factories.ParticipationFactory( course=self.course, user=user2, status=PStatus.requested) - approval_data = f"{user1.institutional_id}\n \ncde \n {user2.institutional_id}\n" # noqa: E501 + approval_data = f"{user1.institutional_id}\n \ncde \n {user2.institutional_id}\n" # ruff:ignore[line-too-long] resp = self.post_preapproval( "institutional_id", @@ -1799,7 +1799,7 @@ def test_parentheses(self): def test_multiple_line(self): queries = ( - f"id:{self.participations[0].user.id}\n \n id:{self.participations[2].user.id}") # noqa: E501 + f"id:{self.participations[0].user.id}\n \n id:{self.participations[2].user.id}") # ruff:ignore[line-too-long] resp = self.post_query_participation(queries) self.assertEqual(resp.status_code, 200) diff --git a/tests/test_flow/test_flow.py b/tests/test_flow/test_flow.py index 61a1b532d..d23d1d537 100644 --- a/tests/test_flow/test_flow.py +++ b/tests/test_flow/test_flow.py @@ -3533,18 +3533,18 @@ class GetPageBehaviorTest(unittest.TestCase): def setUp(self): self.page = mock.MagicMock() - def assertShowCorrectness(self, behavior, perms, show=True): # noqa + def assertShowCorrectness(self, behavior, perms, show=True): # ruff:ignore[invalid-function-name] self.assertEqual( behavior.show_correctness, show, "behavior.show_correctness unexpected to be {} with {}" .format(not show, ", ".join(perms))) - def assertShowAnswer(self, behavior, perms, show=True): # noqa + def assertShowAnswer(self, behavior, perms, show=True): # ruff:ignore[invalid-function-name] self.assertEqual(behavior.show_answer, show, "behavior.show_answer unexpected to be {} with {}" .format(not show, ", ".join(perms))) - def assertMayChangeAnswer(self, behavior, perms, may_change=True): # noqa + def assertMayChangeAnswer(self, behavior, perms, may_change=True): # ruff:ignore[invalid-function-name] self.assertEqual(behavior.may_change_answer, may_change, "behavior.may_change_answer unexpected to be {} with {}" .format(not may_change, ", ".join(perms))) diff --git a/tests/test_grades/test_csv.py b/tests/test_grades/test_csv.py index bf07e4191..f2d83d4a8 100644 --- a/tests/test_grades/test_csv.py +++ b/tests/test_grades/test_csv.py @@ -36,7 +36,9 @@ from tests import factories from tests.base_test_mixins import CoursesTestMixinBase from tests.constants import CSV_PATH -from tests.factories import GradeChangeFactory as gc_factory # noqa +from tests.factories import ( + GradeChangeFactory as gc_factory, # ruff:ignore[camelcase-imported-as-lowercase] +) from tests.test_grades.test_grades import GradesTestMixin from tests.utils import mock @@ -68,13 +70,13 @@ def setUp(self): self.instructor_gc.refresh_from_db() self.student_gc.refresh_from_db() - def assertResponseCsvResultEqual(self, resp, expected_result): # noqa + def assertResponseCsvResultEqual(self, resp, expected_result): # ruff:ignore[invalid-function-name] file_contents = StringIO(resp.content.decode()) spamreader = csv.reader(file_contents) result = list(spamreader) self.assertEqual(result, expected_result) - def assertResponseHasCsv(self, resp): # noqa + def assertResponseHasCsv(self, resp): # ruff:ignore[invalid-function-name] self.assertEqual(resp["Content-Disposition"], f'attachment; filename="grades-{self.course.identifier}.csv"') @@ -233,7 +235,7 @@ def test_not_found_across_course(self): self.course, "username", another_participation.user.username) expected_error_msg = ( - f"no participant found with username '{another_participation.user.username}'") # noqa: E501 + f"no participant found with username '{another_participation.user.username}'") # ruff:ignore[line-too-long] self.assertIn(expected_error_msg, str(cm.exception)) def test_skip_not_active(self): @@ -245,7 +247,7 @@ def test_skip_not_active(self): self.course, "username", dropped_participation.user.username) expected_error_msg = ( - f"no participant found with username '{dropped_participation.user.username}'") # noqa: E501 + f"no participant found with username '{dropped_participation.user.username}'") # ruff:ignore[line-too-long] self.assertIn(expected_error_msg, str(cm.exception)) def test_multiple_found(self): @@ -260,7 +262,7 @@ def test_multiple_found(self): another_student_participation.user.institutional_id) expected_error_msg = ( - f"more than one participant found with Institutional ID '{another_student_participation.user.institutional_id}'") # noqa: E501 + f"more than one participant found with Institutional ID '{another_student_participation.user.institutional_id}'") # ruff:ignore[line-too-long] self.assertIn(expected_error_msg, str(cm.exception)) diff --git a/tests/test_grades/test_generic.py b/tests/test_grades/test_generic.py index 36e5bb30e..da3c494d7 100644 --- a/tests/test_grades/test_generic.py +++ b/tests/test_grades/test_generic.py @@ -46,7 +46,7 @@ def setUpTestData(cls): # Use specified user to take a quiz @classmethod_with_client - def do_quiz(cls, client, participation): # noqa: N805 + def do_quiz(cls, client, participation): # ruff:ignore[invalid-first-argument-name-for-method] # Login user first client.force_login(participation.user) cls.start_flow(client, cls.flow_id) @@ -306,7 +306,7 @@ class GradeTwoQuizTakerTest(GradeGenericTestMixin, TestCase): force_login_student_for_each_test = False @classmethod - def setUpTestData(cls): # noqa + def setUpTestData(cls): # ruff:ignore[too-few-spaces-before-inline-comment] super().setUpTestData() client = Client() @@ -326,7 +326,7 @@ class GradeThreeQuizTakerTest(GradeGenericTestMixin, TestCase): force_login_student_for_each_test = False @classmethod - def setUpTestData(cls): # noqa + def setUpTestData(cls): # ruff:ignore[too-few-spaces-before-inline-comment] super().setUpTestData() client = Client() cls.do_quiz(client, cls.ta_participation) diff --git a/tests/test_grades/test_grades.py b/tests/test_grades/test_grades.py index 6b9c2ea5c..6ced9a4f8 100644 --- a/tests/test_grades/test_grades.py +++ b/tests/test_grades/test_grades.py @@ -149,14 +149,14 @@ def update_gopp_strategy(self, strategy=None): self.gopp.save() self.gopp.refresh_from_db() - def assertGradeChangeStateEqual(self, expected_state_string=None): # noqa + def assertGradeChangeStateEqual(self, expected_state_string=None): # ruff:ignore[invalid-function-name] # targeting stringify_state state_string = self.get_gc_stringify_state() from django.utils.encoding import force_str self.assertEqual(force_str(state_string), expected_state_string) - def assertGradeChangeMachineReadableStateEqual(self, expected_state_string=None): # noqa + def assertGradeChangeMachineReadableStateEqual(self, expected_state_string=None): # ruff:ignore[invalid-function-name] # targeting stringify_machine_readable_state state_string = self.get_gc_stringify_machine_readable_state() from decimal import Decimal, InvalidOperation @@ -332,7 +332,7 @@ def test_view(self): self.assertFalse(resp.context["is_privileged_view"]) self.assertContains(resp, "60.0%", count=1) # for shown_gopp self.assertNotContains(resp, "40.0%") # for hidden_gopp - self.assertContains(resp, "(not released)", count=2) # for hidden_gopp # noqa + self.assertContains(resp, "(not released)", count=2) # for hidden_gopp user = self.ta_participation.user with self.temporarily_switch_to_user(user), self.subTest(user=str(user)): @@ -1872,7 +1872,7 @@ def group_page_id(self): def get_zip_file_buf_from_response(self, resp): return io.BytesIO(resp.content) - def assertDownloadedFileZippedExtensionCount(self, resp, extensions, counts): # noqa + def assertDownloadedFileZippedExtensionCount(self, resp, extensions, counts): # ruff:ignore[invalid-function-name] assert isinstance(extensions, list) assert isinstance(counts, list) diff --git a/tests/test_misc.py b/tests/test_misc.py index 24ac1fb06..1e85e477f 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -81,10 +81,10 @@ def response_contains_korean(self, resp): # Korean literals for 12th month (December) return "12월" in resp.content.decode("utf-8") - def assertResponseContainsChinese(self, resp): # noqa + def assertResponseContainsChinese(self, resp): # ruff:ignore[invalid-function-name] self.assertTrue(self.response_contains_korean(resp)) - def assertResponseNotContainsChinese(self, resp): # noqa + def assertResponseNotContainsChinese(self, resp): # ruff:ignore[invalid-function-name] self.assertFalse(self.response_contains_korean(resp)) # }}} @@ -141,7 +141,7 @@ def setUp(self): "set": [""]} self.post_set_fake_time(set_fake_time_data) - def assertResponseBehaveLikeUnconfigured(self): # noqa + def assertResponseBehaveLikeUnconfigured(self): # ruff:ignore[invalid-function-name] # For each setting combinations, the response behaves the same # as before this functionality was introduced expected_result = ([False, True, False, True], @@ -171,7 +171,7 @@ def assertResponseBehaveLikeUnconfigured(self): # noqa ASSERTION_ERROR_CONTENT_LANGUAGE_PATTERN % "Course" ) - def assertResponseBehaveAsExpectedForCourseWithForceLang(self): # noqa + def assertResponseBehaveAsExpectedForCourseWithForceLang(self): # ruff:ignore[invalid-function-name] # For each setting combinations, the response behaves as expected expected_result = ([False, True, False, True], ["en", "ko", "en", "ko"]) diff --git a/tests/test_pages/test_choice.py b/tests/test_pages/test_choice.py index 4d139eb45..98c44adb6 100644 --- a/tests/test_pages/test_choice.py +++ b/tests/test_pages/test_choice.py @@ -433,12 +433,12 @@ def test_choice_item_with_always_correct(self): self.maxDiff = None self.assertResponseContextEqual( resp, "correct_answer", - '

Sprinkles

\n' # noqa: E501 - '

Chocolate chunks

\n' # noqa: E501 - '

Vacuum cleaner dust

\n' # noqa: E501 - '

Spider webs

\n' # noqa: E501 - '

Almond bits

\n' # noqa: E501 - '

A flawed option

') # noqa: E501 + '

Sprinkles

\n' # ruff:ignore[line-too-long] + '

Chocolate chunks

\n' # ruff:ignore[line-too-long] + '

Vacuum cleaner dust

\n' # ruff:ignore[line-too-long] + '

Spider webs

\n' # ruff:ignore[line-too-long] + '

Almond bits

\n' # ruff:ignore[line-too-long] + '

A flawed option

') # ruff:ignore[line-too-long] # }}} @@ -454,11 +454,11 @@ def test_correct_answer_shows_all_choices_with_icons(self): self.assertSandboxHasValidPage(resp) self.assertResponseContextEqual( resp, "correct_answer", - '

Sprinkles

\n' # noqa: E501 - '

Chocolate chunks

\n' # noqa: E501 - '

Vacuum cleaner dust

\n' # noqa: E501 - '

Spider webs

\n' # noqa: E501 - '

Almond bits

') # noqa: E501 + '

Sprinkles

\n' # ruff:ignore[line-too-long] + '

Chocolate chunks

\n' # ruff:ignore[line-too-long] + '

Vacuum cleaner dust

\n' # ruff:ignore[line-too-long] + '

Spider webs

\n' # ruff:ignore[line-too-long] + '

Almond bits

') # ruff:ignore[line-too-long] def test_correct_answer_disregard_excluded(self): # Tests that ~DISREGARD~ choices are excluded from the correct answer display. diff --git a/tests/test_pages/test_code.py b/tests/test_pages/test_code.py index 372c3b003..1cc86718a 100644 --- a/tests/test_pages/test_code.py +++ b/tests/test_pages/test_code.py @@ -314,7 +314,7 @@ def test_question_without_correct_code(self): self.assertEqual(resp.status_code, 200) self.assertResponseContextAnswerFeedbackCorrectnessEquals(resp, 1) - def test_question_with_human_feedback_neither_feedback_value_feedback_percentage_present(self): # noqa + def test_question_with_human_feedback_neither_feedback_value_feedback_percentage_present(self): # ruff:ignore[line-too-long] markdown = (markdowns.CODE_WITH_HUMAN_FEEDBACK_MARKDOWN_PATTERN % {"value": 3, "human_feedback": "", @@ -419,7 +419,7 @@ def test_request_run_with_retries_raise_uncaught_error(self): self.assertEqual(len(mail.outbox), 1) self.assertIn(expected_error_str, mail.outbox[0].body) - def test_send_email_failure_when_request_run_with_retries_raise_uncaught_error(self): # noqa + def test_send_email_failure_when_request_run_with_retries_raise_uncaught_error(self): # ruff:ignore[line-too-long] with mock.patch( RUNCODE_WITH_RETRIES_PATH, autospec=True @@ -437,7 +437,7 @@ def test_send_email_failure_when_request_run_with_retries_raise_uncaught_error(s # will cause errors ..." mock_page_context.return_value.commit_sha = b"1234" - with mock.patch("django.core.mail.message.EmailMessage.send") as mock_send: # noqa + with mock.patch("django.core.mail.message.EmailMessage.send") as mock_send: # ruff:ignore[line-too-long] mock_send.side_effect = RuntimeError("some email send error") resp = self.get_page_sandbox_submit_answer_response( @@ -561,10 +561,10 @@ def test_figures(self): "2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmq" "srO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T" "19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xA" - "C1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQp" # spellchecker: disable-line # noqa: E501 - "GhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdIS" # spellchecker: disable-line # noqa: E501 + "C1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQp" # spellchecker: disable-line # ruff:ignore[line-too-long] + "GhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdIS" # spellchecker: disable-line # ruff:ignore[line-too-long] "UpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeY" - "mZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+T" # spellchecker: disable-line # noqa: E501 + "mZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+T" # spellchecker: disable-line # ruff:ignore[line-too-long] "l5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AP38ooooA//Z") png_b64 = ( "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAQMAAAB" diff --git a/tests/test_pages/test_text.py b/tests/test_pages/test_text.py index 15c0fe999..94c7d8743 100644 --- a/tests/test_pages/test_text.py +++ b/tests/test_pages/test_text.py @@ -268,8 +268,8 @@ def test_float_or_sympy_evalf(self): assert float_or_sympy_evalf(1) == 1 assert float_or_sympy_evalf(-1) == -1 assert float_or_sympy_evalf(0) == 0 - assert float_or_sympy_evalf(-0.2) == -0.2 # noqa: RUF069 - assert float_or_sympy_evalf(-0.333) == -0.333 # noqa: RUF069 + assert float_or_sympy_evalf(-0.2) == -0.2 # ruff:ignore[float-equality-comparison] + assert float_or_sympy_evalf(-0.333) == -0.333 # ruff:ignore[float-equality-comparison] assert float_or_sympy_evalf("inf") == float("inf") def test_float_or_sympy_evalf_value_empty(self): diff --git a/tests/test_postgres.py b/tests/test_postgres.py index b7cf7ad8e..86a22bcd7 100644 --- a/tests/test_postgres.py +++ b/tests/test_postgres.py @@ -30,7 +30,11 @@ from relate.utils import retry_transaction_decorator from tests import factories from tests.base_test_mixins import HackRepoMixin, SingleCourseQuizPageTestMixin -from tests.utils import SKIP_NON_PSQL_REASON, is_connection_psql, mock # noqa +from tests.utils import ( # ruff:ignore[unused-import] + SKIP_NON_PSQL_REASON, + is_connection_psql, + mock, +) @pytest.mark.postgres diff --git a/tests/test_sandbox.py b/tests/test_sandbox.py index bfd3a1ac1..e1085c3c5 100644 --- a/tests/test_sandbox.py +++ b/tests/test_sandbox.py @@ -104,13 +104,13 @@ def get_page_sandbox_url(cls): return reverse("relate-view_page_sandbox", args=[cls.course.identifier]) @classmethod_with_client - def get_page_sandbox_post_response(cls, client, data, action): # noqa: N805 + def get_page_sandbox_post_response(cls, client, data, action): # ruff:ignore[invalid-first-argument-name-for-method] post_data = {action: ""} post_data.update(data) return client.post(cls.get_page_sandbox_url(), post_data) @classmethod_with_client - def get_page_sandbox_preview_response(cls, client, markup_content): # noqa: N805 + def get_page_sandbox_preview_response(cls, client, markup_content): # ruff:ignore[invalid-first-argument-name-for-method] """ Get the preview response of content in page sandbox :param markup_content: :class:`String`, RELATE flavored page markdown @@ -120,7 +120,7 @@ def get_page_sandbox_preview_response(cls, client, markup_content): # noqa: N80 return cls.get_page_sandbox_post_response(client, data, action="preview") @classmethod_with_client - def get_page_sandbox_submit_answer_response(cls, client, # noqa: N805 + def get_page_sandbox_submit_answer_response(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] markup_content, answer_data): """ Get the response of preview content and then post an answer, in page sandbox @@ -146,10 +146,10 @@ def get_sandbox_answer_data(self): def get_sandbox_page_session(self): return self.get_sandbox_data_by_key(PAGE_SESSION_KEY_PREFIX) - def assertSandboxHasValidPage(self, resp: HttpResponse): # noqa + def assertSandboxHasValidPage(self, resp: HttpResponse): # ruff:ignore[invalid-function-name] self.assertResponseContextEqual(resp, HAVE_VALID_PAGE, True) - def assertSandboxWarningTextContain(self, # noqa: N802 + def assertSandboxWarningTextContain(self, # ruff:ignore[invalid-function-name] resp: HttpResponse, expected_text: str | None, loose: bool = False @@ -164,7 +164,7 @@ def assertSandboxWarningTextContain(self, # noqa: N802 warnings_strs = "".join(warnings_strs) self.assertIn(expected_text, warnings_strs) - def assertSandboxNotHasValidPage(self, resp): # noqa + def assertSandboxNotHasValidPage(self, resp): # ruff:ignore[invalid-function-name] self.assertResponseContextEqual(resp, HAVE_VALID_PAGE, False) @classmethod @@ -172,11 +172,11 @@ def get_markup_sandbox_url(cls): return reverse("relate-view_markup_sandbox", args=[cls.course.identifier]) @classmethod_with_client - def get_markup_sandbox_view(cls, client): # noqa: N805 + def get_markup_sandbox_view(cls, client): # ruff:ignore[invalid-first-argument-name-for-method] return client.get(cls.get_markup_sandbox_url()) @classmethod_with_client - def post_markup_sandbox_view(cls, client, # noqa: N805 + def post_markup_sandbox_view(cls, client, # ruff:ignore[invalid-first-argument-name-for-method] markup_content, *, action="preview"): post_data = { "content": markup_content, diff --git a/tests/test_utils.py b/tests/test_utils.py index 58038803d..056f9b74b 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -64,13 +64,13 @@ if DJANGO_VERSION < (2, 0): REAL_TRANSLATION_FUNCTION_TO_MOCK = ( "django.utils.translation.trans_real.do_translate") - real_trans_side_effect = lambda x, y: x # noqa + real_trans_side_effect = lambda x, y: x # ruff:ignore[lambda-assignment] else: # "do_translate(message, translation_function)" was refactored to # "gettext(message)" since Django >= 2.0 REAL_TRANSLATION_FUNCTION_TO_MOCK = ( "django.utils.translation._trans.gettext") - real_trans_side_effect = lambda x: x # noqa + real_trans_side_effect = lambda x: x # ruff:ignore[lambda-assignment] class GetCourseSpecificLanguageChoicesTest(SimpleTestCase): @@ -837,7 +837,7 @@ def fallback_rule(self): def get_result(self, **extra_kwargs): raise NotImplementedError() - def assertRuleEqual(self, rule, expected_rule): # noqa + def assertRuleEqual(self, rule, expected_rule): # ruff:ignore[invalid-function-name] self.assertIsInstance(rule, self.rule_klass) rule_dict = rule @@ -1477,7 +1477,7 @@ def test_if_completed_before_passed_not_using_last_activity(self): result = self.get_result(flow_desc=self.get_hacked_flow_desc()) self.assertRuleEqual(result, self.get_default_rule()) - def test_if_completed_before_using_last_activity_with_last_activity_none_skipped(self): # noqa + def test_if_completed_before_using_last_activity_with_last_activity_none_skipped(self): # ruff:ignore[line-too-long] self.mock_get_flow_rules.return_value = [ {"if_completed_before": "my_test_event 1", diff --git a/tests/test_versioning.py b/tests/test_versioning.py index ec8c61917..9d112972c 100644 --- a/tests/test_versioning.py +++ b/tests/test_versioning.py @@ -694,7 +694,7 @@ def test_is_ancestor_commit_checked(self): "be called while not") elif not will_check and self.mock_is_ancestor_commit.call_count > 0: self.fail( - f"'is_ancestor_commit' is not expected for command '{command}' to " # noqa: E501 + f"'is_ancestor_commit' is not expected for command '{command}' to " # ruff:ignore[line-too-long] "be called while called") # when not prevent_discarding_revisions, is_ancestor_commit @@ -712,11 +712,11 @@ def test_is_ancestor_commit_checked(self): may_update, prevent_discarding_revisions) if self.mock_is_ancestor_commit.call_count > 0: self.fail( - f"'is_ancestor_commit' is not expected for command '{command}' to " # noqa: E501 + f"'is_ancestor_commit' is not expected for command '{command}' to " # ruff:ignore[line-too-long] "be called while called (expensive)") elif self.mock_is_ancestor_commit.call_count > 0: self.fail( - f"'is_ancestor_commit' is not expected for command '{command}' to " # noqa: E501 + f"'is_ancestor_commit' is not expected for command '{command}' to " # ruff:ignore[line-too-long] "be called while called") def test_is_content_validated(self): diff --git a/tests/test_views.py b/tests/test_views.py index 581680843..1dad8dc8e 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1928,7 +1928,7 @@ def test_create_grading_exception_due_same_as_access_expiration(self): self.assertAddMessageCallCount(1) self.assertAddMessageCalledWith("'Grading' exception granted to ") - def test_create_grading_exception_due_same_as_access_expiration_while_expiration_not_set(self): # noqa + def test_create_grading_exception_due_same_as_access_expiration_while_expiration_not_set(self): # ruff:ignore[line-too-long] due = as_local_time(now() + timedelta(days=5)) resp = self.post_grant_exception_stage_3_view( data=self.get_default_post_data( diff --git a/tests/utils.py b/tests/utils.py index 4ee3e91cf..92f3ac6f6 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -5,7 +5,7 @@ from importlib import import_module, reload from io import StringIO from typing import TYPE_CHECKING -from unittest import mock # noqa: F401 +from unittest import mock # ruff:ignore[unused-import] from django.conf import settings from django.core import mail @@ -34,7 +34,7 @@ def setUp(self): self.email_backend_settings_override.enable() self.addCleanup(self.email_backend_settings_override.disable) - def assertStartsWith(self, first, second): # noqa + def assertStartsWith(self, first, second): # ruff:ignore[invalid-function-name] if not first.startswith(second): self.longMessage = True self.assertEqual(first[:len(second)], second, @@ -109,7 +109,7 @@ def tearDown(self): # }}} -class suppress_stdout_decorator: # noqa +class suppress_stdout_decorator: # ruff:ignore[invalid-class-name] def __init__(self, suppress_stderr=False): self.original_stdout = None self.suppress_stderr = None From 401f6eeeb45d59e01a88850ba5ac4297b5604d63 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 16 Jul 2026 14:11:41 -0500 Subject: [PATCH 4/4] bpr: do not report unused imports (covered by ruff) --- local_settings_example.py | 2 +- pyproject.toml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/local_settings_example.py b/local_settings_example.py index 49d86cb14..d6306b017 100644 --- a/local_settings_example.py +++ b/local_settings_example.py @@ -1,6 +1,6 @@ # See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/ -import os # ruff:ignore[unused-import] # pyright: ignore[reportUnusedImport] +import os # ruff:ignore[unused-import] from os import path diff --git a/pyproject.toml b/pyproject.toml index fae24caa6..7e03c971e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -318,6 +318,9 @@ reportImportCycles = "none" pythonVersion = "3.11" pythonPlatform = "All" +# covered by ruff +reportUnusedImport = "none" + reportAny = "none" # for Sentinel