From ac3160d6d4b26ebeecf44f0f30259ea7c38be7ce Mon Sep 17 00:00:00 2001 From: Albert Hopkins Date: Fri, 21 Feb 2025 00:44:54 -0600 Subject: [PATCH] tests: update to the latest unittest-fixtures --- pdm.lock | 505 +++++++++++++++++-------------- tests/test_cli_addmachine.py | 16 +- tests/test_cli_addrepo.py | 18 +- tests/test_cli_apikey.py | 66 ++-- tests/test_cli_check.py | 52 ++-- tests/test_cli_delete.py | 43 +-- tests/test_cli_worker.py | 14 +- tests/test_fs.py | 90 +++--- tests/test_graphql.py | 343 +++++++++++---------- tests/test_jenkins.py | 54 ++-- tests/test_machines.py | 53 ++-- tests/test_publisher.py | 139 ++++----- tests/test_purge.py | 50 +-- tests/test_records.py | 44 +-- tests/test_records_django_orm.py | 205 ++++++------- tests/test_storage.py | 294 +++++++++--------- tests/test_views.py | 98 +++--- tests/test_views_context.py | 55 ++-- tests/test_views_utils.py | 36 +-- tests/test_workers.py | 71 ++--- 20 files changed, 1151 insertions(+), 1095 deletions(-) diff --git a/pdm.lock b/pdm.lock index e173983..a36896e 100644 --- a/pdm.lock +++ b/pdm.lock @@ -51,16 +51,17 @@ files = [ [[package]] name = "ariadne" -version = "0.24.0" +version = "0.26.1" +requires_python = ">=3.9" summary = "Ariadne is a Python library for implementing GraphQL servers." dependencies = [ - "graphql-core<3.3,>=3.2.0", + "graphql-core<3.2.6,>=3.2.0", "starlette<1.0,>0.17", "typing-extensions>=3.6.0", ] files = [ - {file = "ariadne-0.24.0-py2.py3-none-any.whl", hash = "sha256:aee510e72954a84052c0705b5ed8db7f6ff82d782b9a0a8ead58b4776e3246c9"}, - {file = "ariadne-0.24.0.tar.gz", hash = "sha256:6ea3f53d7e54d83b011e5697795ab7f8a713cb5f9423d6849e43a84f2fe81293"}, + {file = "ariadne-0.26.1-py3-none-any.whl", hash = "sha256:9ca98d47b42e274a8b86286e1f3e22d6ce87b699bbab05d7a24c6d22a3ea690d"}, + {file = "ariadne-0.26.1.tar.gz", hash = "sha256:3b609ce656104d99d2af198cad266a88adf4d4c2a247f943e8c5034e73b4c89e"}, ] [[package]] @@ -112,6 +113,16 @@ files = [ {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, ] +[[package]] +name = "attrs" +version = "25.1.0" +requires_python = ">=3.8" +summary = "Classes Without Boilerplate" +files = [ + {file = "attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"}, + {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"}, +] + [[package]] name = "billiard" version = "4.2.1" @@ -124,7 +135,7 @@ files = [ [[package]] name = "black" -version = "24.10.0" +version = "25.1.0" requires_python = ">=3.9" summary = "The uncompromising code formatter." dependencies = [ @@ -137,20 +148,20 @@ dependencies = [ "typing-extensions>=4.0.1; python_version < \"3.11\"", ] files = [ - {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, - {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, - {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, - {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, - {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, - {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, - {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, - {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, - {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, - {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, - {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, - {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, - {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, - {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, + {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, + {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, + {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, + {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, + {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, + {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, + {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, + {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, + {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, + {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, + {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, + {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, + {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, + {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, ] [[package]] @@ -206,12 +217,12 @@ files = [ [[package]] name = "certifi" -version = "2024.12.14" +version = "2025.1.31" requires_python = ">=3.6" summary = "Python package for providing Mozilla's CA Bundle." files = [ - {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, - {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, + {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, + {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, ] [[package]] @@ -387,137 +398,157 @@ files = [ [[package]] name = "coverage" -version = "7.6.10" +version = "7.6.12" requires_python = ">=3.9" summary = "Code coverage measurement for Python" files = [ - {file = "coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3"}, - {file = "coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43"}, - {file = "coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132"}, - {file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f"}, - {file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994"}, - {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99"}, - {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd"}, - {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377"}, - {file = "coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8"}, - {file = "coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609"}, - {file = "coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853"}, - {file = "coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078"}, - {file = "coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0"}, - {file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50"}, - {file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022"}, - {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b"}, - {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0"}, - {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852"}, - {file = "coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359"}, - {file = "coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247"}, - {file = "coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9"}, - {file = "coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b"}, - {file = "coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690"}, - {file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18"}, - {file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c"}, - {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd"}, - {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e"}, - {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694"}, - {file = "coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6"}, - {file = "coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e"}, - {file = "coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe"}, - {file = "coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273"}, - {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8"}, - {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098"}, - {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb"}, - {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0"}, - {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf"}, - {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2"}, - {file = "coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312"}, - {file = "coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d"}, - {file = "coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23"}, + {file = "coverage-7.6.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e18aafdfb3e9ec0d261c942d35bd7c28d031c5855dadb491d2723ba54f4c3015"}, + {file = "coverage-7.6.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66fe626fd7aa5982cdebad23e49e78ef7dbb3e3c2a5960a2b53632f1f703ea45"}, + {file = "coverage-7.6.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ef01d70198431719af0b1f5dcbefc557d44a190e749004042927b2a3fed0702"}, + {file = "coverage-7.6.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e92ae5a289a4bc4c0aae710c0948d3c7892e20fd3588224ebe242039573bf0"}, + {file = "coverage-7.6.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e695df2c58ce526eeab11a2e915448d3eb76f75dffe338ea613c1201b33bab2f"}, + {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d74c08e9aaef995f8c4ef6d202dbd219c318450fe2a76da624f2ebb9c8ec5d9f"}, + {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e995b3b76ccedc27fe4f477b349b7d64597e53a43fc2961db9d3fbace085d69d"}, + {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b1f097878d74fe51e1ddd1be62d8e3682748875b461232cf4b52ddc6e6db0bba"}, + {file = "coverage-7.6.12-cp311-cp311-win32.whl", hash = "sha256:1f7ffa05da41754e20512202c866d0ebfc440bba3b0ed15133070e20bf5aeb5f"}, + {file = "coverage-7.6.12-cp311-cp311-win_amd64.whl", hash = "sha256:e216c5c45f89ef8971373fd1c5d8d1164b81f7f5f06bbf23c37e7908d19e8558"}, + {file = "coverage-7.6.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b172f8e030e8ef247b3104902cc671e20df80163b60a203653150d2fc204d1ad"}, + {file = "coverage-7.6.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:641dfe0ab73deb7069fb972d4d9725bf11c239c309ce694dd50b1473c0f641c3"}, + {file = "coverage-7.6.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e549f54ac5f301e8e04c569dfdb907f7be71b06b88b5063ce9d6953d2d58574"}, + {file = "coverage-7.6.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:959244a17184515f8c52dcb65fb662808767c0bd233c1d8a166e7cf74c9ea985"}, + {file = "coverage-7.6.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bda1c5f347550c359f841d6614fb8ca42ae5cb0b74d39f8a1e204815ebe25750"}, + {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ceeb90c3eda1f2d8c4c578c14167dbd8c674ecd7d38e45647543f19839dd6ea"}, + {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f16f44025c06792e0fb09571ae454bcc7a3ec75eeb3c36b025eccf501b1a4c3"}, + {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b076e625396e787448d27a411aefff867db2bffac8ed04e8f7056b07024eed5a"}, + {file = "coverage-7.6.12-cp312-cp312-win32.whl", hash = "sha256:00b2086892cf06c7c2d74983c9595dc511acca00665480b3ddff749ec4fb2a95"}, + {file = "coverage-7.6.12-cp312-cp312-win_amd64.whl", hash = "sha256:7ae6eabf519bc7871ce117fb18bf14e0e343eeb96c377667e3e5dd12095e0288"}, + {file = "coverage-7.6.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:488c27b3db0ebee97a830e6b5a3ea930c4a6e2c07f27a5e67e1b3532e76b9ef1"}, + {file = "coverage-7.6.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d1095bbee1851269f79fd8e0c9b5544e4c00c0c24965e66d8cba2eb5bb535fd"}, + {file = "coverage-7.6.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0533adc29adf6a69c1baa88c3d7dbcaadcffa21afbed3ca7a225a440e4744bf9"}, + {file = "coverage-7.6.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53c56358d470fa507a2b6e67a68fd002364d23c83741dbc4c2e0680d80ca227e"}, + {file = "coverage-7.6.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64cbb1a3027c79ca6310bf101014614f6e6e18c226474606cf725238cf5bc2d4"}, + {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:79cac3390bfa9836bb795be377395f28410811c9066bc4eefd8015258a7578c6"}, + {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9b148068e881faa26d878ff63e79650e208e95cf1c22bd3f77c3ca7b1d9821a3"}, + {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8bec2ac5da793c2685ce5319ca9bcf4eee683b8a1679051f8e6ec04c4f2fd7dc"}, + {file = "coverage-7.6.12-cp313-cp313-win32.whl", hash = "sha256:200e10beb6ddd7c3ded322a4186313d5ca9e63e33d8fab4faa67ef46d3460af3"}, + {file = "coverage-7.6.12-cp313-cp313-win_amd64.whl", hash = "sha256:2b996819ced9f7dbb812c701485d58f261bef08f9b85304d41219b1496b591ef"}, + {file = "coverage-7.6.12-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:299cf973a7abff87a30609879c10df0b3bfc33d021e1adabc29138a48888841e"}, + {file = "coverage-7.6.12-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4b467a8c56974bf06e543e69ad803c6865249d7a5ccf6980457ed2bc50312703"}, + {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2458f275944db8129f95d91aee32c828a408481ecde3b30af31d552c2ce284a0"}, + {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a9d8be07fb0832636a0f72b80d2a652fe665e80e720301fb22b191c3434d924"}, + {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d47376a4f445e9743f6c83291e60adb1b127607a3618e3185bbc8091f0467b"}, + {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b95574d06aa9d2bd6e5cc35a5bbe35696342c96760b69dc4287dbd5abd4ad51d"}, + {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ecea0c38c9079570163d663c0433a9af4094a60aafdca491c6a3d248c7432827"}, + {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2251fabcfee0a55a8578a9d29cecfee5f2de02f11530e7d5c5a05859aa85aee9"}, + {file = "coverage-7.6.12-cp313-cp313t-win32.whl", hash = "sha256:eb5507795caabd9b2ae3f1adc95f67b1104971c22c624bb354232d65c4fc90b3"}, + {file = "coverage-7.6.12-cp313-cp313t-win_amd64.whl", hash = "sha256:f60a297c3987c6c02ffb29effc70eadcbb412fe76947d394a1091a3615948e2f"}, + {file = "coverage-7.6.12-py3-none-any.whl", hash = "sha256:eb8668cfbc279a536c633137deeb9435d2962caec279c3f8cf8b91fff6ff8953"}, + {file = "coverage-7.6.12.tar.gz", hash = "sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2"}, ] [[package]] name = "coverage" -version = "7.6.10" +version = "7.6.12" extras = ["toml"] requires_python = ">=3.9" summary = "Code coverage measurement for Python" dependencies = [ - "coverage==7.6.10", + "coverage==7.6.12", "tomli; python_full_version <= \"3.11.0a6\"", ] files = [ - {file = "coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3"}, - {file = "coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43"}, - {file = "coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132"}, - {file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f"}, - {file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994"}, - {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99"}, - {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd"}, - {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377"}, - {file = "coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8"}, - {file = "coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609"}, - {file = "coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853"}, - {file = "coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078"}, - {file = "coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0"}, - {file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50"}, - {file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022"}, - {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b"}, - {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0"}, - {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852"}, - {file = "coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359"}, - {file = "coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247"}, - {file = "coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9"}, - {file = "coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b"}, - {file = "coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690"}, - {file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18"}, - {file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c"}, - {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd"}, - {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e"}, - {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694"}, - {file = "coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6"}, - {file = "coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e"}, - {file = "coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe"}, - {file = "coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273"}, - {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8"}, - {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098"}, - {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb"}, - {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0"}, - {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf"}, - {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2"}, - {file = "coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312"}, - {file = "coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d"}, - {file = "coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23"}, + {file = "coverage-7.6.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e18aafdfb3e9ec0d261c942d35bd7c28d031c5855dadb491d2723ba54f4c3015"}, + {file = "coverage-7.6.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66fe626fd7aa5982cdebad23e49e78ef7dbb3e3c2a5960a2b53632f1f703ea45"}, + {file = "coverage-7.6.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ef01d70198431719af0b1f5dcbefc557d44a190e749004042927b2a3fed0702"}, + {file = "coverage-7.6.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e92ae5a289a4bc4c0aae710c0948d3c7892e20fd3588224ebe242039573bf0"}, + {file = "coverage-7.6.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e695df2c58ce526eeab11a2e915448d3eb76f75dffe338ea613c1201b33bab2f"}, + {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d74c08e9aaef995f8c4ef6d202dbd219c318450fe2a76da624f2ebb9c8ec5d9f"}, + {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e995b3b76ccedc27fe4f477b349b7d64597e53a43fc2961db9d3fbace085d69d"}, + {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b1f097878d74fe51e1ddd1be62d8e3682748875b461232cf4b52ddc6e6db0bba"}, + {file = "coverage-7.6.12-cp311-cp311-win32.whl", hash = "sha256:1f7ffa05da41754e20512202c866d0ebfc440bba3b0ed15133070e20bf5aeb5f"}, + {file = "coverage-7.6.12-cp311-cp311-win_amd64.whl", hash = "sha256:e216c5c45f89ef8971373fd1c5d8d1164b81f7f5f06bbf23c37e7908d19e8558"}, + {file = "coverage-7.6.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b172f8e030e8ef247b3104902cc671e20df80163b60a203653150d2fc204d1ad"}, + {file = "coverage-7.6.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:641dfe0ab73deb7069fb972d4d9725bf11c239c309ce694dd50b1473c0f641c3"}, + {file = "coverage-7.6.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e549f54ac5f301e8e04c569dfdb907f7be71b06b88b5063ce9d6953d2d58574"}, + {file = "coverage-7.6.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:959244a17184515f8c52dcb65fb662808767c0bd233c1d8a166e7cf74c9ea985"}, + {file = "coverage-7.6.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bda1c5f347550c359f841d6614fb8ca42ae5cb0b74d39f8a1e204815ebe25750"}, + {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ceeb90c3eda1f2d8c4c578c14167dbd8c674ecd7d38e45647543f19839dd6ea"}, + {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f16f44025c06792e0fb09571ae454bcc7a3ec75eeb3c36b025eccf501b1a4c3"}, + {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b076e625396e787448d27a411aefff867db2bffac8ed04e8f7056b07024eed5a"}, + {file = "coverage-7.6.12-cp312-cp312-win32.whl", hash = "sha256:00b2086892cf06c7c2d74983c9595dc511acca00665480b3ddff749ec4fb2a95"}, + {file = "coverage-7.6.12-cp312-cp312-win_amd64.whl", hash = "sha256:7ae6eabf519bc7871ce117fb18bf14e0e343eeb96c377667e3e5dd12095e0288"}, + {file = "coverage-7.6.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:488c27b3db0ebee97a830e6b5a3ea930c4a6e2c07f27a5e67e1b3532e76b9ef1"}, + {file = "coverage-7.6.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d1095bbee1851269f79fd8e0c9b5544e4c00c0c24965e66d8cba2eb5bb535fd"}, + {file = "coverage-7.6.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0533adc29adf6a69c1baa88c3d7dbcaadcffa21afbed3ca7a225a440e4744bf9"}, + {file = "coverage-7.6.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53c56358d470fa507a2b6e67a68fd002364d23c83741dbc4c2e0680d80ca227e"}, + {file = "coverage-7.6.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64cbb1a3027c79ca6310bf101014614f6e6e18c226474606cf725238cf5bc2d4"}, + {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:79cac3390bfa9836bb795be377395f28410811c9066bc4eefd8015258a7578c6"}, + {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9b148068e881faa26d878ff63e79650e208e95cf1c22bd3f77c3ca7b1d9821a3"}, + {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8bec2ac5da793c2685ce5319ca9bcf4eee683b8a1679051f8e6ec04c4f2fd7dc"}, + {file = "coverage-7.6.12-cp313-cp313-win32.whl", hash = "sha256:200e10beb6ddd7c3ded322a4186313d5ca9e63e33d8fab4faa67ef46d3460af3"}, + {file = "coverage-7.6.12-cp313-cp313-win_amd64.whl", hash = "sha256:2b996819ced9f7dbb812c701485d58f261bef08f9b85304d41219b1496b591ef"}, + {file = "coverage-7.6.12-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:299cf973a7abff87a30609879c10df0b3bfc33d021e1adabc29138a48888841e"}, + {file = "coverage-7.6.12-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4b467a8c56974bf06e543e69ad803c6865249d7a5ccf6980457ed2bc50312703"}, + {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2458f275944db8129f95d91aee32c828a408481ecde3b30af31d552c2ce284a0"}, + {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a9d8be07fb0832636a0f72b80d2a652fe665e80e720301fb22b191c3434d924"}, + {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d47376a4f445e9743f6c83291e60adb1b127607a3618e3185bbc8091f0467b"}, + {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b95574d06aa9d2bd6e5cc35a5bbe35696342c96760b69dc4287dbd5abd4ad51d"}, + {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ecea0c38c9079570163d663c0433a9af4094a60aafdca491c6a3d248c7432827"}, + {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2251fabcfee0a55a8578a9d29cecfee5f2de02f11530e7d5c5a05859aa85aee9"}, + {file = "coverage-7.6.12-cp313-cp313t-win32.whl", hash = "sha256:eb5507795caabd9b2ae3f1adc95f67b1104971c22c624bb354232d65c4fc90b3"}, + {file = "coverage-7.6.12-cp313-cp313t-win_amd64.whl", hash = "sha256:f60a297c3987c6c02ffb29effc70eadcbb412fe76947d394a1091a3615948e2f"}, + {file = "coverage-7.6.12-py3-none-any.whl", hash = "sha256:eb8668cfbc279a536c633137deeb9435d2962caec279c3f8cf8b91fff6ff8953"}, + {file = "coverage-7.6.12.tar.gz", hash = "sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2"}, ] [[package]] name = "cryptography" -version = "44.0.0" +version = "44.0.1" requires_python = "!=3.9.0,!=3.9.1,>=3.7" summary = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." dependencies = [ "cffi>=1.12; platform_python_implementation != \"PyPy\"", ] files = [ - {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, - {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, - {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, - {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, - {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, - {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, - {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, + {file = "cryptography-44.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009"}, + {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f"}, + {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887143b9ff6bad2b7570da75a7fe8bbf5f65276365ac259a5d2d5147a73775f2"}, + {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:322eb03ecc62784536bc173f1483e76747aafeb69c8728df48537eb431cd1911"}, + {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:21377472ca4ada2906bc313168c9dc7b1d7ca417b63c1c3011d0c74b7de9ae69"}, + {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df978682c1504fc93b3209de21aeabf2375cb1571d4e61907b3e7a2540e83026"}, + {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:eb3889330f2a4a148abead555399ec9a32b13b7c8ba969b72d8e500eb7ef84cd"}, + {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:8e6a85a93d0642bd774460a86513c5d9d80b5c002ca9693e63f6e540f1815ed0"}, + {file = "cryptography-44.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6f76fdd6fd048576a04c5210d53aa04ca34d2ed63336d4abd306d0cbe298fddf"}, + {file = "cryptography-44.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6c8acf6f3d1f47acb2248ec3ea261171a671f3d9428e34ad0357148d492c7864"}, + {file = "cryptography-44.0.1-cp37-abi3-win32.whl", hash = "sha256:24979e9f2040c953a94bf3c6782e67795a4c260734e5264dceea65c8f4bae64a"}, + {file = "cryptography-44.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:fd0ee90072861e276b0ff08bd627abec29e32a53b2be44e41dbcdf87cbee2b00"}, + {file = "cryptography-44.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a2d8a7045e1ab9b9f803f0d9531ead85f90c5f2859e653b61497228b18452008"}, + {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8272f257cf1cbd3f2e120f14c68bff2b6bdfcc157fafdee84a1b795efd72862"}, + {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e8d181e90a777b63f3f0caa836844a1182f1f265687fac2115fcf245f5fbec3"}, + {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:436df4f203482f41aad60ed1813811ac4ab102765ecae7a2bbb1dbb66dcff5a7"}, + {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4f422e8c6a28cf8b7f883eb790695d6d45b0c385a2583073f3cec434cc705e1a"}, + {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:72198e2b5925155497a5a3e8c216c7fb3e64c16ccee11f0e7da272fa93b35c4c"}, + {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a46a89ad3e6176223b632056f321bc7de36b9f9b93b2cc1cccf935a3849dc62"}, + {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:53f23339864b617a3dfc2b0ac8d5c432625c80014c25caac9082314e9de56f41"}, + {file = "cryptography-44.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:888fcc3fce0c888785a4876ca55f9f43787f4c5c1cc1e2e0da71ad481ff82c5b"}, + {file = "cryptography-44.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00918d859aa4e57db8299607086f793fa7813ae2ff5a4637e318a25ef82730f7"}, + {file = "cryptography-44.0.1-cp39-abi3-win32.whl", hash = "sha256:9b336599e2cb77b1008cb2ac264b290803ec5e8e89d618a5e978ff5eb6f715d9"}, + {file = "cryptography-44.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:e403f7f766ded778ecdb790da786b418a9f2394f36e8cc8b796cc056ab05f44f"}, + {file = "cryptography-44.0.1.tar.gz", hash = "sha256:f51f5705ab27898afda1aaa430f34ad90dc117421057782022edf0600bec5f14"}, +] + +[[package]] +name = "dependency-groups" +version = "1.3.0" +requires_python = ">=3.8" +summary = "A tool for resolving PEP 735 Dependency Group data" +dependencies = [ + "packaging", + "tomli; python_version < \"3.11\"", +] +files = [ + {file = "dependency_groups-1.3.0-py3-none-any.whl", hash = "sha256:1abf34d712deda5581e80d507512664d52b35d1c2d7caf16c85e58ca508547e0"}, + {file = "dependency_groups-1.3.0.tar.gz", hash = "sha256:5b9751d5d98fbd6dfd038a560a69c8382e41afcbf7ffdbcc28a2a3f85498830f"}, ] [[package]] @@ -564,25 +595,25 @@ files = [ [[package]] name = "django-stubs" -version = "5.1.2" +version = "5.1.3" requires_python = ">=3.8" summary = "Mypy stubs for Django" dependencies = [ "asgiref", "django", - "django-stubs-ext>=5.1.2", + "django-stubs-ext>=5.1.3", "tomli; python_version < \"3.11\"", "types-PyYAML", "typing-extensions>=4.11.0", ] files = [ - {file = "django_stubs-5.1.2-py3-none-any.whl", hash = "sha256:04ddc778faded6fb48468a8da9e98b8d12b9ba983faa648d37a73ebde0f024da"}, - {file = "django_stubs-5.1.2.tar.gz", hash = "sha256:a0fcb3659bab46a6d835cc2d9bff3fc29c36ccea41a10e8b1930427bc0f9f0df"}, + {file = "django_stubs-5.1.3-py3-none-any.whl", hash = "sha256:716758ced158b439213062e52de6df3cff7c586f9f9ad7ab59210efbea5dfe78"}, + {file = "django_stubs-5.1.3.tar.gz", hash = "sha256:8c230bc5bebee6da282ba8a27ad1503c84a0c4cd2f46e63d149e76d2a63e639a"}, ] [[package]] name = "django-stubs-ext" -version = "5.1.2" +version = "5.1.3" requires_python = ">=3.8" summary = "Monkey-patching and extensions for django-stubs" dependencies = [ @@ -590,8 +621,8 @@ dependencies = [ "typing-extensions", ] files = [ - {file = "django_stubs_ext-5.1.2-py3-none-any.whl", hash = "sha256:6c559214538d6a26f631ca638ddc3251a0a891d607de8ce01d23d3201ad8ad6c"}, - {file = "django_stubs_ext-5.1.2.tar.gz", hash = "sha256:421c0c3025a68e3ab8e16f065fad9ba93335ecefe2dd92a0cff97a665680266c"}, + {file = "django_stubs_ext-5.1.3-py3-none-any.whl", hash = "sha256:64561fbc53e963cc1eed2c8eb27e18b8e48dcb90771205180fe29fc8a59e55fd"}, + {file = "django_stubs_ext-5.1.3.tar.gz", hash = "sha256:3e60f82337f0d40a362f349bf15539144b96e4ceb4dbd0239be1cd71f6a74ad0"}, ] [[package]] @@ -609,21 +640,20 @@ files = [ [[package]] name = "faker" -version = "35.0.0" -requires_python = ">=3.8" +version = "36.1.1" +requires_python = ">=3.9" summary = "Faker is a Python package that generates fake data for you." dependencies = [ - "python-dateutil>=2.4", - "typing-extensions", + "tzdata", ] files = [ - {file = "Faker-35.0.0-py3-none-any.whl", hash = "sha256:926d2301787220e0554c2e39afc4dc535ce4b0a8d0a089657137999f66334ef4"}, - {file = "faker-35.0.0.tar.gz", hash = "sha256:42f2da8cf561e38c72b25e9891168b1e25fec42b6b0b5b0b6cd6041da54af885"}, + {file = "Faker-36.1.1-py3-none-any.whl", hash = "sha256:ad1f1be7fd692ec0256517404a9d7f007ab36ac5d4674082fa72404049725eaa"}, + {file = "faker-36.1.1.tar.gz", hash = "sha256:7cb2bbd4c8f040e4a340ae4019e9a48b6cf1db6a71bda4e5a61d8d13b7bef28d"}, ] [[package]] name = "fakeredis" -version = "2.26.2" +version = "2.27.0" requires_python = "<4.0,>=3.7" summary = "Python implementation of redis API, can be used for testing purposes." dependencies = [ @@ -633,8 +663,8 @@ dependencies = [ "typing-extensions<5.0,>=4.7; python_version < \"3.11\"", ] files = [ - {file = "fakeredis-2.26.2-py3-none-any.whl", hash = "sha256:86d4129df001efc25793cb334008160fccc98425d9f94de47884a92b63988c14"}, - {file = "fakeredis-2.26.2.tar.gz", hash = "sha256:3ee5003a314954032b96b1365290541346c9cc24aab071b52cc983bb99ecafbf"}, + {file = "fakeredis-2.27.0-py3-none-any.whl", hash = "sha256:f4b6e0fa4193acbf00d81dac71ff5cc34fe7d7c12f1560b036f98578a103d5c3"}, + {file = "fakeredis-2.27.0.tar.gz", hash = "sha256:7b7584ec104392592297f46864a82cb7339a23e254ee885bf5ae07cfc64fbce7"}, ] [[package]] @@ -649,14 +679,15 @@ files = [ [[package]] name = "gbp-testkit" -version = "0.1.dev2" +version = "0.1.dev8" requires_python = ">=3.11" git = "https://github.com/enku/gbp-testkit.git" -revision = "c6c748583dfef80d1ee22e8f1232b206c2f52241" +revision = "f20cb150552fc514860b6ca6252c3dc73ac07aaf" summary = "Gentoo Build Publisher testing tools" dependencies = [ "django>=5.1.6", "factory-boy>=3.3.3", + "types-requests>=2.32.0.20241016", "unittest-fixtures @ git+https://github.com/enku/unittest-fixtures.git", ] @@ -680,15 +711,15 @@ files = [ [[package]] name = "graphql-core" -version = "3.2.6" +version = "3.2.5" requires_python = "<4,>=3.6" summary = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." dependencies = [ "typing-extensions<5,>=4; python_version < \"3.10\"", ] files = [ - {file = "graphql_core-3.2.6-py3-none-any.whl", hash = "sha256:78b016718c161a6fb20a7d97bbf107f331cd1afe53e45566c59f776ed7f0b45f"}, - {file = "graphql_core-3.2.6.tar.gz", hash = "sha256:c08eec22f9e40f0bd61d805907e3b3b1b9a320bc606e23dc145eebca07c8fbab"}, + {file = "graphql_core-3.2.5-py3-none-any.whl", hash = "sha256:2f150d5096448aa4f8ab26268567bbfeef823769893b39c1a2e1409590939c8a"}, + {file = "graphql_core-3.2.5.tar.gz", hash = "sha256:e671b90ed653c808715645e3998b7ab67d382d55467b7e2978549111bbabf8d5"}, ] [[package]] @@ -703,12 +734,12 @@ files = [ [[package]] name = "isort" -version = "5.13.2" -requires_python = ">=3.8.0" +version = "6.0.0" +requires_python = ">=3.9.0" summary = "A Python utility / library to sort Python imports." files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, + {file = "isort-6.0.0-py3-none-any.whl", hash = "sha256:567954102bb47bb12e0fae62606570faacddd441e45683968c8d1734fb1af892"}, + {file = "isort-6.0.0.tar.gz", hash = "sha256:75d9d8a1438a9432a7d7b54f2d3b45cad9a4a0fdba43617d9873379704a8bdf1"}, ] [[package]] @@ -887,19 +918,21 @@ files = [ [[package]] name = "nox" -version = "2024.10.9" +version = "2025.2.9" requires_python = ">=3.8" summary = "Flexible test automation." dependencies = [ "argcomplete<4,>=1.9.4", + "attrs>=23.1", "colorlog<7,>=2.6.1", + "dependency-groups>=1.1", "packaging>=20.9", "tomli>=1; python_version < \"3.11\"", "virtualenv>=20.14.1", ] files = [ - {file = "nox-2024.10.9-py3-none-any.whl", hash = "sha256:1d36f309a0a2a853e9bccb76bbef6bb118ba92fa92674d15604ca99adeb29eab"}, - {file = "nox-2024.10.9.tar.gz", hash = "sha256:7aa9dc8d1c27e9f45ab046ffd1c3b2c4f7c91755304769df231308849ebded95"}, + {file = "nox-2025.2.9-py3-none-any.whl", hash = "sha256:7d1e92d1918c6980d70aee9cf1c1d19d16faa71c4afe338fffd39e8a460e2067"}, + {file = "nox-2025.2.9.tar.gz", hash = "sha256:d50cd4ca568bd7621c2e6cbbc4845b3b7f7697f25d5fb0190ce8f4600be79768"}, ] [[package]] @@ -995,60 +1028,76 @@ files = [ [[package]] name = "propcache" -version = "0.2.1" +version = "0.3.0" requires_python = ">=3.9" summary = "Accelerated property cache" files = [ - {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e"}, - {file = "propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034"}, - {file = "propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518"}, - {file = "propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246"}, - {file = "propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30"}, - {file = "propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6"}, - {file = "propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1"}, - {file = "propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54"}, - {file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"}, + {file = "propcache-0.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9ddd49258610499aab83b4f5b61b32e11fce873586282a0e972e5ab3bcadee51"}, + {file = "propcache-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2578541776769b500bada3f8a4eeaf944530516b6e90c089aa368266ed70c49e"}, + {file = "propcache-0.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8074c5dd61c8a3e915fa8fc04754fa55cfa5978200d2daa1e2d4294c1f136aa"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b58229a844931bca61b3a20efd2be2a2acb4ad1622fc026504309a6883686fbf"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e45377d5d6fefe1677da2a2c07b024a6dac782088e37c0b1efea4cfe2b1be19b"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ec5060592d83454e8063e487696ac3783cc48c9a329498bafae0d972bc7816c9"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15010f29fbed80e711db272909a074dc79858c6d28e2915704cfc487a8ac89c6"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a254537b9b696ede293bfdbc0a65200e8e4507bc9f37831e2a0318a9b333c85c"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2b975528998de037dfbc10144b8aed9b8dd5a99ec547f14d1cb7c5665a43f075"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:19d36bb351ad5554ff20f2ae75f88ce205b0748c38b146c75628577020351e3c"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6032231d4a5abd67c7f71168fd64a47b6b451fbcb91c8397c2f7610e67683810"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6985a593417cdbc94c7f9c3403747335e450c1599da1647a5af76539672464d3"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:6a1948df1bb1d56b5e7b0553c0fa04fd0e320997ae99689488201f19fa90d2e7"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8319293e85feadbbfe2150a5659dbc2ebc4afdeaf7d98936fb9a2f2ba0d4c35c"}, + {file = "propcache-0.3.0-cp311-cp311-win32.whl", hash = "sha256:63f26258a163c34542c24808f03d734b338da66ba91f410a703e505c8485791d"}, + {file = "propcache-0.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:cacea77ef7a2195f04f9279297684955e3d1ae4241092ff0cfcef532bb7a1c32"}, + {file = "propcache-0.3.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e53d19c2bf7d0d1e6998a7e693c7e87300dd971808e6618964621ccd0e01fe4e"}, + {file = "propcache-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a61a68d630e812b67b5bf097ab84e2cd79b48c792857dc10ba8a223f5b06a2af"}, + {file = "propcache-0.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fb91d20fa2d3b13deea98a690534697742029f4fb83673a3501ae6e3746508b5"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67054e47c01b7b349b94ed0840ccae075449503cf1fdd0a1fdd98ab5ddc2667b"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:997e7b8f173a391987df40f3b52c423e5850be6f6df0dcfb5376365440b56667"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d663fd71491dde7dfdfc899d13a067a94198e90695b4321084c6e450743b8c7"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8884ba1a0fe7210b775106b25850f5e5a9dc3c840d1ae9924ee6ea2eb3acbfe7"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa806bbc13eac1ab6291ed21ecd2dd426063ca5417dd507e6be58de20e58dfcf"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f4d7a7c0aff92e8354cceca6fe223973ddf08401047920df0fcb24be2bd5138"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9be90eebc9842a93ef8335291f57b3b7488ac24f70df96a6034a13cb58e6ff86"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bf15fc0b45914d9d1b706f7c9c4f66f2b7b053e9517e40123e137e8ca8958b3d"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a16167118677d94bb48bfcd91e420088854eb0737b76ec374b91498fb77a70e"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:41de3da5458edd5678b0f6ff66691507f9885f5fe6a0fb99a5d10d10c0fd2d64"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:728af36011bb5d344c4fe4af79cfe186729efb649d2f8b395d1572fb088a996c"}, + {file = "propcache-0.3.0-cp312-cp312-win32.whl", hash = "sha256:6b5b7fd6ee7b54e01759f2044f936dcf7dea6e7585f35490f7ca0420fe723c0d"}, + {file = "propcache-0.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:2d15bc27163cd4df433e75f546b9ac31c1ba7b0b128bfb1b90df19082466ff57"}, + {file = "propcache-0.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a2b9bf8c79b660d0ca1ad95e587818c30ccdb11f787657458d6f26a1ea18c568"}, + {file = "propcache-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0c1a133d42c6fc1f5fbcf5c91331657a1ff822e87989bf4a6e2e39b818d0ee9"}, + {file = "propcache-0.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bb2f144c6d98bb5cbc94adeb0447cfd4c0f991341baa68eee3f3b0c9c0e83767"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1323cd04d6e92150bcc79d0174ce347ed4b349d748b9358fd2e497b121e03c8"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b812b3cb6caacd072276ac0492d249f210006c57726b6484a1e1805b3cfeea0"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:742840d1d0438eb7ea4280f3347598f507a199a35a08294afdcc560c3739989d"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6e7e4f9167fddc438cd653d826f2222222564daed4116a02a184b464d3ef05"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a94ffc66738da99232ddffcf7910e0f69e2bbe3a0802e54426dbf0714e1c2ffe"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c6ec957025bf32b15cbc6b67afe233c65b30005e4c55fe5768e4bb518d712f1"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:549722908de62aa0b47a78b90531c022fa6e139f9166be634f667ff45632cc92"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5d62c4f6706bff5d8a52fd51fec6069bef69e7202ed481486c0bc3874912c787"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:24c04f8fbf60094c531667b8207acbae54146661657a1b1be6d3ca7773b7a545"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7c5f5290799a3f6539cc5e6f474c3e5c5fbeba74a5e1e5be75587746a940d51e"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4fa0e7c9c3cf7c276d4f6ab9af8adddc127d04e0fcabede315904d2ff76db626"}, + {file = "propcache-0.3.0-cp313-cp313-win32.whl", hash = "sha256:ee0bd3a7b2e184e88d25c9baa6a9dc609ba25b76daae942edfb14499ac7ec374"}, + {file = "propcache-0.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c8f7d896a16da9455f882870a507567d4f58c53504dc2d4b1e1d386dfe4588a"}, + {file = "propcache-0.3.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e560fd75aaf3e5693b91bcaddd8b314f4d57e99aef8a6c6dc692f935cc1e6bbf"}, + {file = "propcache-0.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:65a37714b8ad9aba5780325228598a5b16c47ba0f8aeb3dc0514701e4413d7c0"}, + {file = "propcache-0.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:07700939b2cbd67bfb3b76a12e1412405d71019df00ca5697ce75e5ef789d829"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c0fdbdf6983526e269e5a8d53b7ae3622dd6998468821d660d0daf72779aefa"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:794c3dd744fad478b6232289c866c25406ecdfc47e294618bdf1697e69bd64a6"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4544699674faf66fb6b4473a1518ae4999c1b614f0b8297b1cef96bac25381db"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fddb8870bdb83456a489ab67c6b3040a8d5a55069aa6f72f9d872235fbc52f54"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f857034dc68d5ceb30fb60afb6ff2103087aea10a01b613985610e007053a121"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:02df07041e0820cacc8f739510078f2aadcfd3fc57eaeeb16d5ded85c872c89e"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f47d52fd9b2ac418c4890aad2f6d21a6b96183c98021f0a48497a904199f006e"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9ff4e9ecb6e4b363430edf2c6e50173a63e0820e549918adef70515f87ced19a"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ecc2920630283e0783c22e2ac94427f8cca29a04cfdf331467d4f661f4072dac"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c441c841e82c5ba7a85ad25986014be8d7849c3cfbdb6004541873505929a74e"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c929916cbdb540d3407c66f19f73387f43e7c12fa318a66f64ac99da601bcdf"}, + {file = "propcache-0.3.0-cp313-cp313t-win32.whl", hash = "sha256:0c3e893c4464ebd751b44ae76c12c5f5c1e4f6cbd6fbf67e3783cd93ad221863"}, + {file = "propcache-0.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:75e872573220d1ee2305b35c9813626e620768248425f58798413e9c39741f46"}, + {file = "propcache-0.3.0-py3-none-any.whl", hash = "sha256:67dda3c7325691c2081510e92c561f465ba61b975f481735aefdfc845d2cd043"}, + {file = "propcache-0.3.0.tar.gz", hash = "sha256:a8fd93de4e1d278046345f49e2238cdb298589325849b2645d4a94c53faeffc5"}, ] [[package]] @@ -1073,7 +1122,7 @@ files = [ [[package]] name = "pylint" -version = "3.3.3" +version = "3.3.4" requires_python = ">=3.9.0" summary = "python code static checker" dependencies = [ @@ -1082,7 +1131,7 @@ dependencies = [ "dill>=0.2; python_version < \"3.11\"", "dill>=0.3.6; python_version >= \"3.11\"", "dill>=0.3.7; python_version >= \"3.12\"", - "isort!=5.13.0,<6,>=4.2.5", + "isort!=5.13.0,<7,>=4.2.5", "mccabe<0.8,>=0.6", "platformdirs>=2.2.0", "tomli>=1.1.0; python_version < \"3.11\"", @@ -1090,8 +1139,8 @@ dependencies = [ "typing-extensions>=3.10.0; python_version < \"3.10\"", ] files = [ - {file = "pylint-3.3.3-py3-none-any.whl", hash = "sha256:26e271a2bc8bce0fc23833805a9076dd9b4d5194e2a02164942cb3cdc37b4183"}, - {file = "pylint-3.3.3.tar.gz", hash = "sha256:07c607523b17e6d16e2ae0d7ef59602e332caa762af64203c24b41c27139f36a"}, + {file = "pylint-3.3.4-py3-none-any.whl", hash = "sha256:289e6a1eb27b453b08436478391a48cd53bb0efb824873f949e709350f3de018"}, + {file = "pylint-3.3.4.tar.gz", hash = "sha256:74ae7a38b177e69a9b525d0794bd8183820bfa7eb68cc1bee6e8ed22a42be4ce"}, ] [[package]] @@ -1309,20 +1358,20 @@ files = [ [[package]] name = "typos" -version = "1.29.4" +version = "1.29.9" requires_python = ">=3.7" summary = "Source Code Spelling Correction" files = [ - {file = "typos-1.29.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3825b4b6f6deec99b78c998ae5d1681334920a0519fe6ae4a3fdc6c041834728"}, - {file = "typos-1.29.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f7a318f65bbea371f24ea3f5ab1ba1953d5f5ad7c1115582b4f6992ed79dcfcb"}, - {file = "typos-1.29.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5e3aedf4d99055b27b70f472abb694cc420d03b003e71ab8877acf2a24a945e"}, - {file = "typos-1.29.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59b134bad893e0611a0c0212750c0e49503552b600033b8c2c5cc2b8222e75de"}, - {file = "typos-1.29.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7dac616eacae037e71e6c1089b82dc296c1a5b4621b132eba5c79b7044b1a74"}, - {file = "typos-1.29.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:fdf9d2550796d36120e464f6dac4e525d397204728dc87be0c749f4a3746ce37"}, - {file = "typos-1.29.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:564a39c4803d2285c9756069ca0a4490e4ccecedeea568b085421cd9e035a865"}, - {file = "typos-1.29.4-py3-none-win32.whl", hash = "sha256:f66f292fe88c2ffe537373654c5e157a930f4ba302400916e0b9d802ad6e5932"}, - {file = "typos-1.29.4-py3-none-win_amd64.whl", hash = "sha256:937cd4ef6576f1d5a5f5473ea9ac789b332fb62bee7f6e4f6cfb1cfdd2e9e618"}, - {file = "typos-1.29.4.tar.gz", hash = "sha256:590d776448d634e2437a326ff7f2218d53439f2d4e478337bb17ff627caaa2cd"}, + {file = "typos-1.29.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4547ff98a61f71f75a721b0c401eef220c456e937d77cae141aabf97cdee155d"}, + {file = "typos-1.29.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fb74645a60eb76d4a147de36968d5db51ee6bd35e72a9210e462c96bbe30e7e9"}, + {file = "typos-1.29.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:211ac5179c4c0309f6c486b475cd47ff732df2f5a87b0c940ff906cd432ecf5c"}, + {file = "typos-1.29.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:98f2aa90baa26ba511106ff3bd46e13cdf1c327167159faf6bb8950eb22cc748"}, + {file = "typos-1.29.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24faf9854f317ec1037c72d42821146260a1e1d2deeb6d0eed85a90c56808564"}, + {file = "typos-1.29.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7f0d3fce6ed2fe738e5346cface35d59f1583e2957464b68eb014f861e06c11e"}, + {file = "typos-1.29.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f32f63b7d96c47d749981d7d666978504f73d25704ff27dcb500c516fb86e585"}, + {file = "typos-1.29.9-py3-none-win32.whl", hash = "sha256:059fc40f7e830b7dabad5bc2e311872ba7dfb6cdc4dc8227330c81f61bbdc52f"}, + {file = "typos-1.29.9-py3-none-win_amd64.whl", hash = "sha256:9f618a399ff2ff144b97c0a867f0439c26394f8849853f2f68339fce5b3bae02"}, + {file = "typos-1.29.9.tar.gz", hash = "sha256:481480d7c33a6a426c8728b2df65d9188f0bc855ea8390f4a4f44e713040cbc8"}, ] [[package]] @@ -1337,10 +1386,10 @@ files = [ [[package]] name = "unittest-fixtures" -version = "0.1.dev37" +version = "0.1.dev57" requires_python = ">=3.11" git = "https://github.com/enku/unittest-fixtures.git" -revision = "cecc21e94c9ad93a0a5b5d08cc9b8b2ee40681e7" +revision = "d6c46e57045025eb9757afd395099733fe0b28c1" summary = "A small library for loading unittest fixtures" [[package]] @@ -1365,7 +1414,7 @@ files = [ [[package]] name = "virtualenv" -version = "20.29.1" +version = "20.29.2" requires_python = ">=3.8" summary = "Virtual Python Environment builder" dependencies = [ @@ -1375,8 +1424,8 @@ dependencies = [ "platformdirs<5,>=3.9.1", ] files = [ - {file = "virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779"}, - {file = "virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35"}, + {file = "virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a"}, + {file = "virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728"}, ] [[package]] diff --git a/tests/test_cli_addmachine.py b/tests/test_cli_addmachine.py index 74d7890..aa6c1e4 100644 --- a/tests/test_cli_addmachine.py +++ b/tests/test_cli_addmachine.py @@ -3,29 +3,29 @@ # pylint: disable=missing-docstring from argparse import ArgumentParser, Namespace -import unittest_fixtures as fixture from gbp_testkit import DjangoTestCase as TestCase +from unittest_fixtures import Fixtures, given from gentoo_build_publisher import publisher from gentoo_build_publisher.cli import addmachine from gentoo_build_publisher.types import MachineJob, Repo -@fixture.requires("gbp", "console") +@given("gbp", "console") class AddMachineTestCase(TestCase): - def test_calls_graphql_with_the_expected_args(self) -> None: + def test_calls_graphql_with_the_expected_args(self, fixtures: Fixtures) -> None: args = Namespace( name="base", repo="https://github.com/enku/gbp-machines.git", branch="master", deps=["gentoo"], ) - console = self.fixtures.console - exit_status = addmachine.handler(args, self.fixtures.gbp, console) + console = fixtures.console + exit_status = addmachine.handler(args, fixtures.gbp, console) self.assertEqual(exit_status, 0) - def test_when_item_already_exists(self) -> None: + def test_when_item_already_exists(self, fixtures: Fixtures) -> None: job = MachineJob( name="base", repo=Repo(url="https://github.com/enku/gbp-machines.git", branch="master"), @@ -39,8 +39,8 @@ def test_when_item_already_exists(self) -> None: branch="master", deps=["gentoo"], ) - console = self.fixtures.console - exit_status = addmachine.handler(args, self.fixtures.gbp, console) + console = fixtures.console + exit_status = addmachine.handler(args, fixtures.gbp, console) self.assertEqual(exit_status, 1) self.assertEqual(console.err.file.getvalue(), "error: FileExistsError: base\n") diff --git a/tests/test_cli_addrepo.py b/tests/test_cli_addrepo.py index 84e10bb..b10a722 100644 --- a/tests/test_cli_addrepo.py +++ b/tests/test_cli_addrepo.py @@ -4,7 +4,7 @@ from argparse import ArgumentParser, Namespace from gbp_testkit import DjangoTestCase as TestCase -from unittest_fixtures import requires +from unittest_fixtures import Fixtures, given from gentoo_build_publisher.build_publisher import BuildPublisher from gentoo_build_publisher.cli import addrepo @@ -12,21 +12,21 @@ from gentoo_build_publisher.types import EbuildRepo -@requires("publisher", "gbp", "console") +@given("publisher", "gbp", "console") class AddRepoTestCase(TestCase): - def test_calls_grapql_with_the_expected_args(self) -> None: + def test_calls_graphql_with_the_expected_args(self, fixtures: Fixtures) -> None: args = Namespace( name="gentoo", repo="https://anongit.gentoo.org/git/repo/gentoo.git", branch="master", ) - console = self.fixtures.console - exit_status = addrepo.handler(args, self.fixtures.gbp, console) + console = fixtures.console + exit_status = addrepo.handler(args, fixtures.gbp, console) self.assertEqual(exit_status, 0) - def test_when_item_already_exists(self) -> None: - publisher: BuildPublisher = self.fixtures.publisher + def test_when_item_already_exists(self, fixtures: Fixtures) -> None: + publisher: BuildPublisher = fixtures.publisher publisher.jenkins.make_folder(ProjectPath("repos")) publisher.jenkins.create_repo_job( EbuildRepo(name="gentoo", url="foo", branch="master") @@ -37,8 +37,8 @@ def test_when_item_already_exists(self) -> None: repo="https://anongit.gentoo.org/git/repo/gentoo.git", branch="master", ) - console = self.fixtures.console - exit_status = addrepo.handler(args, self.fixtures.gbp, console) + console = fixtures.console + exit_status = addrepo.handler(args, fixtures.gbp, console) self.assertEqual(exit_status, 1) self.assertEqual( diff --git a/tests/test_cli_apikey.py b/tests/test_cli_apikey.py index 7747c5d..4556516 100644 --- a/tests/test_cli_apikey.py +++ b/tests/test_cli_apikey.py @@ -7,11 +7,10 @@ from dataclasses import replace from unittest.mock import Mock, patch -import unittest_fixtures as fixture from django.conf import settings from gbp_testkit import DjangoTestCase, TestCase from gbp_testkit.helpers import LOCAL_TIMEZONE -from unittest_fixtures import requires +from unittest_fixtures import Fixtures, given, where from gentoo_build_publisher import models, publisher, utils from gentoo_build_publisher.cli import apikey @@ -19,10 +18,10 @@ from gentoo_build_publisher.utils import time -@requires("console") +@given("console") class GBPCreateTests(DjangoTestCase): - def test_create_api_key_with_given_name(self) -> None: - console = self.fixtures.console + def test_create_api_key_with_given_name(self, fixtures: Fixtures) -> None: + console = fixtures.console mock_gbp = Mock(name="gbp") namespace = Namespace(action="create", name="test") @@ -41,15 +40,15 @@ def test_create_api_key_with_given_name(self) -> None: key, ) - def test_name_is_case_insensitive(self) -> None: - console = self.fixtures.console + def test_name_is_case_insensitive(self, fixtures: Fixtures) -> None: + console = fixtures.console apikey.handler(Namespace(action="create", name="TEST"), Mock(), console) self.assertFalse(models.ApiKey.objects.filter(name="TEST").exists()) self.assertTrue(models.ApiKey.objects.filter(name="test").exists()) - def test_name_already_exists(self) -> None: - console = self.fixtures.console + def test_name_already_exists(self, fixtures: Fixtures) -> None: + console = fixtures.console api_key = ApiKey( name="test", key=apikey.create_api_key(), created=time.localtime() ) @@ -66,16 +65,16 @@ def test_name_already_exists(self) -> None: self.assertTrue(models.ApiKey.objects.filter(name="test").exists()) self.assertFalse(models.ApiKey.objects.filter(name="TEST").exists()) - def test_create_empty_name(self) -> None: - console = self.fixtures.console + def test_create_empty_name(self, fixtures: Fixtures) -> None: + console = fixtures.console status = apikey.handler(Namespace(action="create", name=""), Mock(), console) self.assertEqual(status, 2) self.assertEqual(console.err.file.getvalue(), "''\n") - def test_create_badchars_in_name(self) -> None: - console = self.fixtures.console + def test_create_badchars_in_name(self, fixtures: Fixtures) -> None: + console = fixtures.console status = apikey.handler( Namespace(action="create", name="b😈d"), Mock(), console @@ -84,8 +83,8 @@ def test_create_badchars_in_name(self) -> None: self.assertEqual(status, 2) self.assertEqual(console.err.file.getvalue(), "'b😈d'\n") - def test_create_name_too_long(self) -> None: - console = self.fixtures.console + def test_create_name_too_long(self, fixtures: Fixtures) -> None: + console = fixtures.console name = "x" * 129 status = apikey.handler(Namespace(action="create", name=name), Mock(), console) @@ -98,8 +97,8 @@ def test_create_name_too_long(self) -> None: ) @patch("gentoo_build_publisher.cli.apikey.create_secret_key") - def test_root_key(self, create_secret_key: Mock) -> None: - console = self.fixtures.console + def test_root_key(self, create_secret_key: Mock, fixtures: Fixtures) -> None: + console = fixtures.console gbp = Mock() create_secret_key.return_value = b"thisisatest" @@ -110,11 +109,11 @@ def test_root_key(self, create_secret_key: Mock) -> None: self.assertEqual(console.out.file.getvalue(), "thisisatest\n") -@requires("console") +@given("console") @patch("gentoo_build_publisher.utils.time.LOCAL_TIMEZONE", new=LOCAL_TIMEZONE) class GBPListTests(DjangoTestCase): - def test(self) -> None: - console = self.fixtures.console + def test(self, fixtures: Fixtures) -> None: + console = fixtures.console timestamp = dt.datetime(2024, 2, 22, 22, 0, tzinfo=dt.UTC) for name in ["this", "that", "the", "other"]: api_key = ApiKey(name=name, key=apikey.create_api_key(), created=timestamp) @@ -139,8 +138,8 @@ def test(self) -> None: """ self.assertEqual(console.out.file.getvalue(), expected) - def test_with_no_keys(self) -> None: - console = self.fixtures.console + def test_with_no_keys(self, fixtures: Fixtures) -> None: + console = fixtures.console gbp = Mock() status = apikey.handler(Namespace(action="list"), gbp, console) @@ -149,12 +148,11 @@ def test_with_no_keys(self) -> None: self.assertEqual(console.out.file.getvalue(), "No API keys registered.\n") -@fixture.requires("tmpdir", "publisher", "api_keys", "console") +@given("tmpdir", "publisher", "api_keys", "console") +@where(api_keys={"api_key_names": ["this", "that", "the", "other"]}) class GBPDeleteTests(DjangoTestCase): - options = {"api_key_names": ["this", "that", "the", "other"]} - - def test_delete(self) -> None: - console = self.fixtures.console + def test_delete(self, fixtures: Fixtures) -> None: + console = fixtures.console namespace = Namespace(action="delete", name="that") status = apikey.handler(namespace, Mock(), console) @@ -163,8 +161,8 @@ def test_delete(self) -> None: key_query = models.ApiKey.objects.filter(name="that") self.assertFalse(key_query.exists(), "key not deleted") - def test_delete_is_case_insensitive(self) -> None: - console = self.fixtures.console + def test_delete_is_case_insensitive(self, fixtures: Fixtures) -> None: + console = fixtures.console namespace = Namespace(action="delete", name="THAT") status = apikey.handler(namespace, Mock(), console) @@ -173,8 +171,8 @@ def test_delete_is_case_insensitive(self) -> None: key_query = models.ApiKey.objects.filter(name="that") self.assertFalse(key_query.exists(), "key not deleted") - def test_delete_name_does_not_exist(self) -> None: - console = self.fixtures.console + def test_delete_name_does_not_exist(self, fixtures: Fixtures) -> None: + console = fixtures.console namespace = Namespace(action="delete", name="bogus") status = apikey.handler(namespace, Mock(), console) @@ -183,10 +181,10 @@ def test_delete_name_does_not_exist(self) -> None: self.assertEqual(console.err.file.getvalue(), "No key exists with that name.\n") -@requires("console") +@given("console") class GBPAPIKeyTests(TestCase): - def test_unknown_action(self) -> None: - console = self.fixtures.console + def test_unknown_action(self, fixtures: Fixtures) -> None: + console = fixtures.console namespace = Namespace(action="bogus") status = apikey.handler(namespace, Mock(), console) diff --git a/tests/test_cli_check.py b/tests/test_cli_check.py index b39d04b..e1928ac 100644 --- a/tests/test_cli_check.py +++ b/tests/test_cli_check.py @@ -6,16 +6,18 @@ import shutil from argparse import ArgumentParser, Namespace -import unittest_fixtures as fixture from gbp_testkit import TestCase from gbp_testkit.factories import BuildFactory +from unittest_fixtures import Fixtures, given from gentoo_build_publisher import publisher from gentoo_build_publisher.cli import check from gentoo_build_publisher.types import Build, Content +# pylint: disable=unused-argument -@fixture.requires("tmpdir", "publisher", "gbp", "console") + +@given("tmpdir", "publisher", "gbp", "console") class GBPChkTestCase(TestCase): def build_with_missing_content(self, content: Content) -> Build: build = BuildFactory() @@ -33,39 +35,39 @@ def orphan_build(self) -> Build: return build - def test_empty_system(self) -> None: - console = self.fixtures.console - check.handler(Namespace(), self.fixtures.gbp, console) + def test_empty_system(self, fixtures: Fixtures) -> None: + console = fixtures.console + check.handler(Namespace(), fixtures.gbp, console) self.assertEqual(console.out.file.getvalue(), "0 errors, 0 warnings\n") - def test_uncompleted_builds_are_skipped(self) -> None: + def test_uncompleted_builds_are_skipped(self, fixtures: Fixtures) -> None: build = BuildFactory() record = publisher.record(build) publisher.repo.build_records.save(record, completed=None) - console = self.fixtures.console - exit_status = check.handler(Namespace(), self.fixtures.gbp, console) + console = fixtures.console + exit_status = check.handler(Namespace(), fixtures.gbp, console) self.assertEqual(exit_status, 0) - def test_check_tag_with_dots(self) -> None: + def test_check_tag_with_dots(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) publisher.tag(build, "go-1.21.5") - console = self.fixtures.console - exit_status = check.handler(Namespace(), self.fixtures.gbp, console) + console = fixtures.console + exit_status = check.handler(Namespace(), fixtures.gbp, console) self.assertEqual(exit_status, 0, console.err.file.getvalue()) - def test_check_build_content(self) -> None: + def test_check_build_content(self, fixtures: Fixtures) -> None: good_build = BuildFactory() publisher.pull(good_build) bad_build = self.build_with_missing_content(Content.BINPKGS) - console = self.fixtures.console + console = fixtures.console result = check.check_build_content(console) self.assertEqual(result, (1, 0)) @@ -74,14 +76,14 @@ def test_check_build_content(self) -> None: f"^Path missing for {re.escape(str(bad_build))}:", ) - def test_check_orphans(self) -> None: + def test_check_orphans(self, fixtures: Fixtures) -> None: good_build = BuildFactory() publisher.pull(good_build) bad_build = self.orphan_build() binpkg_path = publisher.storage.get_path(bad_build, Content.BINPKGS) - console = self.fixtures.console + console = fixtures.console result = check.check_orphans(console) self.assertEqual(result, (len(Content), 0)) @@ -90,7 +92,7 @@ def test_check_orphans(self) -> None: f"Record missing for {re.escape(str(binpkg_path))}", ) - def test_check_orphans_dangling_symlinks(self) -> None: + def test_check_orphans_dangling_symlinks(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) @@ -102,7 +104,7 @@ def test_check_orphans_dangling_symlinks(self) -> None: # Delete the build. Symlinks are now broken publisher.delete(build) - console = self.fixtures.console + console = fixtures.console result = check.check_orphans(console) self.assertEqual(result, (link_count, 0)) @@ -111,7 +113,7 @@ def test_check_orphans_dangling_symlinks(self) -> None: for line in lines[:-1]: self.assertRegex(line, f"^Broken tag: .*{build.machine}(@broken_tag)?") - def test_check_inconsistent_tags(self) -> None: + def test_check_inconsistent_tags(self, fixtures: Fixtures) -> None: # More than one build is represented by a tag good_build = BuildFactory() publisher.pull(good_build) @@ -129,7 +131,7 @@ def test_check_inconsistent_tags(self) -> None: link = item_path.parent / "larry" link.symlink_to(item_path.name) - console = self.fixtures.console + console = fixtures.console result = check.check_inconsistent_tags(console) self.assertEqual(result, (1, 0)) @@ -137,7 +139,7 @@ def test_check_inconsistent_tags(self) -> None: console.err.file.getvalue(), '^Tag "larry" has multiple targets: ' ) - def test_error_count_in_exit_status(self) -> None: + def test_error_count_in_exit_status(self, fixtures: Fixtures) -> None: for _ in range(2): good_build = BuildFactory() publisher.pull(good_build) @@ -148,28 +150,28 @@ def test_error_count_in_exit_status(self) -> None: for _ in range(2): self.build_with_missing_content(Content.VAR_LIB_PORTAGE) - console = self.fixtures.console - exit_status = check.handler(Namespace(), self.fixtures.gbp, console) + console = fixtures.console + exit_status = check.handler(Namespace(), fixtures.gbp, console) self.assertEqual(exit_status, len(Content) * 3 + 2) stderr_lines = console.err.file.getvalue().split("\n") last_error_line = stderr_lines[-2] self.assertEqual(last_error_line, "gbp check: Errors were encountered") - def test_check_tmpdir_nonempty(self) -> None: + def test_check_tmpdir_nonempty(self, fixtures: Fixtures) -> None: storage = publisher.storage root = storage.root tmp = root / "tmp" dirty_file = tmp / ".keep" dirty_file.write_bytes(b"") - console = self.fixtures.console + console = fixtures.console result = check.check_dirty_temp(console) self.assertEqual(result, (0, 1)) self.assertEqual(console.err.file.getvalue(), f"Warning: {tmp} is not empty.\n") - def test_parse_args(self) -> None: + def test_parse_args(self, fixtures: Fixtures) -> None: # here for completeness parser = ArgumentParser("gbp") check.parse_args(parser) diff --git a/tests/test_cli_delete.py b/tests/test_cli_delete.py index 5861f55..bb1dc91 100644 --- a/tests/test_cli_delete.py +++ b/tests/test_cli_delete.py @@ -2,48 +2,38 @@ # pylint: disable=missing-docstring from argparse import ArgumentParser, Namespace +from typing import Any -import unittest_fixtures as fixture from gbp_testkit import TestCase +from unittest_fixtures import Fixtures, fixture, given, where from gentoo_build_publisher import publisher from gentoo_build_publisher.cli import delete from gentoo_build_publisher.types import Build -@fixture.depends("builds") -def build_fixture( - _options: fixture.FixtureOptions, fixtures: fixture.Fixtures -) -> Build: +@fixture("builds") +def build_fixture(_options: Any, fixtures: Fixtures) -> Build: builds: list[Build] = fixtures.builds return builds[0] -@fixture.depends(build_fixture) -def args_fixture( - _options: fixture.FixtureOptions, fixtures: fixture.Fixtures -) -> Namespace: +@fixture(build_fixture) +def args_fixture(_options: Any, fixtures: Fixtures) -> Namespace: return Namespace(machine="babette", number=fixtures.build.build_id, force=False) -@fixture.depends(build_fixture) -def force_args_fixture( - _options: fixture.FixtureOptions, fixtures: fixture.Fixtures -) -> Namespace: +@fixture(build_fixture) +def force_args_fixture(_options: Any, fixtures: Fixtures) -> Namespace: return Namespace(machine="babette", number=fixtures.build.build_id, force=True) -@fixture.requires( +@given( "pulled_builds", "console", "gbp", build_fixture, args_fixture, force_args_fixture ) +@where(builds={"per_day": 5}, environ={"BUILD_PUBLISHER_MANUAL_DELETE_ENABLE": "true"}) class GBPChkTestCase(TestCase): - options = { - "builds": {"per_day": 6}, - "environ": {"BUILD_PUBLISHER_MANUAL_DELETE_ENABLE": "true"}, - } - - def test_deletes_build(self) -> None: - fixtures = self.fixtures + def test_deletes_build(self, fixtures: Fixtures) -> None: build: Build = fixtures.build self.assertTrue(publisher.pulled(build)) @@ -51,8 +41,7 @@ def test_deletes_build(self) -> None: self.assertFalse(publisher.pulled(build)) - def test_published_build(self) -> None: - fixtures = self.fixtures + def test_published_build(self, fixtures: Fixtures) -> None: build: Build = fixtures.build publisher.publish(build) @@ -67,8 +56,7 @@ def test_published_build(self) -> None: self.assertEqual(status, 0) self.assertFalse(publisher.pulled(build)) - def test_tagged_build(self) -> None: - fixtures = self.fixtures + def test_tagged_build(self, fixtures: Fixtures) -> None: build: Build = fixtures.build publisher.tag(build, "testing") @@ -84,12 +72,11 @@ def test_tagged_build(self) -> None: self.assertFalse(publisher.pulled(build)) -@fixture.requires("pulled_builds", "console", "gbp", build_fixture, args_fixture) +@given("pulled_builds", "console", "gbp", build_fixture, args_fixture) class DisabledDeletestTests(TestCase): options = {"environ": {"BUILD_PUBLISHER_MANUAL_DELETE_ENABLE": "false"}} - def test_deletes_disabled(self) -> None: - fixtures = self.fixtures + def test_deletes_disabled(self, fixtures: Fixtures) -> None: build: Build = fixtures.build console = fixtures.console diff --git a/tests/test_cli_worker.py b/tests/test_cli_worker.py index 9a7b4a8..5b8491a 100644 --- a/tests/test_cli_worker.py +++ b/tests/test_cli_worker.py @@ -2,30 +2,32 @@ from argparse import ArgumentParser, Namespace from unittest import mock -import unittest_fixtures as fixture from gbp_testkit import TestCase +from unittest_fixtures import Fixtures, given from gentoo_build_publisher.cli import worker +# pylint: disable=unused-argument -@fixture.requires("tmpdir", "publisher", "gbp", "console") + +@given("tmpdir", "publisher", "gbp", "console") class WorkerTests(TestCase): """Tests for the worker gbpcli subcommand""" - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: worker_path = "gentoo_build_publisher.worker.rq.RQWorker.work" with mock.patch(worker_path) as mock_work: status = worker.handler( - Namespace(type="rq"), self.fixtures.gbp, self.fixtures.console + Namespace(type="rq"), fixtures.gbp, fixtures.console ) self.assertEqual(status, 0) self.assertEqual( - self.fixtures.console.out.file.getvalue(), + fixtures.console.out.file.getvalue(), "Working for Gentoo Build Publisher!\n", ) mock_work.assert_called_once() - def test_parse_args(self) -> None: + def test_parse_args(self, fixtures: Fixtures) -> None: parser = ArgumentParser("gbp") worker.parse_args(parser) diff --git a/tests/test_fs.py b/tests/test_fs.py index 31f217a..88d428b 100644 --- a/tests/test_fs.py +++ b/tests/test_fs.py @@ -3,41 +3,39 @@ import os import shutil -import unittest_fixtures as fixture from gbp_testkit import TestCase from gbp_testkit.factories import BuildFactory from gbp_testkit.helpers import create_file +from unittest_fixtures import Fixtures, given from gentoo_build_publisher import fs from gentoo_build_publisher.types import Content -@fixture.requires("tmpdir") +@given("tmpdir") class EnsureStorageRootTestCase(TestCase): - def test_creates_dir_if_not_exists(self) -> None: - shutil.rmtree(self.fixtures.tmpdir) + def test_creates_dir_if_not_exists(self, fixtures: Fixtures) -> None: + shutil.rmtree(fixtures.tmpdir) subdirs = ["this", "that", "the other"] - fs.init_root(self.fixtures.tmpdir, subdirs) + fs.init_root(fixtures.tmpdir, subdirs) - self.assertIs(self.fixtures.tmpdir.is_dir(), True) + self.assertIs(fixtures.tmpdir.is_dir(), True) for subdir in subdirs: - self.assertIs(self.fixtures.tmpdir.joinpath(subdir).is_dir(), True) + self.assertIs(fixtures.tmpdir.joinpath(subdir).is_dir(), True) -@fixture.requires("tmpdir", "publisher") +@given("tmpdir", "publisher") class ExtractTestCase(TestCase): - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: build = BuildFactory() - byte_stream = self.fixtures.publisher.jenkins.artifact_builder.get_artifact( - build - ) + byte_stream = fixtures.publisher.jenkins.artifact_builder.get_artifact(build) - path = self.fixtures.tmpdir / "test.tar.gz" + path = fixtures.tmpdir / "test.tar.gz" with open(path, "wb") as outfile: fs.save_stream(byte_stream, outfile) - extracted = self.fixtures.tmpdir / "extracted" + extracted = fixtures.tmpdir / "extracted" fs.extract(path, extracted) self.assertIs(extracted.is_dir(), True) @@ -47,54 +45,58 @@ def test(self) -> None: self.assertIs(path.is_dir(), True) -@fixture.requires("tmpdir") +@given("tmpdir") class QuickCheckTestCase(TestCase): """Tests for the quick_check() helper method""" - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: timestamp = dt.datetime(2021, 10, 30, 7, 10, 39) - file1 = str(create_file(self.fixtures.tmpdir / "foo", b"test", timestamp)) - file2 = str(create_file(self.fixtures.tmpdir / "bar", b"xxxx", timestamp)) + file1 = str(create_file(fixtures.tmpdir / "foo", b"test", timestamp)) + file2 = str(create_file(fixtures.tmpdir / "bar", b"xxxx", timestamp)) result = fs.quick_check(file1, file2) self.assertIs(result, True) - def test_should_return_false_when_file_does_not_exist(self) -> None: + def test_should_return_false_when_file_does_not_exist( + self, fixtures: Fixtures + ) -> None: timestamp = dt.datetime(2021, 10, 30, 7, 10, 39) - file1 = str(create_file(self.fixtures.tmpdir / "foo", b"test", timestamp)) - file2 = str(self.fixtures.tmpdir / "bogus") + file1 = str(create_file(fixtures.tmpdir / "foo", b"test", timestamp)) + file2 = str(fixtures.tmpdir / "bogus") result = fs.quick_check(file1, file2) self.assertIs(result, False) - def test_should_return_false_when_mtimes_differ(self) -> None: + def test_should_return_false_when_mtimes_differ(self, fixtures: Fixtures) -> None: timestamp1 = dt.datetime(2021, 10, 30, 7, 10, 39) timestamp2 = dt.datetime(2021, 10, 30, 7, 10, 40) - file1 = str(create_file(self.fixtures.tmpdir / "foo", b"test", timestamp1)) - file2 = str(create_file(self.fixtures.tmpdir / "bar", b"test", timestamp2)) + file1 = str(create_file(fixtures.tmpdir / "foo", b"test", timestamp1)) + file2 = str(create_file(fixtures.tmpdir / "bar", b"test", timestamp2)) result = fs.quick_check(file1, file2) self.assertIs(result, False) - def test_should_return_false_when_sizes_differ(self) -> None: + def test_should_return_false_when_sizes_differ(self, fixtures: Fixtures) -> None: timestamp = dt.datetime(2021, 10, 30, 7, 10, 39) - file1 = str(create_file(self.fixtures.tmpdir / "foo", b"test", timestamp)) - file2 = str(create_file(self.fixtures.tmpdir / "bar", b"tst", timestamp)) + file1 = str(create_file(fixtures.tmpdir / "foo", b"test", timestamp)) + file2 = str(create_file(fixtures.tmpdir / "bar", b"tst", timestamp)) result = fs.quick_check(file1, file2) self.assertIs(result, False) -@fixture.requires("tmpdir") +@given("tmpdir") class SymlinkTestCase(TestCase): - def test_raise_exception_when_symlink_target_exists_and_not_symlink(self) -> None: + def test_raise_exception_when_symlink_target_exists_and_not_symlink( + self, fixtures: Fixtures + ) -> None: # Given the source and target which is not a symlink - source = create_file(self.fixtures.tmpdir / "source") - target = create_file(self.fixtures.tmpdir / "target") + source = create_file(fixtures.tmpdir / "source") + target = create_file(fixtures.tmpdir / "target") # Then an exception is raised with self.assertRaises(EnvironmentError) as ctx: @@ -106,34 +108,34 @@ def test_raise_exception_when_symlink_target_exists_and_not_symlink(self) -> Non self.assertEqual(exception.args, (f"{target} exists but is not a symlink",)) -@fixture.requires("tmpdir") +@given("tmpdir") class CheckSymlink(TestCase): - def test_good_symlink(self) -> None: - target = create_file(self.fixtures.tmpdir / "target") - symlink = self.fixtures.tmpdir / "symlink" + def test_good_symlink(self, fixtures: Fixtures) -> None: + target = create_file(fixtures.tmpdir / "target") + symlink = fixtures.tmpdir / "symlink" os.symlink(target, symlink) self.assertIs(fs.check_symlink(str(symlink), str(target)), True) - def test_symlink_points_to_different_target(self) -> None: - target = create_file(self.fixtures.tmpdir / "target") - symlink = self.fixtures.tmpdir / "symlink" + def test_symlink_points_to_different_target(self, fixtures: Fixtures) -> None: + target = create_file(fixtures.tmpdir / "target") + symlink = fixtures.tmpdir / "symlink" os.symlink(target, symlink) - other = create_file(self.fixtures.tmpdir / "other") + other = create_file(fixtures.tmpdir / "other") self.assertIs(fs.check_symlink(str(symlink), str(other)), False) - def test_dangling_symlink(self) -> None: - name = self.fixtures.tmpdir / "symlink" + def test_dangling_symlink(self, fixtures: Fixtures) -> None: + name = fixtures.tmpdir / "symlink" os.symlink("bogus", name) self.assertIs(fs.check_symlink(str(name), "bogus"), False) -@fixture.requires("tmpdir") +@given("tmpdir") class CDTests(TestCase): - def test(self) -> None: - tmpdir = str(self.fixtures.tmpdir) + def test(self, fixtures: Fixtures) -> None: + tmpdir = str(fixtures.tmpdir) self.assertNotEqual(os.getcwd(), tmpdir) diff --git a/tests/test_graphql.py b/tests/test_graphql.py index 7f853e1..c9eb6cd 100644 --- a/tests/test_graphql.py +++ b/tests/test_graphql.py @@ -1,17 +1,16 @@ """Tests for the GraphQL interface for Gentoo Build Publisher""" -# pylint: disable=missing-docstring,too-many-lines +# pylint: disable=missing-docstring,too-many-lines,unused-argument import datetime as dt import os from typing import Any from unittest import mock -import unittest_fixtures as fixture from gbp_testkit import TestCase from gbp_testkit.factories import PACKAGE_INDEX, BuildFactory, BuildRecordFactory from gbp_testkit.helpers import BUILD_LOGS, graphql from graphql import GraphQLResolveInfo -from unittest_fixtures import parametrized +from unittest_fixtures import Fixtures, fixture, given, parametrized from gentoo_build_publisher import publisher from gentoo_build_publisher.cli import apikey @@ -44,13 +43,13 @@ def assert_data(test_case: TestCase, result: dict, expected: dict) -> None: test_case.assertEqual(data, expected) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class BuildQueryTestCase(TestCase): """Tests for the build query""" maxDiff = None - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: build = BuildFactory() artifact_builder = publisher.jenkins.artifact_builder artifact_builder.timer = 1646115094 @@ -83,7 +82,7 @@ def test(self) -> None: } """ - result = graphql(self.fixtures.client, query, variables={"id": build.id}) + result = graphql(fixtures.client, query, variables={"id": build.id}) expected = { "build": { @@ -104,7 +103,7 @@ def test(self) -> None: assert_data(self, result, expected) - def test_packages(self) -> None: + def test_packages(self, fixtures: Fixtures) -> None: # given the pulled build with packages build = BuildFactory() publisher.pull(build) @@ -117,12 +116,12 @@ def test_packages(self) -> None: } } """ - result = graphql(self.fixtures.client, query, {"id": build.id}) + result = graphql(fixtures.client, query, {"id": build.id}) # Then we get the list of packages in the build assert_data(self, result, {"build": {"packages": PACKAGE_INDEX}}) - def test_packages_when_not_pulled_returns_none(self) -> None: + def test_packages_when_not_pulled_returns_none(self, fixtures: Fixtures) -> None: # given the unpulled package build = BuildFactory() publisher.repo.build_records.save(publisher.record(build)) @@ -135,12 +134,14 @@ def test_packages_when_not_pulled_returns_none(self) -> None: } } """ - result = graphql(self.fixtures.client, query, {"id": build.id}) + result = graphql(fixtures.client, query, {"id": build.id}) # Then none is returned assert_data(self, result, {"build": {"packages": None}}) - def test_packages_should_return_none_when_package_index_missing(self) -> None: + def test_packages_should_return_none_when_package_index_missing( + self, fixtures: Fixtures + ) -> None: # given the pulled build with index file missing build = BuildFactory() publisher.pull(build) @@ -155,12 +156,14 @@ def test_packages_should_return_none_when_package_index_missing(self) -> None: } } """ - result = graphql(self.fixtures.client, query, {"id": build.id}) + result = graphql(fixtures.client, query, {"id": build.id}) # Then none is returned assert_data(self, result, {"build": {"packages": None}}) - def test_packagesbuild_should_return_error_when_gbpjson_missing(self) -> None: + def test_packagesbuild_should_return_error_when_gbpjson_missing( + self, fixtures: Fixtures + ) -> None: # given the pulled build with gbp.json missing build = BuildFactory() publisher.pull(build) @@ -178,7 +181,7 @@ def test_packagesbuild_should_return_error_when_gbpjson_missing(self) -> None: } } """ - result = graphql(self.fixtures.client, query, {"id": build.id}) + result = graphql(fixtures.client, query, {"id": build.id}) self.assertEqual( result["data"]["build"], @@ -189,13 +192,13 @@ def test_packagesbuild_should_return_error_when_gbpjson_missing(self) -> None: self.assertEqual(result["errors"][0]["path"], ["build", "packagesBuilt"]) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class BuildsQueryTestCase(TestCase): """Tests for the builds query""" maxDiff = None - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: now = dt.datetime(2021, 9, 30, 20, 17, tzinfo=dt.UTC) builds = BuildFactory.create_batch(3) @@ -214,7 +217,7 @@ def test(self) -> None: """ result = graphql( - self.fixtures.client, query, variables={"machine": builds[0].machine} + fixtures.client, query, variables={"machine": builds[0].machine} ) expected = [ @@ -224,7 +227,9 @@ def test(self) -> None: assert_data(self, result, {"builds": expected}) - def test_older_build_pulled_after_newer_should_not_sort_before(self) -> None: + def test_older_build_pulled_after_newer_should_not_sort_before( + self, fixtures: Fixtures + ) -> None: # Build first build first_build = BuildFactory(machine="lighthouse", build_id="10000") publisher.jenkins.artifact_builder.build_info(first_build) @@ -250,9 +255,7 @@ def test_older_build_pulled_after_newer_should_not_sort_before(self) -> None: } } """ - result = graphql( - self.fixtures.client, query, variables={"machine": "lighthouse"} - ) + result = graphql(fixtures.client, query, variables={"machine": "lighthouse"}) assert_data( self, @@ -261,8 +264,8 @@ def test_older_build_pulled_after_newer_should_not_sort_before(self) -> None: ) -@fixture.depends("publisher") -def latest(_options: fixture.FixtureOptions, _fixtures: fixture.Fixtures) -> Build: +@fixture("publisher") +def latest(_options: Any, _fixtures: Fixtures) -> Build: publisher.repo.build_records.save( BuildRecordFactory.build( built=dt.datetime(2021, 4, 25, 18, 0, tzinfo=dt.UTC), @@ -286,11 +289,11 @@ def latest(_options: fixture.FixtureOptions, _fixtures: fixture.Fixtures) -> Bui return latest_build -@fixture.requires("tmpdir", "publisher", latest, "client") +@given("tmpdir", "publisher", latest, "client") class LatestQueryTestCase(TestCase): """Tests for the latest query""" - def test_when_no_builds_should_respond_with_none(self) -> None: + def test_when_no_builds_should_respond_with_none(self, fixtures: Fixtures) -> None: query = """ { latest(machine: "bogus") { @@ -298,11 +301,13 @@ def test_when_no_builds_should_respond_with_none(self) -> None: } } """ - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) assert_data(self, result, {"latest": None}) - def test_should_return_the_latest_submitted_completed(self) -> None: + def test_should_return_the_latest_submitted_completed( + self, fixtures: Fixtures + ) -> None: query = """ { latest(machine: "babette") { @@ -310,15 +315,13 @@ def test_should_return_the_latest_submitted_completed(self) -> None: } } """ - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) - assert_data(self, result, {"latest": {"id": str(self.fixtures.latest)}}) + assert_data(self, result, {"latest": {"id": str(fixtures.latest)}}) -@fixture.depends("publisher") -def diff_query_builds( - _options: fixture.FixtureOptions, fixtures: fixture.Fixtures -) -> dict[str, Build]: +@fixture("publisher") +def diff_query_builds(_options: Any, fixtures: Fixtures) -> dict[str, Build]: # Given the first build with tar-1.34 left = BuildFactory() artifact_builder = fixtures.publisher.jenkins.artifact_builder @@ -334,11 +337,11 @@ def diff_query_builds( return {"left": left, "right": right} -@fixture.requires("tmpdir", "publisher", diff_query_builds, "client") +@given("tmpdir", "publisher", diff_query_builds, "client") class DiffQueryTestCase(TestCase): """Tests for the diff query""" - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: # When we call get the diff view given the 2 builds query = """ query Diff($left: ID!, $right: ID!) { @@ -356,9 +359,9 @@ def test(self) -> None: } } """ - builds = self.fixtures.diff_query_builds + builds = fixtures.diff_query_builds variables = {"left": builds["left"].id, "right": builds["right"].id} - result = graphql(self.fixtures.client, query, variables=variables) + result = graphql(fixtures.client, query, variables=variables) # Then the differences are given between the two builds expected = { @@ -373,7 +376,9 @@ def test(self) -> None: } assert_data(self, result, expected) - def test_should_exclude_build_data_when_not_selected(self) -> None: + def test_should_exclude_build_data_when_not_selected( + self, fixtures: Fixtures + ) -> None: query = """ query ($left: ID!, $right: ID!) { diff(left: $left, right: $right) { @@ -384,10 +389,10 @@ def test_should_exclude_build_data_when_not_selected(self) -> None: } } """ - builds = self.fixtures.diff_query_builds + builds = fixtures.diff_query_builds variables = {"left": builds["left"].id, "right": builds["right"].id} - result = graphql(self.fixtures.client, query, variables=variables) + result = graphql(fixtures.client, query, variables=variables) # Then the differences are given between the two builds expected = { @@ -400,7 +405,9 @@ def test_should_exclude_build_data_when_not_selected(self) -> None: } assert_data(self, result, expected) - def test_should_return_error_when_left_does_not_exist(self) -> None: + def test_should_return_error_when_left_does_not_exist( + self, fixtures: Fixtures + ) -> None: query = """ query Diff($left: ID!, $right: ID!) { diff(left: $left, right: $right) { @@ -417,9 +424,9 @@ def test_should_return_error_when_left_does_not_exist(self) -> None: } } """ - builds = self.fixtures.diff_query_builds + builds = fixtures.diff_query_builds variables = {"left": "bogus.1", "right": builds["right"].id} - result = graphql(self.fixtures.client, query, variables=variables) + result = graphql(fixtures.client, query, variables=variables) # Then an error is returned self.assertEqual(result["data"]["diff"], None) @@ -427,7 +434,9 @@ def test_should_return_error_when_left_does_not_exist(self) -> None: result["errors"][0]["message"], "Build does not exist: bogus.1" ) - def test_should_return_error_when_right_does_not_exist(self) -> None: + def test_should_return_error_when_right_does_not_exist( + self, fixtures: Fixtures + ) -> None: query = """ query ($left: ID!, $right: ID!) { diff(left: $left, right: $right) { @@ -444,9 +453,9 @@ def test_should_return_error_when_right_does_not_exist(self) -> None: } } """ - builds = self.fixtures.diff_query_builds + builds = fixtures.diff_query_builds variables = {"left": builds["left"].id, "right": "bogus.1"} - result = graphql(self.fixtures.client, query, variables=variables) + result = graphql(fixtures.client, query, variables=variables) # Then an error is returned self.assertEqual(result["data"]["diff"], None) @@ -455,13 +464,13 @@ def test_should_return_error_when_right_does_not_exist(self) -> None: ) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class MachinesQueryTestCase(TestCase): """Tests for the machines query""" maxDiff = None - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: babette_builds = BuildFactory.create_batch(3, machine="babette") lighthouse_builds = BuildFactory.create_batch(3, machine="lighthouse") @@ -490,7 +499,7 @@ def test(self) -> None: } """ - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) expected = [ { @@ -510,7 +519,7 @@ def test(self) -> None: ] assert_data(self, result, {"machines": expected}) - def test_only_machine(self) -> None: + def test_only_machine(self, fixtures: Fixtures) -> None: # basically test that only selecting the name doesn't query other infos # (coverage.py) for build in BuildFactory.create_batch( @@ -525,7 +534,7 @@ def test_only_machine(self) -> None: } } """ - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) assert_data( self, @@ -533,7 +542,7 @@ def test_only_machine(self) -> None: {"machines": [{"machine": "babette"}, {"machine": "lighthouse"}]}, ) - def test_latest_build_is_published(self) -> None: + def test_latest_build_is_published(self, fixtures: Fixtures) -> None: build = BuildFactory.create() publisher.pull(build) @@ -549,15 +558,15 @@ def test_latest_build_is_published(self) -> None: } } """ - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) self.assertFalse(result["data"]["machines"][0]["latestBuild"]["published"]) publisher.publish(build) - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) self.assertTrue(result["data"]["machines"][0]["latestBuild"]["published"]) - def test_with_names_filter(self) -> None: + def test_with_names_filter(self, fixtures: Fixtures) -> None: builds = [ *BuildFactory.create_batch(3, machine="foo"), *BuildFactory.create_batch(2, machine="bar"), @@ -573,16 +582,16 @@ def test_with_names_filter(self) -> None: } } """ - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) self.assertEqual(len(result["data"]["machines"]), 2) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class PublishMutationTestCase(TestCase): """Tests for the publish mutation""" - def test_publish_when_pulled(self) -> None: + def test_publish_when_pulled(self, fixtures: Fixtures) -> None: """Should publish builds""" build = BuildFactory() publisher.pull(build) @@ -596,11 +605,11 @@ def test_publish_when_pulled(self) -> None: } } """ - result = graphql(self.fixtures.client, query, variables={"id": build.id}) + result = graphql(fixtures.client, query, variables={"id": build.id}) assert_data(self, result, {"publish": {"publishedBuild": {"id": build.id}}}) - def test_publish_when_not_pulled(self) -> None: + def test_publish_when_not_pulled(self, fixtures: Fixtures) -> None: """Should publish builds""" query = """ mutation { @@ -612,16 +621,16 @@ def test_publish_when_not_pulled(self) -> None: } """ with mock.patch(WORKER) as mock_worker: - graphql(self.fixtures.client, query) + graphql(fixtures.client, query) mock_worker.run.assert_called_once_with(tasks.publish_build, "babette.193") -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class PullMutationTestCase(TestCase): """Tests for the pull mutation""" - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: """Should publish builds""" build = BuildFactory() @@ -634,14 +643,14 @@ def test(self) -> None: } }""" with mock.patch(WORKER) as mock_worker: - result = graphql(self.fixtures.client, query, variables={"id": build.id}) + result = graphql(fixtures.client, query, variables={"id": build.id}) assert_data(self, result, {"pull": {"publishedBuild": None}}) mock_worker.run.assert_called_once_with( tasks.pull_build, build.id, note=None, tags=None ) - def test_pull_with_note(self) -> None: + def test_pull_with_note(self, fixtures: Fixtures) -> None: build = BuildFactory() query = """ @@ -654,7 +663,7 @@ def test_pull_with_note(self) -> None: }""" with mock.patch(WORKER) as mock_worker: result = graphql( - self.fixtures.client, + fixtures.client, query, variables={"id": build.id, "note": "This is a test"}, ) @@ -664,7 +673,7 @@ def test_pull_with_note(self) -> None: tasks.pull_build, build.id, note="This is a test", tags=None ) - def test_pull_with_tag(self) -> None: + def test_pull_with_tag(self, fixtures: Fixtures) -> None: build = BuildFactory() query = """ @@ -677,7 +686,7 @@ def test_pull_with_tag(self) -> None: }""" with mock.patch(WORKER) as mock_worker: result = graphql( - self.fixtures.client, + fixtures.client, query, variables={"id": build.id, "tags": ["emptytree"]}, ) @@ -688,20 +697,20 @@ def test_pull_with_tag(self) -> None: ) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class ScheduleBuildMutationTestCase(TestCase): """Tests for the build mutation""" maxDiff = None - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: query = 'mutation { scheduleBuild(machine: "babette") }' with mock.patch.object(publisher, "schedule_build") as mock_schedule_build: mock_schedule_build.return_value = ( "https://jenkins.invalid/queue/item/31528/" ) - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) self.assertEqual( result, @@ -709,7 +718,7 @@ def test(self) -> None: ) mock_schedule_build.assert_called_once_with("babette") - def test_with_params(self) -> None: + def test_with_params(self, fixtures: Fixtures) -> None: query = """mutation { scheduleBuild( @@ -723,7 +732,7 @@ def test_with_params(self) -> None: mock_schedule_build.return_value = ( "https://jenkins.invalid/queue/item/31528/" ) - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) self.assertEqual( result, @@ -731,12 +740,14 @@ def test_with_params(self) -> None: ) mock_schedule_build.assert_called_once_with("babette", BUILD_TARGET="world") - def test_should_return_error_when_schedule_build_fails(self) -> None: + def test_should_return_error_when_schedule_build_fails( + self, fixtures: Fixtures + ) -> None: query = 'mutation { scheduleBuild(machine: "babette") }' with mock.patch.object(publisher, "schedule_build") as mock_schedule_build: mock_schedule_build.side_effect = Exception("The end is near") - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) expected = { "data": {"scheduleBuild": None}, @@ -751,14 +762,14 @@ def test_should_return_error_when_schedule_build_fails(self) -> None: self.assertEqual(result, expected) mock_schedule_build.assert_called_once_with("babette") - def test_with_repos(self) -> None: + def test_with_repos(self, fixtures: Fixtures) -> None: query = 'mutation { scheduleBuild(machine: "gentoo", isRepo: true) }' with mock.patch.object(publisher, "schedule_build") as mock_schedule_build: mock_schedule_build.return_value = ( "https://jenkins.invalid/queue/item/31528/" ) - result = graphql(self.fixtures.client, query) + result = graphql(fixtures.client, query) self.assertEqual( result, @@ -767,13 +778,13 @@ def test_with_repos(self) -> None: mock_schedule_build.assert_called_once_with("repos/job/gentoo") -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class KeepBuildMutationTestCase(TestCase): """Tests for the keep mutation""" maxDiff = None - def test_should_keep_existing_build(self) -> None: + def test_should_keep_existing_build(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) query = """ @@ -783,11 +794,13 @@ def test_should_keep_existing_build(self) -> None: } } """ - result = graphql(self.fixtures.client, query, variables={"id": str(build)}) + result = graphql(fixtures.client, query, variables={"id": str(build)}) assert_data(self, result, {"keepBuild": {"keep": True}}) - def test_should_return_none_when_build_doesnt_exist(self) -> None: + def test_should_return_none_when_build_doesnt_exist( + self, fixtures: Fixtures + ) -> None: query = """ mutation KeepBuild($id: ID!) { keepBuild(id: $id) { @@ -796,16 +809,16 @@ def test_should_return_none_when_build_doesnt_exist(self) -> None: } """ - result = graphql(self.fixtures.client, query, variables={"id": "bogus.309"}) + result = graphql(fixtures.client, query, variables={"id": "bogus.309"}) assert_data(self, result, {"keepBuild": None}) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class ReleaseBuildMutationTestCase(TestCase): """Tests for the releaseBuild mutation""" - def test_should_release_existing_build(self) -> None: + def test_should_release_existing_build(self, fixtures: Fixtures) -> None: build = BuildFactory() record = publisher.record(build) publisher.repo.build_records.save(record, keep=True) @@ -818,11 +831,13 @@ def test_should_release_existing_build(self) -> None: } """ - result = graphql(self.fixtures.client, query, variables={"id": build.id}) + result = graphql(fixtures.client, query, variables={"id": build.id}) assert_data(self, result, {"releaseBuild": {"keep": False}}) - def test_should_return_none_when_build_doesnt_exist(self) -> None: + def test_should_return_none_when_build_doesnt_exist( + self, fixtures: Fixtures + ) -> None: query = """ mutation ($id: ID!) { releaseBuild(id: $id) { @@ -831,16 +846,16 @@ def test_should_return_none_when_build_doesnt_exist(self) -> None: } """ - result = graphql(self.fixtures.client, query, variables={"id": "bogus.309"}) + result = graphql(fixtures.client, query, variables={"id": "bogus.309"}) assert_data(self, result, {"releaseBuild": None}) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class CreateNoteMutationTestCase(TestCase): """Tests for the createNote mutation""" - def test_set_text(self) -> None: + def test_set_text(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) note_text = "Hello, world!" @@ -853,14 +868,14 @@ def test_set_text(self) -> None: """ result = graphql( - self.fixtures.client, query, variables={"id": str(build), "note": note_text} + fixtures.client, query, variables={"id": str(build), "note": note_text} ) assert_data(self, result, {"createNote": {"notes": note_text}}) record = publisher.repo.build_records.get(build) self.assertEqual(record.note, note_text) - def test_set_none(self) -> None: + def test_set_none(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) @@ -873,7 +888,7 @@ def test_set_none(self) -> None: """ result = graphql( - self.fixtures.client, query, variables={"id": build.id, "note": None} + fixtures.client, query, variables={"id": build.id, "note": None} ) assert_data(self, result, {"createNote": {"notes": None}}) @@ -881,7 +896,9 @@ def test_set_none(self) -> None: record = publisher.record(build) self.assertEqual(record.note, None) - def test_should_return_none_when_build_doesnt_exist(self) -> None: + def test_should_return_none_when_build_doesnt_exist( + self, fixtures: Fixtures + ) -> None: query = """ mutation ($id: ID!, $note: String) { createNote(id: $id, note: $note) { @@ -891,15 +908,15 @@ def test_should_return_none_when_build_doesnt_exist(self) -> None: """ result = graphql( - self.fixtures.client, query, variables={"id": "bogus.309", "note": None} + fixtures.client, query, variables={"id": "bogus.309", "note": None} ) assert_data(self, result, {"createNote": None}) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class TagsTestCase(TestCase): - def test_createbuildtag_mutation_tags_the_build(self) -> None: + def test_createbuildtag_mutation_tags_the_build(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) query = """ @@ -911,12 +928,14 @@ def test_createbuildtag_mutation_tags_the_build(self) -> None: """ result = graphql( - self.fixtures.client, query, variables={"id": build.id, "tag": "prod"} + fixtures.client, query, variables={"id": build.id, "tag": "prod"} ) assert_data(self, result, {"createBuildTag": {"tags": ["prod"]}}) - def test_removebuildtag_mutation_removes_tag_from_the_build(self) -> None: + def test_removebuildtag_mutation_removes_tag_from_the_build( + self, fixtures: Fixtures + ) -> None: build = BuildFactory() publisher.pull(build) publisher.tag(build, "prod") @@ -930,14 +949,12 @@ def test_removebuildtag_mutation_removes_tag_from_the_build(self) -> None: """ result = graphql( - self.fixtures.client, - query, - variables={"machine": build.machine, "tag": "prod"}, + fixtures.client, query, variables={"machine": build.machine, "tag": "prod"} ) assert_data(self, result, {"removeBuildTag": {"tags": []}}) - def test_resolvetag_query_resolves_tag(self) -> None: + def test_resolvetag_query_resolves_tag(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) publisher.tag(build, "prod") @@ -951,14 +968,14 @@ def test_resolvetag_query_resolves_tag(self) -> None: """ result = graphql( - self.fixtures.client, - query, - variables={"machine": build.machine, "tag": "prod"}, + fixtures.client, query, variables={"machine": build.machine, "tag": "prod"} ) assert_data(self, result, {"resolveBuildTag": {"id": build.id}}) - def test_resolvetag_query_resolves_to_none_when_tag_does_not_exist(self) -> None: + def test_resolvetag_query_resolves_to_none_when_tag_does_not_exist( + self, fixtures: Fixtures + ) -> None: build = BuildFactory() publisher.pull(build) @@ -971,17 +988,13 @@ def test_resolvetag_query_resolves_to_none_when_tag_does_not_exist(self) -> None """ result = graphql( - self.fixtures.client, - query, - variables={"machine": build.machine, "tag": "prod"}, + fixtures.client, query, variables={"machine": build.machine, "tag": "prod"} ) assert_data(self, result, {"resolveBuildTag": None}) -def search_query_builds( - _options: fixture.FixtureOptions, _fixtures: fixture.Fixtures -) -> list[Build]: +def search_query_builds(_options: Any, _fixtures: Fixtures) -> list[Build]: for _, field in SEARCH_PARAMS: build1 = BuildFactory() record = publisher.record(build1) @@ -993,7 +1006,7 @@ def search_query_builds( return [build1, build2] -@fixture.requires("tmpdir", "publisher", search_query_builds, "client") +@given("tmpdir", "publisher", search_query_builds, "client") class SearchQueryTestCase(TestCase): """Tests for the search query""" @@ -1007,9 +1020,9 @@ class SearchQueryTestCase(TestCase): """ @parametrized(SEARCH_PARAMS) - def test_single_match(self, enum: str, field: str) -> None: + def test_single_match(self, enum: str, field: str, fixtures: Fixtures) -> None: result = graphql( - self.fixtures.client, + fixtures.client, self.query, variables={"machine": "babette", "field": enum, "key": "foo"}, ) @@ -1021,9 +1034,9 @@ def test_single_match(self, enum: str, field: str) -> None: ) @parametrized(SEARCH_PARAMS) - def test_multiple_match(self, enum: str, field: str) -> None: + def test_multiple_match(self, enum: str, field: str, fixtures: Fixtures) -> None: result = graphql( - self.fixtures.client, + fixtures.client, self.query, variables={"machine": "babette", "field": enum, "key": "test"}, ) @@ -1041,13 +1054,15 @@ def test_multiple_match(self, enum: str, field: str) -> None: assert_data(self, result, {"search": expected}) @parametrized(SEARCH_PARAMS) - def test_only_matches_given_machine(self, enum: str, field: str) -> None: + def test_only_matches_given_machine( + self, enum: str, field: str, fixtures: Fixtures + ) -> None: build = BuildFactory(machine="lighthouse") record = publisher.record(build) publisher.repo.build_records.save(record, **{field: "test foo"}) result = graphql( - self.fixtures.client, + fixtures.client, self.query, variables={"machine": "lighthouse", "field": enum, "key": "test"}, ) @@ -1065,9 +1080,9 @@ def test_only_matches_given_machine(self, enum: str, field: str) -> None: }, ) - def test_when_named_machine_does_not_exist(self) -> None: + def test_when_named_machine_does_not_exist(self, fixtures: Fixtures) -> None: result = graphql( - self.fixtures.client, + fixtures.client, self.query, variables={"machine": "bogus", "field": "NOTES", "key": "test"}, ) @@ -1075,10 +1090,8 @@ def test_when_named_machine_does_not_exist(self) -> None: assert_data(self, result, {"search": []}) -@fixture.depends("publisher") -def search_notes_query_builds( - _options: fixture.FixtureOptions, _fixtures: fixture.Fixtures -) -> list[Build]: +@fixture("publisher") +def search_notes_query_builds(_options: Any, _fixtures: Fixtures) -> list[Build]: build1 = BuildFactory() record = publisher.record(build1) publisher.repo.build_records.save(record, note="test foo") @@ -1089,7 +1102,7 @@ def search_notes_query_builds( return [build1, build2] -@fixture.requires("tmpdir", "publisher", search_notes_query_builds, "client") +@given("tmpdir", "publisher", search_notes_query_builds, "client") class SearchNotesQueryTestCase(TestCase): """tests for the searchNotes query""" @@ -1102,26 +1115,22 @@ class SearchNotesQueryTestCase(TestCase): } """ - def test_single_match(self) -> None: + def test_single_match(self, fixtures: Fixtures) -> None: result = graphql( - self.fixtures.client, - self.query, - variables={"machine": "babette", "key": "foo"}, + fixtures.client, self.query, variables={"machine": "babette", "key": "foo"} ) - builds = self.fixtures.search_notes_query_builds + builds = fixtures.search_notes_query_builds assert_data( self, result, {"searchNotes": [{"id": builds[0].id, "notes": "test foo"}]} ) - def test_multiple_match(self) -> None: + def test_multiple_match(self, fixtures: Fixtures) -> None: result = graphql( - self.fixtures.client, - self.query, - variables={"machine": "babette", "key": "test"}, + fixtures.client, self.query, variables={"machine": "babette", "key": "test"} ) - builds = self.fixtures.search_notes_query_builds + builds = fixtures.search_notes_query_builds assert_data( self, result, @@ -1133,14 +1142,14 @@ def test_multiple_match(self) -> None: }, ) - def test_only_matches_given_machine(self) -> None: + def test_only_matches_given_machine(self, fixtures: Fixtures) -> None: build = BuildFactory(machine="lighthouse") publisher.pull(build) record = publisher.record(build) publisher.repo.build_records.save(record, note="test foo") result = graphql( - self.fixtures.client, + fixtures.client, self.query, variables={"machine": "lighthouse", "key": "test"}, ) @@ -1149,17 +1158,15 @@ def test_only_matches_given_machine(self) -> None: self, result, {"searchNotes": [{"id": build.id, "notes": "test foo"}]} ) - def test_when_named_machine_does_not_exist(self) -> None: + def test_when_named_machine_does_not_exist(self, fixtures: Fixtures) -> None: result = graphql( - self.fixtures.client, - self.query, - variables={"machine": "bogus", "key": "test"}, + fixtures.client, self.query, variables={"machine": "bogus", "key": "test"} ) assert_data(self, result, {"searchNotes": []}) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class WorkingTestCase(TestCase): query = """ { @@ -1169,7 +1176,7 @@ class WorkingTestCase(TestCase): } """ - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: publisher.pull(BuildFactory()) publisher.pull(BuildFactory(machine="lighthouse")) working = BuildFactory() @@ -1177,24 +1184,24 @@ def test(self) -> None: BuildRecord(working.machine, working.build_id) ) - result = graphql(self.fixtures.client, self.query) + result = graphql(fixtures.client, self.query) assert_data(self, result, {"working": [{"id": working.id}]}) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class VersionTestCase(TestCase): maxDiff = None query = """query { version }""" - def test(self) -> None: - result = graphql(self.fixtures.client, self.query) + def test(self, fixtures: Fixtures) -> None: + result = graphql(fixtures.client, self.query) version = get_version() assert_data(self, result, {"version": version}) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class CreateRepoTestCase(TestCase): """Tests for the createRepo mutation""" @@ -1206,9 +1213,9 @@ class CreateRepoTestCase(TestCase): } """ - def test_creates_repo_when_does_not_exist(self) -> None: + def test_creates_repo_when_does_not_exist(self, fixtures: Fixtures) -> None: result = graphql( - self.fixtures.client, + fixtures.client, self.query, variables={ "name": "gentoo", @@ -1220,14 +1227,14 @@ def test_creates_repo_when_does_not_exist(self) -> None: assert_data(self, result, {"createRepo": None}) self.assertTrue(publisher.jenkins.project_exists(ProjectPath("repos/gentoo"))) - def test_returns_error_when_already_exists(self) -> None: + def test_returns_error_when_already_exists(self, fixtures: Fixtures) -> None: publisher.jenkins.make_folder(ProjectPath("repos")) publisher.jenkins.create_repo_job( EbuildRepo(name="gentoo", url="foo", branch="master") ) result = graphql( - self.fixtures.client, + fixtures.client, self.query, variables={ "name": "gentoo", @@ -1241,7 +1248,7 @@ def test_returns_error_when_already_exists(self) -> None: ) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class CreateMachineTestCase(TestCase): """Tests for the createMachine mutation""" @@ -1257,9 +1264,9 @@ class CreateMachineTestCase(TestCase): } """ - def test_creates_machine_when_does_not_exist(self) -> None: + def test_creates_machine_when_does_not_exist(self, fixtures: Fixtures) -> None: result = graphql( - self.fixtures.client, + fixtures.client, self.query, variables={ "name": "babette", @@ -1272,7 +1279,7 @@ def test_creates_machine_when_does_not_exist(self) -> None: assert_data(self, result, {"createMachine": None}) self.assertTrue(publisher.jenkins.project_exists(ProjectPath("babette"))) - def test_returns_error_when_already_exists(self) -> None: + def test_returns_error_when_already_exists(self, fixtures: Fixtures) -> None: job = MachineJob( name="babette", repo=Repo(url="https://github.com/enku/gbp-machines.git", branch="master"), @@ -1281,7 +1288,7 @@ def test_returns_error_when_already_exists(self) -> None: publisher.jenkins.create_machine_job(job) result = graphql( - self.fixtures.client, + fixtures.client, self.query, variables={ "name": "babette", @@ -1296,19 +1303,19 @@ def test_returns_error_when_already_exists(self) -> None: ) -@fixture.requires("tmpdir", "publisher", "client") +@given("tmpdir", "publisher", "client") class MaybeRequiresAPIKeyTests(TestCase): query = 'mutation { scheduleBuild(machine: "babette") }' - def test_enabled(self) -> None: + def test_enabled(self, fixtures: Fixtures) -> None: with mock.patch.dict(os.environ, {"BUILD_PUBLISHER_API_KEY_ENABLE": "yes"}): - error = graphql(self.fixtures.client, self.query)["errors"][0]["message"] + error = graphql(fixtures.client, self.query)["errors"][0]["message"] self.assertEqual(error, "Unauthorized to resolve scheduleBuild") - def test_disabled(self) -> None: + def test_disabled(self, fixtures: Fixtures) -> None: with mock.patch.dict(os.environ, {"BUILD_PUBLISHER_API_KEY_ENABLE": "no"}): - response = graphql(self.fixtures.client, self.query) + response = graphql(fixtures.client, self.query) self.assertNotIn("errors", response) @@ -1320,9 +1327,9 @@ def dummy_resolver( return "permitted" -@fixture.requires("tmpdir", "publisher") +@given("tmpdir", "publisher") class RequireAPIKeyTestCase(TestCase): - def test_good_apikey(self) -> None: + def test_good_apikey(self, fixtures: Fixtures) -> None: name = "test" api_key = ApiKey( name=name, @@ -1338,7 +1345,7 @@ def test_good_apikey(self) -> None: self.assertEqual(resolver(None, info), "permitted") - def test_good_key_updates_records_last_use(self) -> None: + def test_good_key_updates_records_last_use(self, fixtures: Fixtures) -> None: name = "test" api_key = ApiKey( name=name, @@ -1360,7 +1367,7 @@ def test_good_key_updates_records_last_use(self) -> None: api_key = publisher.repo.api_keys.get(name) self.assertIsNot(api_key.last_used, None, "The last_used field was not updated") - def test_no_apikey(self) -> None: + def test_no_apikey(self, fixtures: Fixtures) -> None: gql_context = {"request": Mock(headers={})} info = Mock(context=gql_context) info.path.key = "dummy_resolver" @@ -1373,7 +1380,7 @@ def test_no_apikey(self) -> None: str(context.exception), "Unauthorized to resolve dummy_resolver" ) - def test_bad_apikey(self) -> None: + def test_bad_apikey(self, fixtures: Fixtures) -> None: name = "test" api_key = ApiKey( name=name, diff --git a/tests/test_jenkins.py b/tests/test_jenkins.py index 42a1d96..811bfbe 100644 --- a/tests/test_jenkins.py +++ b/tests/test_jenkins.py @@ -7,11 +7,11 @@ import os from pathlib import Path from typing import Any -from unittest import mock +from unittest import TestCase, mock import requests -import unittest_fixtures as fixture from gbp_testkit.helpers import MockJenkins, test_data +from unittest_fixtures import FixtureContext, Fixtures, given from yarl import URL from gentoo_build_publisher.jenkins import ( @@ -35,7 +35,7 @@ JOB_PARAMS = json.loads(test_data("job_parameters.json")) -class JenkinsTestCase(fixture.BaseTestCase): +class JenkinsTestCase(TestCase): """Tests for the Jenkins api wrapper""" def test_download_artifact(self) -> None: @@ -183,7 +183,7 @@ def test_project_root_bogus_jenkins_base(self) -> None: self.assertEqual(jenkins.project_root, ProjectPath("i/think/this/is/invalid")) -class ProjectPathExistsTestCase(fixture.BaseTestCase): +class ProjectPathExistsTestCase(TestCase): def test_should_return_false_when_does_not_exist(self) -> None: def mock_head(url: str, *args: Any, **kwargs: Any) -> requests.Response: status_code = 404 @@ -236,7 +236,7 @@ def mock_head(_url: str, *args: Any, **kwargs: Any) -> requests.Response: jenkins.project_exists(project_path) -class CreateItemTestCase(fixture.BaseTestCase): +class CreateItemTestCase(TestCase): """Tests for the Jenkins.create_item method""" def test_creates_item(self) -> None: @@ -313,7 +313,7 @@ def test_raises_exception_on_http_errors(self) -> None: ) -class GetItemTestCase(fixture.BaseTestCase): +class GetItemTestCase(TestCase): def test_gets_item(self) -> None: jenkins = MockJenkins(JENKINS_CONFIG) jenkins.root.set(["Gentoo"], "Test") @@ -342,7 +342,7 @@ def test_raises_exception_on_http_errors(self) -> None: ) -class MakeFolderTestCase(fixture.BaseTestCase): +class MakeFolderTestCase(TestCase): """Tests for the Jenkins.make_folder method""" def test_when_folder_does_not_exist_creates_folder(self) -> None: @@ -408,7 +408,7 @@ def test_when_passing_root_and_exists_ok_succeeds(self) -> None: jenkins.make_folder(project_path, exist_ok=True) -class IsFolderTestCase(fixture.BaseTestCase): +class IsFolderTestCase(TestCase): """Tests for the Jenkins.is_folder method""" def test_when_is_a_folder_returns_true(self) -> None: @@ -436,7 +436,7 @@ def test_root_folder(self) -> None: self.assertEqual(jenkins.is_folder(ProjectPath()), True) -class InstallPluginTestCase(fixture.BaseTestCase): +class InstallPluginTestCase(TestCase): """Tests for the Jenkins.install_plugin method""" def test_installs_plugin(self) -> None: @@ -451,7 +451,7 @@ def test_installs_plugin(self) -> None: ) -class CreateRepoJobTestCase(fixture.BaseTestCase): +class CreateRepoJobTestCase(TestCase): """Tests for the Jenkins.create_repo_job method""" def test_creates_given_repo(self) -> None: @@ -498,7 +498,7 @@ def test_when_base_url_is_not_root(self) -> None: ) -class CreateMachineJobTestCase(fixture.BaseTestCase): +class CreateMachineJobTestCase(TestCase): """Tests for the Jenkins.create_machine_job method""" def test_creates_given_machine(self) -> None: @@ -530,7 +530,7 @@ def test_creates_given_machine(self) -> None: ) -class ProjectPathTestCase(fixture.BaseTestCase): +class ProjectPathTestCase(TestCase): """Tests for the ProjectPath class""" def test_job_path_with_root(self) -> None: @@ -559,9 +559,7 @@ def test_str(self) -> None: self.assertEqual(str(project_path), "Gentoo/repos/marduk") -def mock_jenkins( - _options: fixture.FixtureOptions, _fixtures: fixture.Fixtures -) -> fixture.FixtureContext[Jenkins]: +def mock_jenkins(_options: Any, _fixtures: Fixtures) -> FixtureContext[Jenkins]: obj = Jenkins(JENKINS_CONFIG) with mock.patch.object( obj.session, "get", **{"return_value.json.return_value": JOB_PARAMS} @@ -569,12 +567,12 @@ def mock_jenkins( yield obj -@fixture.requires(mock_jenkins) -class ScheduleBuildTestCase(fixture.BaseTestCase): +@given(mock_jenkins) +class ScheduleBuildTestCase(TestCase): """Tests for the schedule_build function""" - def test(self) -> None: - jenkins = self.fixtures.mock_jenkins + def test(self, fixtures: Fixtures) -> None: + jenkins = fixtures.mock_jenkins with mock.patch.object(jenkins.session, "post") as mock_post: mock_response = mock_post.return_value @@ -599,19 +597,17 @@ def test(self) -> None: }, ) - def test_schedule_build_with_bogus_build_params(self) -> None: + def test_schedule_build_with_bogus_build_params(self, fixtures: Fixtures) -> None: with self.assertRaises(ValueError) as context: - self.fixtures.mock_jenkins.schedule_build( - "babette", BOGUS="idunno", FOO="bar" - ) + fixtures.mock_jenkins.schedule_build("babette", BOGUS="idunno", FOO="bar") self.assertEqual( context.exception.args, ("parameter(s) ['BOGUS', 'FOO'] are invalid for this build",), ) - def test_should_raise_on_http_error(self) -> None: - jenkins = self.fixtures.mock_jenkins + def test_should_raise_on_http_error(self, fixtures: Fixtures) -> None: + jenkins = fixtures.mock_jenkins class MyException(Exception): pass @@ -623,9 +619,9 @@ class MyException(Exception): with self.assertRaises(MyException): jenkins.schedule_build("babette") - def test_with_missing_location_header(self) -> None: + def test_with_missing_location_header(self, fixtures: Fixtures) -> None: # Sometimes the Jenkins response is missing the location header(?) - jenkins = self.fixtures.mock_jenkins + jenkins = fixtures.mock_jenkins with mock.patch.object(jenkins.session, "post") as mock_post: attrs = {"status_code": 301, "headers": {}} @@ -635,7 +631,7 @@ def test_with_missing_location_header(self) -> None: self.assertEqual(location, None) -class GetJobParametersTests(fixture.BaseTestCase): +class GetJobParametersTests(TestCase): # pylint: disable=no-member def test_gets_parameter_name_and_default_values(self) -> None: jenkins = MockJenkins(JENKINS_CONFIG) @@ -665,7 +661,7 @@ def test_returns_empty_if_no_paramdefs(self) -> None: self.assertEqual(response, {}) -class URLBuilderTestCase(fixture.BaseTestCase): +class URLBuilderTestCase(TestCase): """Tests for the URLBuilder""" config = JenkinsConfig(base_url=URL("https://jenkins.invalid")) diff --git a/tests/test_machines.py b/tests/test_machines.py index 76dcab6..8cca12a 100644 --- a/tests/test_machines.py +++ b/tests/test_machines.py @@ -1,20 +1,23 @@ """Tests for the machines module""" # pylint: disable=missing-docstring +from typing import Any + from gbp_testkit import TestCase from gbp_testkit.factories import BuildFactory -from unittest_fixtures import FixtureOptions, Fixtures, depends, requires +from unittest_fixtures import Fixtures, fixture, given from gentoo_build_publisher import publisher from gentoo_build_publisher.machines import MachineInfo from gentoo_build_publisher.types import Build -@requires("publisher") +# pylint: disable=unused-argument +@given("publisher") class MachineInfoTestCase(TestCase): """Tests for the MachineInfo thingy""" - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: # Given the "foo" builds, one of which is published first_build = BuildFactory(machine="foo") publisher.publish(first_build) @@ -34,7 +37,7 @@ def test(self) -> None: self.assertEqual(machine_info.latest_build, publisher.record(latest_build)) self.assertEqual(machine_info.published_build, first_build) - def test_empty_db(self) -> None: + def test_empty_db(self, fixtures: Fixtures) -> None: # When we get MachineInfo for foo machine_info = MachineInfo("foo") @@ -44,7 +47,7 @@ def test_empty_db(self) -> None: self.assertEqual(machine_info.latest_build, None) self.assertEqual(machine_info.published_build, None) - def test_builds_property(self) -> None: + def test_builds_property(self, fixtures: Fixtures) -> None: # Given the "foo" builds builds = BuildFactory.create_batch(3, machine="foo") for build in builds: @@ -59,7 +62,9 @@ def test_builds_property(self) -> None: # Then we get the list of builds in reverse chronological order self.assertEqual(result, [publisher.record(i) for i in reversed(builds)]) - def test_tags_property_shows_tags_across_machines_builds(self) -> None: + def test_tags_property_shows_tags_across_machines_builds( + self, fixtures: Fixtures + ) -> None: builds = BuildFactory.create_batch(3, machine="foo") for build in builds: publisher.pull(build) @@ -72,7 +77,7 @@ def test_tags_property_shows_tags_across_machines_builds(self) -> None: self.assertEqual(machine_info.tags, ["stable", "testing"]) -def builds_fixture(_options: FixtureOptions, _fixtures: Fixtures) -> list[Build]: +def builds_fixture(_options: Any, _fixtures: Fixtures) -> list[Build]: # So for this case let's say we have 4 builds. None have built timestamps. The # 3rd one is published (but has no built timestamp) and the first 2 are pulled # but not published: @@ -80,8 +85,8 @@ def builds_fixture(_options: FixtureOptions, _fixtures: Fixtures) -> list[Build] return builds -@depends("publisher", builds_fixture) -def machine_info_fixture(_options: FixtureOptions, fixtures: Fixtures) -> MachineInfo: +@fixture("publisher", builds_fixture) +def machine_info_fixture(_options: Any, fixtures: Fixtures) -> MachineInfo: machine = fixtures.builds[0].machine for build in fixtures.builds: @@ -96,7 +101,7 @@ def machine_info_fixture(_options: FixtureOptions, fixtures: Fixtures) -> Machin return MachineInfo(fixtures.builds[0].machine) -@requires(builds_fixture, "publisher", machine_info_fixture) +@given(builds_fixture, "publisher", machine_info_fixture) class MachineInfoLegacyBuiltTestCase(TestCase): """Test case for MachineInfo where built field is not always populated""" @@ -105,32 +110,34 @@ def pull_build_with_no_built_timestamp(build: Build) -> None: publisher.pull(build) publisher.repo.build_records.save(publisher.record(build), built=None) - def test_build_count(self) -> None: - self.assertEqual(self.fixtures.machine_info.build_count, 4) + def test_build_count(self, fixtures: Fixtures) -> None: + self.assertEqual(fixtures.machine_info.build_count, 4) - def test_builds(self) -> None: - builds = self.fixtures.machine_info.builds + def test_builds(self, fixtures: Fixtures) -> None: + builds = fixtures.machine_info.builds - expected = list(reversed([publisher.record(i) for i in self.fixtures.builds])) + expected = list(reversed([publisher.record(i) for i in fixtures.builds])) self.assertEqual(expected, builds) - def test_latest_build(self) -> None: - build4 = self.fixtures.builds[3] - latest_build = self.fixtures.machine_info.latest_build + def test_latest_build(self, fixtures: Fixtures) -> None: + build4 = fixtures.builds[3] + latest_build = fixtures.machine_info.latest_build self.assertEqual(publisher.record(build4), latest_build) - def test_latest_with_latest_having_built_timestamp(self) -> None: + def test_latest_with_latest_having_built_timestamp( + self, fixtures: Fixtures + ) -> None: build5 = BuildFactory() publisher.pull(build5) - latest_build = self.fixtures.machine_info.latest_build + latest_build = fixtures.machine_info.latest_build self.assertEqual(publisher.record(build5), latest_build) - def test_published_build(self) -> None: - build3 = self.fixtures.builds[2] - published_build = self.fixtures.machine_info.published_build + def test_published_build(self, fixtures: Fixtures) -> None: + build3 = fixtures.builds[2] + published_build = fixtures.machine_info.published_build self.assertEqual(build3, published_build) self.assertTrue(publisher.published(build3)) diff --git a/tests/test_publisher.py b/tests/test_publisher.py index 34dbff0..739071a 100644 --- a/tests/test_publisher.py +++ b/tests/test_publisher.py @@ -1,20 +1,14 @@ """Tests for the GBP publisher""" -# pylint: disable=missing-docstring +# pylint: disable=missing-docstring,unused-argument import datetime as dt -from unittest import mock +from typing import Any +from unittest import TestCase, mock from zoneinfo import ZoneInfo -from gbp_testkit import TestCase from gbp_testkit.factories import BuildFactory, BuildRecordFactory from gbp_testkit.helpers import BUILD_LOGS -from unittest_fixtures import ( - BaseTestCase, - FixtureContext, - FixtureOptions, - Fixtures, - requires, -) +from unittest_fixtures import FixtureContext, Fixtures, given from yarl import URL from gentoo_build_publisher import publisher as gbp @@ -26,37 +20,37 @@ from gentoo_build_publisher.utils.time import utctime -@requires("tmpdir") -class BuildPublisherFromSettingsTestCase(BaseTestCase): - def test_from_settings_returns_publisher_with_given_settings(self) -> None: +@given("tmpdir") +class BuildPublisherFromSettingsTestCase(TestCase): + def test_from_settings_returns_publisher_with_given_settings( + self, fixtures: Fixtures + ) -> None: settings = Settings( JENKINS_BASE_URL="https://testserver.invalid/", RECORDS_BACKEND="memory", - STORAGE_PATH=self.fixtures.tmpdir / "test_from_settings", + STORAGE_PATH=fixtures.tmpdir / "test_from_settings", ) pub = BuildPublisher.from_settings(settings) self.assertEqual( pub.jenkins.config.base_url, URL("https://testserver.invalid/") ) - self.assertEqual(pub.storage.root, self.fixtures.tmpdir / "test_from_settings") + self.assertEqual(pub.storage.root, fixtures.tmpdir / "test_from_settings") self.assertIsInstance(pub.repo.build_records, RecordDB) -@requires("build", "publisher") +@given("build", "publisher") class BuildPublisherTestCase(TestCase): # pylint: disable=too-many-public-methods - def test_publish(self) -> None: + def test_publish(self, fixtures: Fixtures) -> None: """.publish should publish the build artifact""" - fixtures = self.fixtures publisher = fixtures.publisher publisher.publish(fixtures.build) self.assertIs(publisher.storage.published(fixtures.build), True) - def test_pull_without_db(self) -> None: + def test_pull_without_db(self, fixtures: Fixtures) -> None: """pull creates db record and pulls from jenkins""" - fixtures = self.fixtures publisher = fixtures.publisher publisher.pull(fixtures.build) @@ -64,9 +58,8 @@ def test_pull_without_db(self) -> None: self.assertIs(publisher.storage.pulled(fixtures.build), True) self.assertIs(publisher.repo.build_records.exists(fixtures.build), True) - def test_pull_stores_build_logs(self) -> None: + def test_pull_stores_build_logs(self, fixtures: Fixtures) -> None: """Should store the logs of the build""" - fixtures = self.fixtures publisher = fixtures.publisher publisher.pull(fixtures.build) @@ -76,9 +69,10 @@ def test_pull_stores_build_logs(self) -> None: record = publisher.record(fixtures.build) self.assertEqual(record.logs, BUILD_LOGS) - def test_pull_updates_build_models_completed_field(self) -> None: + def test_pull_updates_build_models_completed_field( + self, fixtures: Fixtures + ) -> None: """Should update the completed field with the current timestamp""" - fixtures = self.fixtures publisher = fixtures.publisher now = utctime() @@ -89,8 +83,7 @@ def test_pull_updates_build_models_completed_field(self) -> None: record = publisher.record(fixtures.build) self.assertEqual(record.completed, now) - def test_pull_updates_build_models_built_field(self) -> None: - fixtures = self.fixtures + def test_pull_updates_build_models_built_field(self, fixtures: Fixtures) -> None: publisher = fixtures.publisher build = fixtures.build @@ -103,22 +96,22 @@ def test_pull_updates_build_models_built_field(self) -> None: ).replace(tzinfo=dt.UTC) self.assertEqual(record.built, jenkins_timestamp) - def test_pull_does_not_download_when_already_pulled(self) -> None: - fixtures = self.fixtures + def test_pull_does_not_download_when_already_pulled( + self, fixtures: Fixtures + ) -> None: build = fixtures.build - self.fixtures.publisher.pull(build) - assert self.fixtures.publisher.pulled(build) + fixtures.publisher.pull(build) + assert fixtures.publisher.pulled(build) - pulled = self.fixtures.publisher.pull(build) + pulled = fixtures.publisher.pull(build) self.assertFalse(pulled) - def test_pulled_when_storage_is_ok_but_db_is_not(self) -> None: + def test_pulled_when_storage_is_ok_but_db_is_not(self, fixtures: Fixtures) -> None: # On rare occasion (server crash) the build appears to be extracted but the # record.completed field is None. In this case Publisher.pulled(build) should # be False - fixtures = self.fixtures publisher = fixtures.publisher build = fixtures.build @@ -131,8 +124,7 @@ def test_pulled_when_storage_is_ok_but_db_is_not(self) -> None: self.assertFalse(publisher.pulled(build)) - def test_build_timestamps(self) -> None: - fixtures = self.fixtures + def test_build_timestamps(self, fixtures: Fixtures) -> None: publisher = fixtures.publisher datetime = dt.datetime localtimezone = "gentoo_build_publisher.utils.time.LOCAL_TIMEZONE" @@ -153,8 +145,7 @@ def test_build_timestamps(self) -> None: self.assertEqual(record.submitted, datetime(2024, 1, 19, 5, 5, 49, tzinfo=ct)) self.assertEqual(record.completed, datetime(2024, 1, 19, 5, 5, 49, tzinfo=ct)) - def test_pull_with_note(self) -> None: - fixtures = self.fixtures + def test_pull_with_note(self, fixtures: Fixtures) -> None: publisher = fixtures.publisher publisher.pull(fixtures.build, note="This is a test") @@ -163,8 +154,7 @@ def test_pull_with_note(self) -> None: build_record = publisher.record(fixtures.build) self.assertEqual(build_record.note, "This is a test") - def test_pull_with_tags(self) -> None: - fixtures = self.fixtures + def test_pull_with_tags(self, fixtures: Fixtures) -> None: publisher = fixtures.publisher build = fixtures.build tags = {"this", "is", "a", "test"} @@ -174,9 +164,8 @@ def test_pull_with_tags(self) -> None: self.assertIs(publisher.storage.pulled(build), True) self.assertEqual(set(publisher.tags(build)), tags) - def test_purge_deletes_old_build(self) -> None: + def test_purge_deletes_old_build(self, fixtures: Fixtures) -> None: """Should remove purgeable builds""" - fixtures = self.fixtures publisher = fixtures.publisher old_build = fixtures.build publisher.pull(old_build) @@ -200,10 +189,9 @@ def test_purge_deletes_old_build(self) -> None: path = publisher.storage.get_path(old_build, item) self.assertIs(path.exists(), False, path) - def test_purge_does_not_delete_old_tagged_builds(self) -> None: + def test_purge_does_not_delete_old_tagged_builds(self, fixtures: Fixtures) -> None: """Should remove purgeable builds""" - fixtures = self.fixtures publisher = fixtures.publisher repo = publisher.repo datetime = dt.datetime @@ -230,9 +218,8 @@ def test_purge_does_not_delete_old_tagged_builds(self) -> None: self.assertIs(repo.build_records.exists(kept_build), True) self.assertIs(repo.build_records.exists(tagged_build), True) - def test_purge_doesnt_delete_old_published_build(self) -> None: + def test_purge_doesnt_delete_old_published_build(self, fixtures: Fixtures) -> None: """Should not delete old build if published""" - fixtures = self.fixtures publisher = fixtures.publisher build = fixtures.build repo = publisher.repo @@ -250,9 +237,8 @@ def test_purge_doesnt_delete_old_published_build(self) -> None: self.assertIs(repo.build_records.exists(build), True) - def test_update_build_metadata(self) -> None: + def test_update_build_metadata(self, fixtures: Fixtures) -> None: # pylint: disable=protected-access - fixtures = self.fixtures publisher = fixtures.publisher record = publisher.record(fixtures.build) @@ -262,8 +248,9 @@ def test_update_build_metadata(self) -> None: self.assertEqual(record.logs, BUILD_LOGS) self.assertIsNot(record.completed, None) - def test_diff_binpkgs_should_be_empty_if_left_and_right_are_equal(self) -> None: - fixtures = self.fixtures + def test_diff_binpkgs_should_be_empty_if_left_and_right_are_equal( + self, fixtures: Fixtures + ) -> None: left = fixtures.build publisher = fixtures.publisher publisher.get_packages = mock.Mock(wraps=publisher.get_packages) @@ -276,8 +263,9 @@ def test_diff_binpkgs_should_be_empty_if_left_and_right_are_equal(self) -> None: self.assertEqual(diff, []) self.assertEqual(publisher.get_packages.call_count, 0) - def test_tags_returns_the_list_of_tags_except_empty_tag(self) -> None: - fixtures = self.fixtures + def test_tags_returns_the_list_of_tags_except_empty_tag( + self, fixtures: Fixtures + ) -> None: publisher = fixtures.publisher build = fixtures.build @@ -287,8 +275,7 @@ def test_tags_returns_the_list_of_tags_except_empty_tag(self) -> None: self.assertEqual(publisher.storage.get_tags(build), ["", "prod"]) self.assertEqual(publisher.tags(build), ["prod"]) - def test_tag_tags_the_build_at_the_storage_layer(self) -> None: - fixtures = self.fixtures + def test_tag_tags_the_build_at_the_storage_layer(self, fixtures: Fixtures) -> None: build = fixtures.build gbp.pull(build) @@ -297,8 +284,7 @@ def test_tag_tags_the_build_at_the_storage_layer(self) -> None: self.assertEqual(gbp.storage.get_tags(build), ["albert", "prod"]) - def test_untag_removes_tag_from_the_build(self) -> None: - fixtures = self.fixtures + def test_untag_removes_tag_from_the_build(self, fixtures: Fixtures) -> None: publisher = fixtures.publisher build = fixtures.build @@ -310,8 +296,7 @@ def test_untag_removes_tag_from_the_build(self) -> None: self.assertEqual(publisher.storage.get_tags(build), ["prod"]) - def test_untag_with_empty_unpublishes_the_build(self) -> None: - fixtures = self.fixtures + def test_untag_with_empty_unpublishes_the_build(self, fixtures: Fixtures) -> None: publisher = fixtures.publisher build = fixtures.build @@ -322,7 +307,7 @@ def test_untag_with_empty_unpublishes_the_build(self) -> None: self.assertFalse(publisher.published(build)) - def test_save(self) -> None: + def test_save(self, fixtures: Fixtures) -> None: r1 = BuildRecordFactory() r2 = gbp.save(r1, note="This is a test") @@ -331,13 +316,13 @@ def test_save(self) -> None: r3 = gbp.record(Build(r1.machine, r1.build_id)) self.assertEqual(r2, r3) - def test_machines(self) -> None: + def test_machines(self, fixtures: Fixtures) -> None: builds = [ *BuildFactory.create_batch(3, machine="foo"), *BuildFactory.create_batch(2, machine="bar"), *BuildFactory.create_batch(1, machine="baz"), ] - publisher = self.fixtures.publisher + publisher = fixtures.publisher for build in builds: publisher.pull(build) @@ -345,13 +330,13 @@ def test_machines(self) -> None: self.assertEqual(len(machines), 3) - def test_machines_with_filter(self) -> None: + def test_machines_with_filter(self, fixtures: Fixtures) -> None: builds = [ *BuildFactory.create_batch(3, machine="foo"), *BuildFactory.create_batch(2, machine="bar"), *BuildFactory.create_batch(1, machine="baz"), ] - publisher = self.fixtures.publisher + publisher = fixtures.publisher for build in builds: publisher.pull(build) machines = publisher.machines(names={"bar", "baz", "bogus"}) @@ -359,9 +344,7 @@ def test_machines_with_filter(self) -> None: self.assertEqual(len(machines), 2) -def prepull_events( - _options: FixtureOptions, _fixtures: Fixtures -) -> FixtureContext[list[Build]]: +def prepull_events(_options: Any, _fixtures: Fixtures) -> FixtureContext[list[Build]]: events: list[Build] = [] def prepull(build: Build) -> None: @@ -373,7 +356,7 @@ def prepull(build: Build) -> None: def postpull_events( - _options: FixtureOptions, _fixtures: Fixtures + _options: Any, _fixtures: Fixtures ) -> FixtureContext[list[tuple[Build, list[Package], GBPMetadata | None]]]: events: list[tuple[Build, list[Package], GBPMetadata | None]] = [] @@ -387,9 +370,7 @@ def postpull( yield events -def publish_events( - _options: FixtureOptions, _fixtures: Fixtures -) -> FixtureContext[list[Build]]: +def publish_events(_options: Any, _fixtures: Fixtures) -> FixtureContext[list[Build]]: events: list[Build] = [] def publish(build: Build) -> None: @@ -400,11 +381,11 @@ def publish(build: Build) -> None: yield events -@requires("publisher", prepull_events, postpull_events, publish_events) +@given("publisher", prepull_events, postpull_events, publish_events) class DispatcherTestCase(TestCase): maxDiff = None - def test_pull_single(self) -> None: + def test_pull_single(self, fixtures: Fixtures) -> None: new_build = BuildFactory() gbp.pull(new_build) @@ -414,11 +395,10 @@ def test_pull_single(self) -> None: packages, gbp.gbp_metadata(gbp.jenkins.get_metadata(new_build), packages), ) - self.assertEqual(self.fixtures.postpull_events, [expected]) - self.assertEqual(self.fixtures.prepull_events, [new_build]) + self.assertEqual(fixtures.postpull_events, [expected]) + self.assertEqual(fixtures.prepull_events, [new_build]) - def test_pull_multi(self) -> None: - fixtures = self.fixtures + def test_pull_multi(self, fixtures: Fixtures) -> None: build1 = BuildFactory() build2 = BuildFactory(machine="fileserver") gbp.pull(build1) @@ -442,8 +422,7 @@ def test_pull_multi(self) -> None: self.assertEqual(fixtures.prepull_events, [build1, build2]) self.assertEqual(fixtures.postpull_events, [event1, event2]) - def test_publish(self) -> None: - fixtures = self.fixtures + def test_publish(self, fixtures: Fixtures) -> None: new_build = BuildFactory() gbp.publish(new_build) @@ -451,7 +430,7 @@ def test_publish(self) -> None: self.assertEqual(fixtures.publish_events, [record]) -def builds_fixture(_options: FixtureOptions, _fixtures: Fixtures) -> list[Build]: +def builds_fixture(_options: Any, _fixtures: Fixtures) -> list[Build]: # So for this case let's say we have 4 builds. None have built timestamps. The # 3rd one is published (but has no built timestamp) and the first 2 are pulled # but not published: @@ -459,11 +438,11 @@ def builds_fixture(_options: FixtureOptions, _fixtures: Fixtures) -> list[Build] return builds -@requires("publisher") +@given("publisher") class ScheduleBuildTestCase(TestCase): """Tests for the schedule_build function""" - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: response = gbp.schedule_build("babette") self.assertEqual("https://jenkins.invalid/job/babette/build", response) diff --git a/tests/test_purge.py b/tests/test_purge.py index 61f161b..c3ef41b 100644 --- a/tests/test_purge.py +++ b/tests/test_purge.py @@ -5,10 +5,9 @@ import random import typing as t from dataclasses import dataclass +from unittest import TestCase -import unittest_fixtures as fixture -from unittest_fixtures import BaseTestCase as TestCase -from unittest_fixtures import FixtureOptions, Fixtures +from unittest_fixtures import Fixtures, fixture, given from gentoo_build_publisher.purge import Purger @@ -76,20 +75,21 @@ def str2dt(string: str) -> datetime.datetime: return datetime.datetime(year, month, day) -def items_fixture(_options: FixtureOptions, _fixtures: Fixtures) -> list[Item]: +def items_fixture(_options: t.Any, _fixtures: Fixtures) -> list[Item]: dates = [*DATES] random.shuffle(dates) return [Item(timestamp=str2dt(i)) for i in dates] -@fixture.depends(items_fixture) -def purger_fixture(_options: FixtureOptions, fixtures: Fixtures) -> Purger[Item]: +@fixture(items_fixture) +def purger_fixture(_options: t.Any, fixtures: Fixtures) -> Purger[Item]: return Purger(fixtures.items, key=lambda i: i.timestamp, start=START, end=END) -@fixture.requires(items_fixture, purger_fixture) +# pylint: disable=unused-argument +@given(items_fixture, purger_fixture) class PurgeTestCase(TestCase): def assertDates(self, items, expected) -> None: # pylint: disable=invalid-name @@ -99,14 +99,14 @@ def assertDates(self, items, expected) -> None: self.assertEqual(set(item_dates), set(expected)) - def test_last_day_of_month(self) -> None: + def test_last_day_of_month(self, fixtures: Fixtures) -> None: self.assertEqual( - self.fixtures.purger.last_day_of_month(END), + fixtures.purger.last_day_of_month(END), datetime.datetime(2021, 4, 30, 23, 59, 59), ) - def test_yesterday_plus(self) -> None: - items = self.fixtures.purger.yesterday_plus() + def test_yesterday_plus(self, fixtures: Fixtures) -> None: + items = fixtures.purger.yesterday_plus() expected = [ "2021-04-20", @@ -119,21 +119,21 @@ def test_yesterday_plus(self) -> None: ] self.assertDates(items, expected) - def test_one_per_day_last_week(self) -> None: - items = self.fixtures.purger.one_per_day_last_week() + def test_one_per_day_last_week(self, fixtures: Fixtures) -> None: + items = fixtures.purger.one_per_day_last_week() expected = ["2021-04-14", "2021-04-16", "2021-04-17", "2021-04-20"] self.assertDates(items, expected) - def test_one_per_week_last_month(self) -> None: - items = self.fixtures.purger.one_per_week_last_month() + def test_one_per_week_last_month(self, fixtures: Fixtures) -> None: + items = fixtures.purger.one_per_week_last_month() expected = ["2021-03-01", "2021-03-09", "2021-03-17", "2021-03-27"] self.assertDates(items, expected) - def test_one_per_month_last_year(self) -> None: - items = self.fixtures.purger.one_per_month_last_year() + def test_one_per_month_last_year(self, fixtures: Fixtures) -> None: + items = fixtures.purger.one_per_month_last_year() expected = [ "2020-07-29", @@ -146,8 +146,8 @@ def test_one_per_month_last_year(self) -> None: self.assertDates(items, expected) - def test_one_per_year(self) -> None: - items = self.fixtures.purger.one_per_year() + def test_one_per_year(self, fixtures: Fixtures) -> None: + items = fixtures.purger.one_per_year() expected = [ "2015-12-31", @@ -161,18 +161,18 @@ def test_one_per_year(self) -> None: self.assertDates(items, expected) - def test_past(self) -> None: - items = self.fixtures.purger.past() + def test_past(self, fixtures: Fixtures) -> None: + items = fixtures.purger.past() expected = ["2015-12-30", "2015-12-31"] self.assertDates(items, expected) - def test_filter_range(self) -> None: + def test_filter_range(self, fixtures: Fixtures) -> None: start = datetime.datetime(2017, 4, 21) end = datetime.datetime(2019, 12, 31) - filtered = self.fixtures.purger.filter_range(self.fixtures.items, start, end) + filtered = fixtures.purger.filter_range(fixtures.items, start, end) expected = { datetime.datetime(2017, 10, 10, 0, 0), @@ -182,8 +182,8 @@ def test_filter_range(self) -> None: self.assertEqual(set(i.timestamp for i in filtered), expected) - def test_purge(self) -> None: - to_purge = self.fixtures.purger.purge() + def test_purge(self, fixtures: Fixtures) -> None: + to_purge = fixtures.purger.purge() expected = [ "2016-01-01", diff --git a/tests/test_records.py b/tests/test_records.py index 90c8854..c8841f9 100644 --- a/tests/test_records.py +++ b/tests/test_records.py @@ -1,13 +1,13 @@ """Tests for the db module""" -# pylint: disable=missing-class-docstring,missing-function-docstring +# pylint: disable=missing-class-docstring,missing-function-docstring,unused-argument import datetime as dt from itertools import product from pathlib import Path from django.test import TestCase from gbp_testkit.factories import BuildRecordFactory -from unittest_fixtures import parametrized, requires +from unittest_fixtures import Fixtures, given, parametrized from gentoo_build_publisher.records import ( ApiKeyDB, @@ -27,7 +27,7 @@ BACKENDS = [["django"], ["memory"]] -@requires("tmpdir") +@given("tmpdir") class RecordDBTestCase(TestCase): def backend(self, backend_name: str) -> RecordDB: settings = Settings( @@ -38,7 +38,7 @@ def backend(self, backend_name: str) -> RecordDB: return build_records(settings) @parametrized(BACKENDS) - def test_save(self, backend: str) -> None: + def test_save(self, backend: str, fixtures: Fixtures) -> None: records = self.backend(backend) timestamp = dt.datetime(2022, 9, 4, 9, 22, 0, 0, dt.UTC) @@ -50,7 +50,9 @@ def test_save(self, backend: str) -> None: self.assertEqual(records.get(Build("lighthouse", "8924")).completed, timestamp) @parametrized(BACKENDS) - def test_save_with_given_fields_updates_fields(self, backend: str) -> None: + def test_save_with_given_fields_updates_fields( + self, backend: str, fixtures: Fixtures + ) -> None: records = self.backend(backend) timestamp = dt.datetime(2022, 9, 4, 9, 22, 0, 0, dt.UTC) @@ -64,7 +66,7 @@ def test_save_with_given_fields_updates_fields(self, backend: str) -> None: self.assertEqual(records.get(Build("lighthouse", "8924")).keep, True) @parametrized(BACKENDS) - def test_get(self, backend: str) -> None: + def test_get(self, backend: str, fixtures: Fixtures) -> None: records = self.backend(backend) build_record = records.save(BuildRecord("lighthouse", "8924")) @@ -78,7 +80,7 @@ def test_get(self, backend: str) -> None: self.assertEqual(exception.args, (build,)) @parametrized(BACKENDS) - def test_for_machine(self, backend: str) -> None: + def test_for_machine(self, backend: str, fixtures: Fixtures) -> None: records = self.backend(backend) builds: list[BuildRecord] = [ records.save(BuildRecord("lighthouse", "8923")), @@ -89,7 +91,7 @@ def test_for_machine(self, backend: str) -> None: self.assertListEqual([*records.for_machine("anchor")], []) @parametrized(BACKENDS) - def test_delete(self, backend: str) -> None: + def test_delete(self, backend: str, fixtures: Fixtures) -> None: build_record = BuildRecordFactory() records = self.backend(backend) records.save(build_record) @@ -100,7 +102,7 @@ def test_delete(self, backend: str) -> None: self.assertFalse(records.exists(build_record)) @parametrized(BACKENDS) - def test_exists(self, backend: str) -> None: + def test_exists(self, backend: str, fixtures: Fixtures) -> None: records = self.backend(backend) build_record = BuildRecord("lighthouse", "8924") records.save(build_record) @@ -110,7 +112,7 @@ def test_exists(self, backend: str) -> None: self.assertIs(records.exists(bogus_build), False) @parametrized(BACKENDS) - def test_list_machines(self, backend: str) -> None: + def test_list_machines(self, backend: str, fixtures: Fixtures) -> None: records = self.backend(backend) self.assertEqual(records.list_machines(), []) @@ -123,7 +125,7 @@ def test_list_machines(self, backend: str) -> None: self.assertEqual(machines, ["anchor", "lighthouse"]) @parametrized(BACKENDS) - def test_previous(self, backend: str) -> None: + def test_previous(self, backend: str, fixtures: Fixtures) -> None: records = self.backend(backend) build1 = BuildRecordFactory( built=dt.datetime.fromtimestamp(1662310204, dt.UTC), @@ -138,7 +140,7 @@ def test_previous(self, backend: str) -> None: self.assertIsNone(records.previous(BuildRecordFactory(machine="bogus"))) @parametrized(BACKENDS) - def test_next(self, backend: str) -> None: + def test_next(self, backend: str, fixtures: Fixtures) -> None: records = self.backend(backend) build1 = BuildRecordFactory(built=dt.datetime.fromtimestamp(1662310204, dt.UTC)) records.save(build1) @@ -153,7 +155,7 @@ def test_next(self, backend: str) -> None: self.assertIsNone(records.next(BuildRecordFactory(machine="bogus"))) @parametrized(BACKENDS) - def test_next_excludes_unbuilt(self, backend: str) -> None: + def test_next_excludes_unbuilt(self, backend: str, fixtures: Fixtures) -> None: records = self.backend(backend) build1 = BuildRecordFactory(built=dt.datetime.fromtimestamp(1662310204, dt.UTC)) records.save(build1) @@ -165,7 +167,9 @@ def test_next_excludes_unbuilt(self, backend: str) -> None: self.assertEqual(records.next(build1), None) @parametrized(BACKENDS) - def test_next_second_built_before_first(self, backend: str) -> None: + def test_next_second_built_before_first( + self, backend: str, fixtures: Fixtures + ) -> None: records = self.backend(backend) build1 = BuildRecordFactory(built=dt.datetime.fromtimestamp(1662310204, dt.UTC)) records.save(build1) @@ -179,7 +183,7 @@ def test_next_second_built_before_first(self, backend: str) -> None: self.assertEqual(records.next(build1), None) @parametrized(BACKENDS) - def test_latest_with_completed_true(self, backend: str) -> None: + def test_latest_with_completed_true(self, backend: str, fixtures: Fixtures) -> None: records = self.backend(backend) build1 = BuildRecordFactory( machine="lighthouse", built=dt.datetime.fromtimestamp(1662310204, dt.UTC) @@ -198,7 +202,9 @@ def test_latest_with_completed_true(self, backend: str) -> None: self.assertEqual(records.latest("lighthouse", completed=True), None) @parametrized(BACKENDS) - def test_latest_with_completed_false(self, backend: str) -> None: + def test_latest_with_completed_false( + self, backend: str, fixtures: Fixtures + ) -> None: records = self.backend(backend) build1 = BuildRecordFactory( machine="lighthouse", built=dt.datetime.fromtimestamp(1662310204, dt.UTC) @@ -217,7 +223,7 @@ def test_latest_with_completed_false(self, backend: str) -> None: self.assertEqual(records.latest("lighthouse", completed=False).id, build1.id) @parametrized(product(BACKENDS[0], ["logs", "note"])) - def test_search(self, backend: str, field: str) -> None: + def test_search(self, backend: str, field: str, fixtures: Fixtures) -> None: records = self.backend(backend) build1 = BuildRecordFactory( **{ @@ -248,7 +254,7 @@ def test_search(self, backend: str, field: str) -> None: self.assertEqual([build.id for build in builds], []) @parametrized(BACKENDS) - def test_search_unsearchable_field(self, backend: str) -> None: + def test_search_unsearchable_field(self, backend: str, fixtures: Fixtures) -> None: # Assume "machine" is an unsearchable field unsearchable = "machine" @@ -259,7 +265,7 @@ def test_search_unsearchable_field(self, backend: str) -> None: [*records.search("lighthouse", unsearchable, "foo")] @parametrized(BACKENDS) - def test_count(self, backend: str) -> None: + def test_count(self, backend: str, fixtures: Fixtures) -> None: records = self.backend(backend) today = dt.datetime(2022, 9, 4, 9, 22, 0, tzinfo=dt.UTC) diff --git a/tests/test_records_django_orm.py b/tests/test_records_django_orm.py index b88e977..0e2e011 100644 --- a/tests/test_records_django_orm.py +++ b/tests/test_records_django_orm.py @@ -4,9 +4,9 @@ import datetime as dt from dataclasses import replace -import unittest_fixtures as fixture from gbp_testkit import DjangoTestCase as TestCase from gbp_testkit.factories import BuildModelFactory, BuildRecordFactory +from unittest_fixtures import Fixtures, given, where from gentoo_build_publisher.models import BuildLog, BuildModel, BuildNote, KeptBuild from gentoo_build_publisher.records import BuildRecord, RecordNotFound @@ -14,100 +14,96 @@ # pylint: disable=too-many-public-methods -@fixture.requires("build_model", "records_db", "record") +@given("build_model", "records_db", "record") +@where( + records_db={"records_backend": "django"}, + build_model={ + "submitted": dt.datetime(2022, 2, 20, 15, 47, tzinfo=dt.UTC), + "completed": dt.datetime(2022, 2, 20, 15, 58, tzinfo=dt.UTC), + "built": dt.datetime(2022, 2, 20, 15, 58, tzinfo=dt.UTC), + }, +) class RecordDBTestCase(TestCase): - options = { - "records_backend": "django", - "build_model": { - "submitted": dt.datetime(2022, 2, 20, 15, 47, tzinfo=dt.UTC), - "completed": dt.datetime(2022, 2, 20, 15, 58, tzinfo=dt.UTC), - "built": dt.datetime(2022, 2, 20, 15, 58, tzinfo=dt.UTC), - }, - } - - def test_submitted_set(self) -> None: + def test_submitted_set(self, fixtures: Fixtures) -> None: record = replace( - self.fixtures.record, - submitted=dt.datetime(2022, 2, 20, 16, 47, tzinfo=dt.UTC), + fixtures.record, submitted=dt.datetime(2022, 2, 20, 16, 47, tzinfo=dt.UTC) ) - self.fixtures.records_db.save(record) + fixtures.records_db.save(record) - self.fixtures.build_model.refresh_from_db() + fixtures.build_model.refresh_from_db() self.assertEqual( - self.fixtures.build_model.submitted, + fixtures.build_model.submitted, dt.datetime(2022, 2, 20, 16, 47, tzinfo=dt.UTC), ) - def test_completed_get(self) -> None: + def test_completed_get(self, fixtures: Fixtures) -> None: self.assertEqual( - self.fixtures.record.submitted, - dt.datetime(2022, 2, 20, 15, 47, tzinfo=dt.UTC), + fixtures.record.submitted, dt.datetime(2022, 2, 20, 15, 47, tzinfo=dt.UTC) ) - def test_completed_set(self) -> None: + def test_completed_set(self, fixtures: Fixtures) -> None: record = replace( - self.fixtures.record, - completed=dt.datetime(2022, 2, 20, 16, 47, tzinfo=dt.UTC), + fixtures.record, completed=dt.datetime(2022, 2, 20, 16, 47, tzinfo=dt.UTC) ) - self.fixtures.records_db.save(record) + fixtures.records_db.save(record) - self.fixtures.build_model.refresh_from_db() + fixtures.build_model.refresh_from_db() self.assertEqual( - self.fixtures.build_model.completed, + fixtures.build_model.completed, dt.datetime(2022, 2, 20, 16, 47, tzinfo=dt.UTC), ) - def test_save_note(self) -> None: - record = replace(self.fixtures.record, note="This is a test") - self.fixtures.records_db.save(record) + def test_save_note(self, fixtures: Fixtures) -> None: + record = replace(fixtures.record, note="This is a test") + fixtures.records_db.save(record) - self.fixtures.build_model.refresh_from_db() + fixtures.build_model.refresh_from_db() - self.assertEqual(self.fixtures.build_model.buildnote.note, "This is a test") + self.assertEqual(fixtures.build_model.buildnote.note, "This is a test") - def test_delete_build_note(self) -> None: + def test_delete_build_note(self, fixtures: Fixtures) -> None: BuildNote.objects.create( - build_model=self.fixtures.build_model, note="This is a test" + build_model=fixtures.build_model, note="This is a test" ) - self.fixtures.records_db.save(self.fixtures.record, note=None) + fixtures.records_db.save(fixtures.record, note=None) with self.assertRaises(BuildNote.DoesNotExist): - BuildNote.objects.get(build_model=self.fixtures.build_model) + BuildNote.objects.get(build_model=fixtures.build_model) - def test_save_keep(self) -> None: - record = self.fixtures.record - self.fixtures.records_db.save(record, keep=True) + def test_save_keep(self, fixtures: Fixtures) -> None: + record = fixtures.record + fixtures.records_db.save(record, keep=True) - KeptBuild.objects.get(build_model=self.fixtures.build_model) + KeptBuild.objects.get(build_model=fixtures.build_model) - def test_delete_build_keep(self) -> None: - KeptBuild.objects.create(build_model=self.fixtures.build_model) + def test_delete_build_keep(self, fixtures: Fixtures) -> None: + KeptBuild.objects.create(build_model=fixtures.build_model) - self.fixtures.records_db.save(self.fixtures.record, keep=False) + fixtures.records_db.save(fixtures.record, keep=False) with self.assertRaises(KeptBuild.DoesNotExist): - KeptBuild.objects.get(build_model=self.fixtures.build_model) + KeptBuild.objects.get(build_model=fixtures.build_model) - def test_save_logs(self) -> None: - self.fixtures.records_db.save(self.fixtures.record, logs="New logs") + def test_save_logs(self, fixtures: Fixtures) -> None: + fixtures.records_db.save(fixtures.record, logs="New logs") - build_logs = BuildLog.objects.get(build_model=self.fixtures.build_model) + build_logs = BuildLog.objects.get(build_model=fixtures.build_model) self.assertEqual(build_logs.logs, "New logs") - def test_delete_build_logs(self) -> None: - self.fixtures.records_db.save(self.fixtures.record, logs=None) + def test_delete_build_logs(self, fixtures: Fixtures) -> None: + fixtures.records_db.save(fixtures.record, logs=None) with self.assertRaises(BuildLog.DoesNotExist): - BuildLog.objects.get(build_model=self.fixtures.build_model) + BuildLog.objects.get(build_model=fixtures.build_model) - def test_save_not_exists(self) -> None: + def test_save_not_exists(self, fixtures: Fixtures) -> None: record = BuildRecordFactory() - self.fixtures.records_db.save(record) + fixtures.records_db.save(record) self.assertTrue( BuildModel.objects.filter( @@ -115,77 +111,86 @@ def test_save_not_exists(self) -> None: ).exists() ) - def test_save_exists(self) -> None: - record = self.fixtures.records_db.get(self.fixtures.record) - self.fixtures.records_db.save(record) + def test_save_exists(self, fixtures: Fixtures) -> None: + record = fixtures.records_db.get(fixtures.record) + fixtures.records_db.save(record) build_model = BuildModel.objects.get( machine=record.machine, build_id=record.build_id ) - self.assertEqual(build_model, self.fixtures.build_model) + self.assertEqual(build_model, fixtures.build_model) - def test_get(self) -> None: - build = Build.from_id(str(self.fixtures.build_model)) - record = self.fixtures.records_db.get(build) + def test_get(self, fixtures: Fixtures) -> None: + build = Build.from_id(str(fixtures.build_model)) + record = fixtures.records_db.get(build) self.assertEqual(record.id, build.id) - self.assertEqual(record.submitted, self.fixtures.build_model.submitted) + self.assertEqual(record.submitted, fixtures.build_model.submitted) - def test_get_does_not_exist(self) -> None: + def test_get_does_not_exist(self, fixtures: Fixtures) -> None: with self.assertRaises(RecordNotFound): - self.fixtures.records_db.get(Build("bogus", "955")) + fixtures.records_db.get(Build("bogus", "955")) - def test_previous_should_return_none_when_there_are_none(self) -> None: - previous = self.fixtures.records_db.previous(self.fixtures.record) + def test_previous_should_return_none_when_there_are_none( + self, fixtures: Fixtures + ) -> None: + previous = fixtures.records_db.previous(fixtures.record) self.assertIs(previous, None) - def test_previous_when_not_completed_should_return_none(self) -> None: - previous_build = self.fixtures.record - self.fixtures.records_db.save(previous_build, completed=None) + def test_previous_when_not_completed_should_return_none( + self, fixtures: Fixtures + ) -> None: + previous_build = fixtures.record + fixtures.records_db.save(previous_build, completed=None) record = BuildModelFactory().record() self.assertEqual(previous_build.machine, record.machine) - self.assertIs(self.fixtures.records_db.previous(record), None) + self.assertIs(fixtures.records_db.previous(record), None) - def test_previous_when_not_completed_and_completed_arg_is_false(self) -> None: - previous_build = self.fixtures.records_db.save( - self.fixtures.record, completed=None - ) + def test_previous_when_not_completed_and_completed_arg_is_false( + self, fixtures: Fixtures + ) -> None: + previous_build = fixtures.records_db.save(fixtures.record, completed=None) record = BuildModelFactory().record() self.assertEqual(previous_build.machine, record.machine) self.assertEqual( - self.fixtures.records_db.previous(record, completed=False), previous_build + fixtures.records_db.previous(record, completed=False), previous_build ) - def test_previous_when_completed(self) -> None: - previous_build = self.fixtures.build_model + def test_previous_when_completed(self, fixtures: Fixtures) -> None: + previous_build = fixtures.build_model current_build = BuildModelFactory() self.assertEqual(previous_build.machine, current_build.machine) current_build_record = current_build.record() self.assertEqual( - self.fixtures.records_db.previous(current_build_record), - self.fixtures.record, + fixtures.records_db.previous(current_build_record), fixtures.record ) - def test_next_should_return_none_when_there_are_none(self) -> None: + def test_next_should_return_none_when_there_are_none( + self, fixtures: Fixtures + ) -> None: build = BuildRecordFactory.build(machine="bogus", build_id="1") - next_build = self.fixtures.records_db.next(build) + next_build = fixtures.records_db.next(build) self.assertIs(next_build, None) - def test_next_when_not_completed_should_return_none(self) -> None: + def test_next_when_not_completed_should_return_none( + self, fixtures: Fixtures + ) -> None: next_build = BuildModelFactory() - self.assertEqual(next_build.machine, self.fixtures.build_model.machine) - self.assertIs(self.fixtures.records_db.next(self.fixtures.record), None) + self.assertEqual(next_build.machine, fixtures.build_model.machine) + self.assertIs(fixtures.records_db.next(fixtures.record), None) - def test_next_when_not_completed_and_completed_arg_is_false(self) -> None: + def test_next_when_not_completed_and_completed_arg_is_false( + self, fixtures: Fixtures + ) -> None: # You really can't/shouldn't have a build that's built date is set but it isn't # completed as BuildPublisher._update_build_metadata updates both fields # simultaneously, but... @@ -193,64 +198,62 @@ def test_next_when_not_completed_and_completed_arg_is_false(self) -> None: built=dt.datetime(2022, 2, 21, 15, 58, tzinfo=dt.UTC) ) - self.assertEqual(next_build.machine, self.fixtures.build_model.machine) + self.assertEqual(next_build.machine, fixtures.build_model.machine) next_build_record = next_build.record() self.assertEqual( - self.fixtures.records_db.next(self.fixtures.record, completed=False), + fixtures.records_db.next(fixtures.record, completed=False), next_build_record, ) - def test_next_when_completed(self) -> None: + def test_next_when_completed(self, fixtures: Fixtures) -> None: next_build = BuildModelFactory( completed=dt.datetime(2022, 2, 21, 15, 58, tzinfo=dt.UTC), built=dt.datetime(2022, 2, 21, 15, 58, tzinfo=dt.UTC), ) - self.assertEqual(next_build.machine, self.fixtures.build_model.machine) + self.assertEqual(next_build.machine, fixtures.build_model.machine) next_build_record = next_build.record() - self.assertEqual( - self.fixtures.records_db.next(self.fixtures.record), next_build_record - ) + self.assertEqual(fixtures.records_db.next(fixtures.record), next_build_record) - def test_list_machines(self) -> None: + def test_list_machines(self, fixtures: Fixtures) -> None: BuildModelFactory.create(machine="lighthouse") BuildModelFactory.create(machine="babette") BuildModelFactory.create(machine="babette") - machines = self.fixtures.records_db.list_machines() + machines = fixtures.records_db.list_machines() self.assertEqual(machines, ["babette", "lighthouse"]) - def test_count_machine(self) -> None: + def test_count_machine(self, fixtures: Fixtures) -> None: BuildModelFactory.create(machine="lighthouse") BuildModelFactory.create(machine="babette") BuildModelFactory.create(machine="babette") - self.assertEqual(self.fixtures.records_db.count(), 4) - self.assertEqual(self.fixtures.records_db.count("lighthouse"), 1) - self.assertEqual(self.fixtures.records_db.count("bogus"), 0) + self.assertEqual(fixtures.records_db.count(), 4) + self.assertEqual(fixtures.records_db.count("lighthouse"), 1) + self.assertEqual(fixtures.records_db.count("bogus"), 0) - def test_for_machine_when_only_one_build(self) -> None: + def test_for_machine_when_only_one_build(self, fixtures: Fixtures) -> None: BuildModelFactory.create(machine="lighthouse") - records = [*self.fixtures.records_db.for_machine("lighthouse")] + records = [*fixtures.records_db.for_machine("lighthouse")] self.assertEqual(1, len(records)) record = records[0] self.assertIsInstance(record, BuildRecord) - def test_for_machine_when_only_many_builds(self) -> None: + def test_for_machine_when_only_many_builds(self, fixtures: Fixtures) -> None: BuildModelFactory.create_batch(3, machine="lighthouse") BuildModelFactory.create_batch(2, machine="babette") - records = [*self.fixtures.records_db.for_machine("lighthouse")] + records = [*fixtures.records_db.for_machine("lighthouse")] self.assertEqual(3, len(records)) self.assertTrue(all(i.machine == "lighthouse" for i in records)) - def test_for_machine_when_no_builds(self) -> None: - records = [*self.fixtures.records_db.for_machine("bogus")] + def test_for_machine_when_no_builds(self, fixtures: Fixtures) -> None: + records = [*fixtures.records_db.for_machine("bogus")] self.assertEqual([], records) diff --git a/tests/test_storage.py b/tests/test_storage.py index 9f924f1..19bac96 100644 --- a/tests/test_storage.py +++ b/tests/test_storage.py @@ -6,11 +6,12 @@ import tarfile from dataclasses import replace from pathlib import Path +from typing import Any -import unittest_fixtures as fixture from gbp_testkit import TestCase from gbp_testkit.factories import PACKAGE_INDEX, BuildFactory from gbp_testkit.helpers import MockJenkins +from unittest_fixtures import Fixtures, fixture, given from gentoo_build_publisher import publisher, utils from gentoo_build_publisher.jenkins import Jenkins @@ -30,103 +31,114 @@ from . import data -FixtureOptions = fixture.FixtureOptions -Fixtures = fixture.Fixtures - TEST_SETTINGS = Settings( STORAGE_PATH=Path("/dev/null"), JENKINS_BASE_URL="https://jenkins.invalid/" ) -@fixture.requires("environ", "tmpdir") +# pylint: disable=unused-argument +@given("environ", "tmpdir") class StorageFromSettings(TestCase): options = {"environ": {}, "environ_clear": False} - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: """Should instantiate Storage from settings""" # Given the settings - settings = replace(TEST_SETTINGS, STORAGE_PATH=self.fixtures.tmpdir) + settings = replace(TEST_SETTINGS, STORAGE_PATH=fixtures.tmpdir) # When we instantiate Storage.from_settings storage = Storage.from_settings(settings) # Then we get a Storage instance with attributes from settings self.assertIsInstance(storage, Storage) - self.assertEqual(storage.root, self.fixtures.tmpdir) + self.assertEqual(storage.root, fixtures.tmpdir) -@fixture.depends("tmpdir") -def storage_fixture(_options: FixtureOptions, fixtures: Fixtures) -> Storage: +@fixture("tmpdir") +def storage_fixture(_options: Any, fixtures: Fixtures) -> Storage: root = fixtures.tmpdir / "root" return Storage(root) -@fixture.depends("tmpdir") -def jenkins_fixture(_options: FixtureOptions, fixtures: Fixtures) -> Jenkins: +@fixture("tmpdir") +def jenkins_fixture(_options: Any, fixtures: Fixtures) -> Jenkins: root = fixtures.tmpdir / "root" settings = replace(TEST_SETTINGS, STORAGE_PATH=root) return MockJenkins.from_settings(settings) -@fixture.requires("build", storage_fixture, jenkins_fixture) +@given("build", storage_fixture, jenkins_fixture) class StorageDownloadArtifactTestCase(TestCase): """Tests for Storage.download_artifact""" - def has_content(self, build: Build, content: Content) -> bool: - storage: Storage = self.fixtures.storage + def has_content(self, build: Build, content: Content, storage: Storage) -> bool: return storage.get_path(build, content).is_dir() - def download_and_extract(self, build: Build) -> None: - self.fixtures.storage.extract_artifact( - build, self.fixtures.jenkins.download_artifact(build) - ) + def download_and_extract( + self, build: Build, storage: Storage, jenkins: Jenkins + ) -> None: + storage.extract_artifact(build, jenkins.download_artifact(build)) - def test_extract_artifact_moves_repos_and_binpkgs(self) -> None: + def test_extract_artifact_moves_repos_and_binpkgs(self, fixtures: Fixtures) -> None: """Should extract artifacts and move to repos/ and binpkgs/""" - self.download_and_extract(self.fixtures.build) + self.download_and_extract(fixtures.build, fixtures.storage, fixtures.jenkins) - self.assertTrue(self.has_content(self.fixtures.build, Content.REPOS)) - self.assertTrue(self.has_content(self.fixtures.build, Content.BINPKGS)) + self.assertTrue( + self.has_content(fixtures.build, Content.REPOS, fixtures.storage) + ) + self.assertTrue( + self.has_content(fixtures.build, Content.BINPKGS, fixtures.storage) + ) - def test_extract_artifact_creates_etc_portage_dir(self) -> None: + def test_extract_artifact_creates_etc_portage_dir(self, fixtures: Fixtures) -> None: """Should extract artifacts and move to etc-portage/""" - self.download_and_extract(self.fixtures.build) + self.download_and_extract(fixtures.build, fixtures.storage, fixtures.jenkins) - self.assertTrue(self.has_content(self.fixtures.build, Content.ETC_PORTAGE)) + self.assertTrue( + self.has_content(fixtures.build, Content.ETC_PORTAGE, fixtures.storage) + ) - def test_extract_artifact_creates_var_lib_portage_dir(self) -> None: + def test_extract_artifact_creates_var_lib_portage_dir( + self, fixtures: Fixtures + ) -> None: """Should extract artifacts and move to var-lib-portage/""" - self.download_and_extract(self.fixtures.build) + self.download_and_extract(fixtures.build, fixtures.storage, fixtures.jenkins) - self.assertTrue(self.has_content(self.fixtures.build, Content.VAR_LIB_PORTAGE)) + self.assertTrue( + self.has_content(fixtures.build, Content.VAR_LIB_PORTAGE, fixtures.storage) + ) - def test_extract_artifact_should_remove_dst_if_it_already_exists(self) -> None: + def test_extract_artifact_should_remove_dst_if_it_already_exists( + self, fixtures: Fixtures + ) -> None: # When when one of the target paths already exist - path = self.fixtures.storage.get_path(self.fixtures.build, Content.BINPKGS) + path = fixtures.storage.get_path(fixtures.build, Content.BINPKGS) path.mkdir(parents=True) orphan = path / "this should not be here" orphan.touch() # And we extract the build - self.download_and_extract(self.fixtures.build) + self.download_and_extract(fixtures.build, fixtures.storage, fixtures.jenkins) # Then the orphaned path is removed self.assertIs(path.exists(), True) self.assertIs(orphan.exists(), False, orphan) -@fixture.requires("tmpdir") +@given("tmpdir") class StoragePublishTestCase(TestCase): """Tests for Storage.publish""" - def test_publish_raises_exception_repos_dir_does_not_exist(self) -> None: + def test_publish_raises_exception_repos_dir_does_not_exist( + self, fixtures: Fixtures + ) -> None: """Should raise an exception if the build has not been pulled""" # Given the build build = Build("babette", "193") # Given the storage - storage = Storage(self.fixtures.tmpdir) + storage = Storage(fixtures.tmpdir) # Then an exception is raised with self.assertRaises(FileNotFoundError): @@ -134,53 +146,53 @@ def test_publish_raises_exception_repos_dir_does_not_exist(self) -> None: storage.publish(build) -@fixture.requires("environ", "storage", "build", "settings", "jenkins") +@given("environ", "storage", "build", "settings", "jenkins") class StoragePublishedTestCase(TestCase): """Tests for Storage.published""" - def download_and_extract(self, build: Build) -> None: - self.fixtures.storage.extract_artifact( - build, self.fixtures.jenkins.download_artifact(build) - ) + def download_and_extract( + self, build: Build, storage: Storage, jenkins: Jenkins + ) -> None: + storage.extract_artifact(build, jenkins.download_artifact(build)) - def test_published_true(self) -> None: + def test_published_true(self, fixtures: Fixtures) -> None: """.published should return True when published""" - self.download_and_extract(self.fixtures.build) - self.fixtures.storage.publish(self.fixtures.build) + self.download_and_extract(fixtures.build, fixtures.storage, fixtures.jenkins) + fixtures.storage.publish(fixtures.build) - published = self.fixtures.storage.published(self.fixtures.build) + published = fixtures.storage.published(fixtures.build) self.assertTrue(published) - def test_published_false(self) -> None: + def test_published_false(self, fixtures: Fixtures) -> None: """.published should return False when not published""" - published = self.fixtures.storage.published(self.fixtures.build) + published = fixtures.storage.published(fixtures.build) self.assertFalse(published) - def test_other_published(self) -> None: - self.download_and_extract(self.fixtures.build) - self.fixtures.storage.publish(self.fixtures.build) + def test_other_published(self, fixtures: Fixtures) -> None: + self.download_and_extract(fixtures.build, fixtures.storage, fixtures.jenkins) + fixtures.storage.publish(fixtures.build) # Given the second build published build2 = Build("babette", "194") - self.download_and_extract(build2) - self.fixtures.storage.publish(build2) + self.download_and_extract(build2, fixtures.storage, fixtures.jenkins) + fixtures.storage.publish(build2) # Then published returns True on the second build - self.assertTrue(self.fixtures.storage.published(build2)) + self.assertTrue(fixtures.storage.published(build2)) # And False on the first build - self.assertFalse(self.fixtures.storage.published(self.fixtures.build)) + self.assertFalse(fixtures.storage.published(fixtures.build)) -@fixture.requires("tmpdir") +@given("tmpdir") class StorageDeleteTestCase(TestCase): """Tests for Storage.delete""" - def test_deletes_expected_directories(self) -> None: + def test_deletes_expected_directories(self, fixtures: Fixtures) -> None: build = Build("babette", "19") - root = self.fixtures.tmpdir / "root" + root = fixtures.tmpdir / "root" storage = Storage(root) settings = replace(TEST_SETTINGS, STORAGE_PATH=root) jenkins = MockJenkins.from_settings(settings) @@ -199,68 +211,66 @@ def test_deletes_expected_directories(self) -> None: self.assertIs(os.path.exists(directory), False) -@fixture.requires("build", "storage", jenkins_fixture) +@given("build", "storage", jenkins_fixture) class StorageExtractArtifactTestCase(TestCase): """Tests for Storage.extract_artifact""" - def test_does_not_extract_already_pulled_build(self) -> None: - self.fixtures.storage.extract_artifact( - self.fixtures.build, - self.fixtures.jenkins.download_artifact(self.fixtures.build), + def test_does_not_extract_already_pulled_build(self, fixtures: Fixtures) -> None: + fixtures.storage.extract_artifact( + fixtures.build, fixtures.jenkins.download_artifact(fixtures.build) ) - assert self.fixtures.storage.pulled(self.fixtures.build) + assert fixtures.storage.pulled(fixtures.build) # extract won't be able to extract this byte_stream_mock = iter([b""]) try: - self.fixtures.storage.extract_artifact( - self.fixtures.build, byte_stream_mock - ) + fixtures.storage.extract_artifact(fixtures.build, byte_stream_mock) except tarfile.ReadError: self.fail("extract_artifact() should not have attempted to extract") - def test_extracts_bytesteam_and_content(self) -> None: - self.fixtures.storage.extract_artifact( - self.fixtures.build, - self.fixtures.jenkins.download_artifact(self.fixtures.build), + def test_extracts_bytesteam_and_content(self, fixtures: Fixtures) -> None: + fixtures.storage.extract_artifact( + fixtures.build, fixtures.jenkins.download_artifact(fixtures.build) ) - self.assertIs(self.fixtures.storage.pulled(self.fixtures.build), True) + self.assertIs(fixtures.storage.pulled(fixtures.build), True) - def test_uses_hard_link_if_previous_build_exists(self) -> None: + def test_uses_hard_link_if_previous_build_exists(self, fixtures: Fixtures) -> None: previous_build = Build("babette", "19") - timestamp = self.fixtures.jenkins.artifact_builder.timer - self.fixtures.storage.extract_artifact( - previous_build, self.fixtures.jenkins.download_artifact(previous_build) + timestamp = fixtures.jenkins.artifact_builder.timer + fixtures.storage.extract_artifact( + previous_build, fixtures.jenkins.download_artifact(previous_build) ) current_build = Build("babette", "20") # Reverse time so we have duplicate mtimes - self.fixtures.jenkins.artifact_builder.timer = timestamp - self.fixtures.storage.extract_artifact( + fixtures.jenkins.artifact_builder.timer = timestamp + fixtures.storage.extract_artifact( current_build, - self.fixtures.jenkins.download_artifact(current_build), + fixtures.jenkins.download_artifact(current_build), previous=previous_build, ) for item in Content: - dst_path = self.fixtures.storage.get_path(current_build, item) + dst_path = fixtures.storage.get_path(current_build, item) self.assertIs(dst_path.exists(), True) package_index = ( - self.fixtures.storage.get_path(current_build, Content.BINPKGS) / "Packages" + fixtures.storage.get_path(current_build, Content.BINPKGS) / "Packages" ) self.assertEqual(package_index.stat().st_nlink, 2) -@fixture.requires("publisher", "build") +@given("publisher", "build") class StorageGetPackagesTestCase(TestCase): """tests for the Storage.get_packages() method""" - def test_should_return_list_of_packages_from_index(self) -> None: - publisher.pull(self.fixtures.build) - packages = publisher.storage.get_packages(self.fixtures.build) + def test_should_return_list_of_packages_from_index( + self, fixtures: Fixtures + ) -> None: + publisher.pull(fixtures.build) + packages = publisher.storage.get_packages(fixtures.build) self.assertEqual(len(packages), len(PACKAGE_INDEX)) package = packages[3] @@ -271,25 +281,26 @@ def test_should_return_list_of_packages_from_index(self) -> None: self.assertEqual(package.size, 484) self.assertEqual(package.build_time, 0) - def test_should_raise_lookuperror_when_index_file_missing(self) -> None: - publisher.pull(self.fixtures.build) + def test_should_raise_lookuperror_when_index_file_missing( + self, fixtures: Fixtures + ) -> None: + publisher.pull(fixtures.build) index_file = ( - publisher.storage.get_path(self.fixtures.build, Content.BINPKGS) - / "Packages" + publisher.storage.get_path(fixtures.build, Content.BINPKGS) / "Packages" ) index_file.unlink() with self.assertRaises(LookupError): - publisher.storage.get_packages(self.fixtures.build) + publisher.storage.get_packages(fixtures.build) -@fixture.depends("publisher") -def timestamp_fixture(_options: FixtureOptions, fixtures: Fixtures) -> int: +@fixture("publisher") +def timestamp_fixture(_options: Any, fixtures: Fixtures) -> int: return int(fixtures.publisher.jenkins.artifact_builder.timestamp / 1000) -@fixture.depends("publisher") -def artifacts(_options: FixtureOptions, fixtures: Fixtures) -> list[Package]: +@fixture("publisher") +def artifacts(_options: Any, fixtures: Fixtures) -> list[Package]: artifact_builder = fixtures.publisher.jenkins.artifact_builder a1 = artifact_builder.build(fixtures.build, "dev-libs/cyrus-sasl-2.1.28-r1") a2 = artifact_builder.build(fixtures.build, "net-libs/nghttp2-1.47.0") @@ -299,12 +310,14 @@ def artifacts(_options: FixtureOptions, fixtures: Fixtures) -> list[Package]: return [a1, a2, a3] -@fixture.requires("build", "publisher", timestamp_fixture, artifacts) +@given("build", "publisher", timestamp_fixture, artifacts) class StorageGetMetadataTestCase(TestCase): """tests for the Storage.get_metadata() method""" - def test_should_return_gbpmetadata_when_gbp_json_exists(self) -> None: - metadata = publisher.storage.get_metadata(self.fixtures.build) + def test_should_return_gbpmetadata_when_gbp_json_exists( + self, fixtures: Fixtures + ) -> None: + metadata = publisher.storage.get_metadata(fixtures.build) expected = GBPMetadata( build_duration=124, @@ -318,7 +331,7 @@ def test_should_return_gbpmetadata_when_gbp_json_exists(self) -> None: path="dev-libs/cyrus-sasl/cyrus-sasl-2.1.28-r1-1.gpkg.tar", build_id=1, size=841, - build_time=self.fixtures.timestamp + 10, + build_time=fixtures.timestamp + 10, ), Package( cpv="net-libs/nghttp2-1.47.0", @@ -326,7 +339,7 @@ def test_should_return_gbpmetadata_when_gbp_json_exists(self) -> None: path="net-libs/nghttp2/nghttp2-1.47.0-1.gpkg.tar", build_id=1, size=529, - build_time=self.fixtures.timestamp + 20, + build_time=fixtures.timestamp + 20, ), Package( cpv="sys-libs/glibc-2.34-r9", @@ -334,31 +347,30 @@ def test_should_return_gbpmetadata_when_gbp_json_exists(self) -> None: path="sys-libs/glibc/glibc-2.34-r9-1.gpkg.tar", build_id=1, size=484, - build_time=self.fixtures.timestamp + 30, + build_time=fixtures.timestamp + 30, ), ], ), ) self.assertEqual(metadata, expected) - def test_should_raise_lookuperror_when_file_does_not_exist(self) -> None: - path = ( - publisher.storage.get_path(self.fixtures.build, Content.BINPKGS) - / "gbp.json" - ) + def test_should_raise_lookuperror_when_file_does_not_exist( + self, fixtures: Fixtures + ) -> None: + path = publisher.storage.get_path(fixtures.build, Content.BINPKGS) / "gbp.json" path.unlink() with self.assertRaises(LookupError) as context: - publisher.storage.get_metadata(self.fixtures.build) + publisher.storage.get_metadata(fixtures.build) exception = context.exception self.assertEqual( - exception.args, (f"gbp.json does not exist for {self.fixtures.build}",) + exception.args, (f"gbp.json does not exist for {fixtures.build}",) ) -@fixture.depends("publisher", "build") -def path_fixture(_options: FixtureOptions, fixtures: Fixtures) -> Path: +@fixture("publisher", "build") +def path_fixture(_options: Any, fixtures: Fixtures) -> Path: publisher.pull(fixtures.build) metadata = publisher.storage.get_path(fixtures.build, Content.BINPKGS) / "gbp.json" @@ -368,11 +380,11 @@ def path_fixture(_options: FixtureOptions, fixtures: Fixtures) -> Path: return metadata -@fixture.requires("publisher", "build", path_fixture) +@given("publisher", "build", path_fixture) class StorageSetMetadataTestCase(TestCase): """tests for the Storage.set_metadata() method""" - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: package_metadata = PackageMetadata( total=666, size=666, @@ -388,9 +400,9 @@ def test(self) -> None: ], ) gbp_metadata = GBPMetadata(build_duration=666, packages=package_metadata) - publisher.storage.set_metadata(self.fixtures.build, gbp_metadata) + publisher.storage.set_metadata(fixtures.build, gbp_metadata) - with self.fixtures.path.open("r") as json_file: + with fixtures.path.open("r") as json_file: result = json.load(json_file) expected = { @@ -415,9 +427,9 @@ def test(self) -> None: self.assertEqual(result, expected) -@fixture.requires("publisher") +@given("publisher") class StorageReposTestCase(TestCase): - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) @@ -425,7 +437,7 @@ def test(self) -> None: self.assertEqual(repos, {"gentoo", "marduk"}) - def test_raise_exception_when_not_pulled(self) -> None: + def test_raise_exception_when_not_pulled(self, fixtures: Fixtures) -> None: build = BuildFactory() with self.assertRaises(FileNotFoundError) as context: @@ -434,9 +446,9 @@ def test_raise_exception_when_not_pulled(self) -> None: self.assertEqual(context.exception.args, ("The build has not been pulled",)) -@fixture.requires("publisher") +@given("publisher") class StorageTaggingTestCase(TestCase): - def test_can_create_tagged_directory_symlinks(self) -> None: + def test_can_create_tagged_directory_symlinks(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) @@ -449,7 +461,7 @@ def test_can_create_tagged_directory_symlinks(self) -> None: self.assertTrue(source_path.is_symlink()) self.assertEqual(source_path.resolve(), target_path) - def test_can_retag(self) -> None: + def test_can_retag(self, fixtures: Fixtures) -> None: build1 = BuildFactory() publisher.pull(build1) publisher.storage.tag(build1, "prod") @@ -465,7 +477,7 @@ def test_can_retag(self) -> None: self.assertTrue(source_path.is_symlink()) self.assertEqual(source_path.resolve(), target_path) - def test_can_untag(self) -> None: + def test_can_untag(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) publisher.storage.tag(build, "prod") @@ -479,13 +491,13 @@ def test_can_untag(self) -> None: self.assertFalse(source_path.exists()) self.assertTrue(target_path.exists()) - def test_can_untag_if_no_such_tag_exists(self) -> None: + def test_can_untag_if_no_such_tag_exists(self, fixtures: Fixtures) -> None: """Removing a non-existent tag should fail silently""" build = BuildFactory() publisher.pull(build) publisher.storage.untag(build, "prod") - def test_non_published_builds_have_no_tags(self) -> None: + def test_non_published_builds_have_no_tags(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) @@ -493,7 +505,7 @@ def test_non_published_builds_have_no_tags(self) -> None: self.assertEqual(tags, []) - def test_builds_can_have_multiple_tags(self) -> None: + def test_builds_can_have_multiple_tags(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) publisher.storage.tag(build, "prod") @@ -508,7 +520,7 @@ def test_builds_can_have_multiple_tags(self) -> None: self.assertEqual(tags, ["", "albert", "prod"]) - def test_published_builds_have_the_empty_tag(self) -> None: + def test_published_builds_have_the_empty_tag(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.publish(build) @@ -516,14 +528,16 @@ def test_published_builds_have_the_empty_tag(self) -> None: self.assertEqual(tags, [""]) - def test_unpulled_builds_have_no_tags(self) -> None: + def test_unpulled_builds_have_no_tags(self, fixtures: Fixtures) -> None: build = BuildFactory() tags = publisher.storage.get_tags(build) self.assertEqual(tags, []) - def test_partially_tagged_directories_are_not_tagged(self) -> None: + def test_partially_tagged_directories_are_not_tagged( + self, fixtures: Fixtures + ) -> None: build = BuildFactory() publisher.pull(build) publisher.storage.tag(build, "prod") @@ -537,7 +551,7 @@ def test_partially_tagged_directories_are_not_tagged(self) -> None: self.assertEqual(tags, ["albert"]) - def test_get_path(self) -> None: + def test_get_path(self, fixtures: Fixtures) -> None: build = BuildFactory() storage = publisher.storage @@ -546,7 +560,7 @@ def test_get_path(self) -> None: expected = Path(storage.root, "binpkgs", str(build)) self.assertEqual(expected, path) - def test_get_path_with_tag(self) -> None: + def test_get_path_with_tag(self, fixtures: Fixtures) -> None: build = BuildFactory() storage = publisher.storage @@ -555,7 +569,7 @@ def test_get_path_with_tag(self) -> None: expected = Path(storage.root, "binpkgs", f"{build.machine}@prod") self.assertEqual(expected, path) - def test_get_path_with_published_tag(self) -> None: + def test_get_path_with_published_tag(self, fixtures: Fixtures) -> None: build = BuildFactory() storage = publisher.storage @@ -565,11 +579,13 @@ def test_get_path_with_published_tag(self) -> None: self.assertEqual(expected, path) -@fixture.requires("publisher") +@given("publisher") class StorageResolveTagTestCase(TestCase): """Tests for the Storage.resolve_tag method""" - def test_resolve_tag_returns_the_build_that_it_belongs_to(self) -> None: + def test_resolve_tag_returns_the_build_that_it_belongs_to( + self, fixtures: Fixtures + ) -> None: build = BuildFactory() publisher.pull(build) publisher.storage.tag(build, "prod") @@ -579,13 +595,17 @@ def test_resolve_tag_returns_the_build_that_it_belongs_to(self) -> None: self.assertEqual(target, build) - def test_resolve_tag_raises_exception_when_given_invalid_tag(self) -> None: + def test_resolve_tag_raises_exception_when_given_invalid_tag( + self, fixtures: Fixtures + ) -> None: with self.assertRaises(ValueError) as context: publisher.storage.resolve_tag("notatag") self.assertEqual(context.exception.args[0], "Invalid tag: notatag") - def test_resolve_tag_raises_exception_when_build_doesnt_exist(self) -> None: + def test_resolve_tag_raises_exception_when_build_doesnt_exist( + self, fixtures: Fixtures + ) -> None: build = BuildFactory(machine="lighthouse") publisher.pull(build) publisher.storage.tag(build, "prod") @@ -599,7 +619,9 @@ def test_resolve_tag_raises_exception_when_build_doesnt_exist(self) -> None: "Tag is broken or does not exist: lighthouse@prod", ) - def test_resolve_tag_resolves_to_more_than_one_build(self) -> None: + def test_resolve_tag_resolves_to_more_than_one_build( + self, fixtures: Fixtures + ) -> None: build1 = BuildFactory() publisher.pull(build1) build2 = BuildFactory() @@ -612,7 +634,9 @@ def test_resolve_tag_resolves_to_more_than_one_build(self) -> None: with self.assertRaises(FileNotFoundError): publisher.storage.resolve_tag(f"{build1.machine}@prod") - def test_resolve_tag_when_symlink_points_to_nonbuild(self) -> None: + def test_resolve_tag_when_symlink_points_to_nonbuild( + self, fixtures: Fixtures + ) -> None: build = BuildFactory() publisher.pull(build) publisher.storage.tag(build, "prod") @@ -641,11 +665,11 @@ def test_when_line_missing(self) -> None: self.assertEqual(context.exception.args[0], "Package lines missing CPV value") -@fixture.requires("publisher") +@given("publisher") class MakePackagesTestCase(TestCase): """Tests for the make_packages method""" - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: build = BuildFactory() publisher.pull(build) index_file = publisher.storage.get_path(build, Content.BINPKGS) / "Packages" diff --git a/tests/test_views.py b/tests/test_views.py index ed83c67..0c5ba4b 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -3,28 +3,28 @@ # pylint: disable=missing-class-docstring,missing-function-docstring,too-many-ancestors import datetime as dt from functools import partial +from typing import Any -import unittest_fixtures as fixture from django import urls from django.http import HttpResponse from gbp_testkit import DjangoTestCase as BaseTestCase +from unittest_fixtures import Fixtures, fixture, given, where from gentoo_build_publisher import publisher from gentoo_build_publisher.types import Build now = partial(dt.datetime.now, tz=dt.UTC) -FixtureOptions = fixture.FixtureOptions -Fixtures = fixture.Fixtures -@fixture.depends("client") -def lighthouse(_options: FixtureOptions, fixtures: Fixtures) -> HttpResponse: +@fixture("client") +def lighthouse(_options: Any, fixtures: Fixtures) -> HttpResponse: response: HttpResponse = fixtures.client.get("/machines/lighthouse/") return response -@fixture.depends("publisher", "builds") -def artifacts(_options: FixtureOptions, fixtures: Fixtures) -> dict[str, Build]: +# pylint: disable=unused-argument +@fixture("publisher", "builds") +def artifacts(_options: Any, fixtures: Fixtures) -> dict[str, Build]: artifact_builder = fixtures.publisher.jenkins.artifact_builder published = first_build(fixtures.builds, "lighthouse") artifact_builder.advance(-86400) @@ -39,42 +39,41 @@ def artifacts(_options: FixtureOptions, fixtures: Fixtures) -> dict[str, Build]: return {"published": published, "latest": latest} -@fixture.requires("publisher", "builds") +@given("publisher", "builds") +@where( + records_db={"records_backend": "memory"}, + builds={"machines": ["babette", "lighthouse", "web"], "num_days": 3, "per_day": 2}, +) class TestCase(BaseTestCase): - options = { - "records_backend": "memory", - "builds": { - "machines": ["babette", "lighthouse", "web"], - "num_days": 3, - "per_day": 2, - }, - } + pass +@given() class DashboardTestCase(TestCase): """Tests for the dashboard view""" - def test(self) -> None: - publisher.publish(latest_build(self.fixtures.builds, "lighthouse")) + def test(self, fixtures: Fixtures) -> None: + publisher.publish(latest_build(fixtures.builds, "lighthouse")) # pull the latest web - publisher.pull(latest_build(self.fixtures.builds, "web")) + publisher.pull(latest_build(fixtures.builds, "web")) response = self.client.get("/") self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, "gentoo_build_publisher/dashboard/main.html") - def test_can_retrieve_view_by_name(self) -> None: + def test_can_retrieve_view_by_name(self, fixtures: Fixtures) -> None: view = urls.reverse("dashboard") self.assertEqual(view, "/") +@given() class ReposDotConfTestCase(TestCase): """Tests for the repos_dot_conf view""" - def test(self) -> None: - publisher.publish(latest_build(self.fixtures.builds, "lighthouse")) + def test(self, fixtures: Fixtures) -> None: + publisher.publish(latest_build(fixtures.builds, "lighthouse")) response = self.client.get("/machines/lighthouse/repos.conf") @@ -82,15 +81,17 @@ def test(self) -> None: self.assertEqual(response.headers["Content-Type"], "text/plain") self.assertTemplateUsed(response, "gentoo_build_publisher/repos.conf") - def test_non_published(self) -> None: - publisher.pull(latest_build(self.fixtures.builds, "lighthouse")) + def test_non_published(self, fixtures: Fixtures) -> None: + publisher.pull(latest_build(fixtures.builds, "lighthouse")) response = self.client.get("/machines/lighthouse/repos.conf") self.assertEqual(response.status_code, 404) - def test_tagged_builds_should_have_a_repos_dot_conf(self) -> None: - publisher.pull(build := latest_build(self.fixtures.builds, "lighthouse")) + def test_tagged_builds_should_have_a_repos_dot_conf( + self, fixtures: Fixtures + ) -> None: + publisher.pull(build := latest_build(fixtures.builds, "lighthouse")) publisher.tag(build, "prod") response = self.client.get("/machines/lighthouse@prod/repos.conf") @@ -100,17 +101,18 @@ def test_tagged_builds_should_have_a_repos_dot_conf(self) -> None: self.assertTemplateUsed(response, "gentoo_build_publisher/repos.conf") self.assertTrue(b"/repos/lighthouse@prod/" in response.content) - def test_nonexistent_tags_should_return_404(self) -> None: + def test_nonexistent_tags_should_return_404(self, fixtures: Fixtures) -> None: response = self.client.get("/machines/lighthouse@prod/repos.conf") self.assertEqual(response.status_code, 404) +@given() class BinReposDotConfTestCase(TestCase): """Tests for the repos_dot_conf view""" - def test(self) -> None: - publisher.publish(latest_build(self.fixtures.builds, "lighthouse")) + def test(self, fixtures: Fixtures) -> None: + publisher.publish(latest_build(fixtures.builds, "lighthouse")) response = self.client.get("/machines/lighthouse/binrepos.conf") @@ -118,22 +120,24 @@ def test(self) -> None: self.assertEqual(response.headers["Content-Type"], "text/plain") self.assertTemplateUsed(response, "gentoo_build_publisher/binrepos.conf") - def test_non_published(self) -> None: - publisher.pull(latest_build(self.fixtures.builds, "lighthouse")) + def test_non_published(self, fixtures: Fixtures) -> None: + publisher.pull(latest_build(fixtures.builds, "lighthouse")) response = self.client.get("/machines/lighthouse/binrepos.conf") self.assertEqual(response.status_code, 404) - def test_when_no_such_tag_exists_gives_404(self) -> None: - publisher.pull(latest_build(self.fixtures.builds, "lighthouse")) + def test_when_no_such_tag_exists_gives_404(self, fixtures: Fixtures) -> None: + publisher.pull(latest_build(fixtures.builds, "lighthouse")) response = self.client.get("/machines/lighthouse@bogus/binrepos.conf") self.assertEqual(response.status_code, 404) - def test_tagged_builds_should_have_a_binrepos_dot_conf(self) -> None: - publisher.pull(build := latest_build(self.fixtures.builds, "lighthouse")) + def test_tagged_builds_should_have_a_binrepos_dot_conf( + self, fixtures: Fixtures + ) -> None: + publisher.pull(build := latest_build(fixtures.builds, "lighthouse")) publisher.tag(build, "prod") response = self.client.get("/machines/lighthouse@prod/binrepos.conf") @@ -144,33 +148,32 @@ def test_tagged_builds_should_have_a_binrepos_dot_conf(self) -> None: self.assertTrue(b"/binpkgs/lighthouse@prod/" in response.content) -@fixture.requires("publisher", "client", "builds", artifacts, lighthouse) +@given("publisher", "client", "builds", artifacts, lighthouse) class MachineViewTests(TestCase): """Tests for the machine view""" - def test_row1(self) -> None: + def test_row1(self, fixtures: Fixtures) -> None: latest_str = ( 'Latest ' - f"{latest_build(self.fixtures.builds, 'lighthouse').build_id}" + f"{latest_build(fixtures.builds, 'lighthouse').build_id}" ) - self.assertContains(self.fixtures.lighthouse, latest_str) + self.assertContains(fixtures.lighthouse, latest_str) published_str = ( 'Published ' - f"{self.fixtures.artifacts['published'].build_id}" + f"{fixtures.artifacts['published'].build_id}" ) - self.assertContains(self.fixtures.lighthouse, published_str) + self.assertContains(fixtures.lighthouse, published_str) - def test_returns_404_on_nonbuild_machines(self) -> None: + def test_returns_404_on_nonbuild_machines(self, fixtures: Fixtures) -> None: response = self.client.get("/machines/bogus/") self.assertEqual(response.status_code, 404) -@fixture.requires(artifacts) +@given(artifacts) class BinPkgViewTests(TestCase): - def test(self) -> None: - fixtures = self.fixtures + def test(self, fixtures: Fixtures) -> None: package = fixtures.artifacts["latest"] client = self.client url = ( @@ -187,7 +190,7 @@ def test(self) -> None: ) self.assertTrue(response["Location"].endswith(expected), response["Location"]) - def test_when_build_does_not_exist(self) -> None: + def test_when_build_does_not_exist(self, fixtures: Fixtures) -> None: client = self.client url = "/machines/bogus/builds/2/packages/x11-apps/xhost/xhost-1.0.10-1" @@ -195,8 +198,7 @@ def test_when_build_does_not_exist(self) -> None: self.assertEqual(response.status_code, 404, response.content) - def test_when_pkg_does_not_exist(self) -> None: - fixtures = self.fixtures + def test_when_pkg_does_not_exist(self, fixtures: Fixtures) -> None: package = fixtures.artifacts["latest"] client = self.client diff --git a/tests/test_views_context.py b/tests/test_views_context.py index 101e869..6ee6776 100644 --- a/tests/test_views_context.py +++ b/tests/test_views_context.py @@ -1,12 +1,11 @@ """Tests for the views context helpers""" -# pylint: disable=missing-docstring +# pylint: disable=missing-docstring,unused-argument import datetime as dt from typing import Any, Generator from unittest import mock from zoneinfo import ZoneInfo -import unittest_fixtures as fixture from django.utils import timezone from gbp_testkit import TestCase from gbp_testkit.factories import ( @@ -16,6 +15,7 @@ package_factory, ) from gbp_testkit.helpers import QuickCache +from unittest_fixtures import Fixtures, fixture, given from gentoo_build_publisher import publisher from gentoo_build_publisher.utils import Color @@ -27,11 +27,8 @@ create_machine_context, ) -FixtureOptions = fixture.FixtureOptions -Fixtures = fixture.Fixtures - -@fixture.requires("publisher") +@given("publisher") class CreateDashboardContextTests(TestCase): """Tests for create_dashboard_context()""" @@ -45,10 +42,10 @@ def input_context(self, **kwargs: Any) -> ViewInputContext: defaults |= kwargs return ViewInputContext(**defaults) - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: lighthouse1 = BuildFactory(machine="lighthouse") for cpv in ["dev-vcs/git-2.34.1", "app-portage/gentoolkit-0.5.1-r1"]: - self.fixtures.publisher.jenkins.artifact_builder.build(lighthouse1, cpv) + fixtures.publisher.jenkins.artifact_builder.build(lighthouse1, cpv) publisher.pull(lighthouse1) polaris1 = BuildFactory(machine="polaris") @@ -90,7 +87,7 @@ def test(self) -> None: }, ) - def test_latest_published(self) -> None: + def test_latest_published(self, fixtures: Fixtures) -> None: babette = BuildFactory(machine="babette") publisher.publish(babette) publisher.pull(BuildFactory(machine="lighthouse")) @@ -100,7 +97,7 @@ def test_latest_published(self) -> None: self.assertEqual(ctx["latest_published"], set([publisher.record(babette)])) self.assertEqual(ctx["unpublished_builds_count"], 2) - def test_builds_over_time_and_build_recently(self) -> None: + def test_builds_over_time_and_build_recently(self, fixtures: Fixtures) -> None: now = dt.datetime(2024, 1, 17, 4, 51, tzinfo=dt.UTC) for machine in ["babette", "lighthouse"]: for day in range(2): @@ -120,10 +117,8 @@ def test_builds_over_time_and_build_recently(self) -> None: self.assertEqual(len(ctx["built_recently"]), 2) -@fixture.depends("publisher") -def pf_fixture( - _options: FixtureOptions, fixtures: Fixtures -) -> Generator[str, None, None]: +@fixture("publisher") +def pf_fixture(_options: Any, fixtures: Fixtures) -> Generator[str, None, None]: pf = package_factory() ab: ArtifactFactory = fixtures.publisher.jenkins.artifact_builder ab.initial_packages = [] @@ -132,7 +127,7 @@ def pf_fixture( return pf -@fixture.requires("publisher", pf_fixture) +@given("publisher", pf_fixture) class CreateMachineContextTests(TestCase): def input_context(self, **kwargs: Any) -> MachineInputContext: defaults: dict[str, Any] = { @@ -144,52 +139,48 @@ def input_context(self, **kwargs: Any) -> MachineInputContext: defaults |= kwargs return MachineInputContext(**defaults) - def test_average_storage(self) -> None: + def test_average_storage(self, fixtures: Fixtures) -> None: total_size = 0 build_size = 0 for _ in range(3): - self.fixtures.publisher.jenkins.artifact_builder.advance(3600) + fixtures.publisher.jenkins.artifact_builder.advance(3600) build = BuildFactory() for _pkgs in range(3): - cpv = next(self.fixtures.pf) - pkg = self.fixtures.publisher.jenkins.artifact_builder.build(build, cpv) + cpv = next(fixtures.pf) + pkg = fixtures.publisher.jenkins.artifact_builder.build(build, cpv) build_size += pkg.size total_size += build_size publisher.pull(build) now = localtime( - dt.datetime.fromtimestamp( - self.fixtures.publisher.jenkins.artifact_builder.timer - ) + dt.datetime.fromtimestamp(fixtures.publisher.jenkins.artifact_builder.timer) ) input_context = self.input_context(now=now, machine=build.machine) ctx = create_machine_context(input_context) self.assertEqual(ctx["average_storage"], total_size / 3) - def test_packages_built_today(self) -> None: + def test_packages_built_today(self, fixtures: Fixtures) -> None: for day in [1, 1, 1, 0]: - self.fixtures.publisher.jenkins.artifact_builder.advance( - day * SECONDS_PER_DAY - ) + fixtures.publisher.jenkins.artifact_builder.advance(day * SECONDS_PER_DAY) build = BuildFactory() for _ in range(3): - cpv = next(self.fixtures.pf) - self.fixtures.publisher.jenkins.artifact_builder.build(build, cpv) + cpv = next(fixtures.pf) + fixtures.publisher.jenkins.artifact_builder.build(build, cpv) publisher.pull(build) now = localtime( - dt.datetime.fromtimestamp( - self.fixtures.publisher.jenkins.artifact_builder.timer - ) + dt.datetime.fromtimestamp(fixtures.publisher.jenkins.artifact_builder.timer) ) input_context = self.input_context(now=now, machine=build.machine) ctx = create_machine_context(input_context) self.assertEqual(len(ctx["packages_built_today"]), 6) - def test_packages_built_today_when_build_built_is_none(self) -> None: + def test_packages_built_today_when_build_built_is_none( + self, fixtures: Fixtures + ) -> None: built = utctime(dt.datetime(2021, 4, 25, 7, 50, 7)) submitted = utctime(dt.datetime(2021, 4, 25, 7, 56, 2)) completed = utctime(dt.datetime(2021, 4, 25, 7, 56, 36)) diff --git a/tests/test_views_utils.py b/tests/test_views_utils.py index 0c75e8c..eca00a7 100644 --- a/tests/test_views_utils.py +++ b/tests/test_views_utils.py @@ -1,10 +1,9 @@ """Tests for the dashboard utils""" -# pylint: disable=missing-docstring +# pylint: disable=missing-docstring,unused-argument import datetime as dt from unittest import mock -import unittest_fixtures as fixture from django.http import Http404, HttpRequest, HttpResponse from django.utils import timezone from gbp_testkit import DjangoTestCase, TestCase @@ -15,6 +14,7 @@ package_factory, ) from gbp_testkit.helpers import QuickCache +from unittest_fixtures import Fixtures, given from gentoo_build_publisher import publisher from gentoo_build_publisher.types import Build, Content @@ -28,11 +28,11 @@ ) -@fixture.requires("publisher") +@given("publisher") class GetMetadataTestCase(TestCase): """This is just cached Storage.get_metadata()""" - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: build = BuildFactory() cache = QuickCache() publisher.pull(build) @@ -42,7 +42,7 @@ def test(self) -> None: self.assertEqual(metadata, publisher.storage.get_metadata(build)) self.assertEqual(cache.cache, {f"metadata-{build}": metadata}) - def test_when_cached_return_cache(self) -> None: + def test_when_cached_return_cache(self, fixtures: Fixtures) -> None: build = BuildFactory() cache = QuickCache() cache.set(f"metadata-{build}", [1, 2, 3]) # not real metadata @@ -72,19 +72,19 @@ def test_with_invalid_queryparam(self) -> None: self.assertEqual(chart_days, 10) -@fixture.requires("publisher") +@given("publisher") class StatsCollectorTests(TestCase): def stats_collector(self) -> StatsCollector: return StatsCollector(QuickCache()) - def test_init(self) -> None: + def test_init(self, fixtures: Fixtures) -> None: publisher.pull(BuildFactory(machine="lighthouse")) publisher.pull(BuildFactory(machine="babette")) sc = self.stats_collector() self.assertEqual(sc.machines, ["babette", "lighthouse"]) - def test_package_count(self) -> None: + def test_package_count(self, fixtures: Fixtures) -> None: for build in [ *create_builds_and_packages( "babette", 5, 2, publisher.jenkins.artifact_builder @@ -103,7 +103,7 @@ def test_package_count(self) -> None: self.assertEqual(sc.package_count("babette"), 50) self.assertEqual(sc.package_count("lighthouse"), 36) - def test_build_packages(self) -> None: + def test_build_packages(self, fixtures: Fixtures) -> None: [build] = create_builds_and_packages( "lighthouse", 1, 4, publisher.jenkins.artifact_builder ) @@ -119,7 +119,7 @@ def test_build_packages(self) -> None: ] self.assertEqual(sc.build_packages(build), expected) - def test_latest_published(self) -> None: + def test_latest_published(self, fixtures: Fixtures) -> None: build = None for build in [ *create_builds_and_packages( @@ -143,7 +143,7 @@ def test_latest_published(self) -> None: self.assertEqual(sc.latest_published("babette"), None) self.assertEqual(sc.latest_published("lighthouse"), None) - def test_recent_packages(self) -> None: + def test_recent_packages(self, fixtures: Fixtures) -> None: for build in create_builds_and_packages( "babette", 3, 4, publisher.jenkins.artifact_builder ): @@ -159,7 +159,7 @@ def test_recent_packages(self) -> None: ) self.assertEqual(recent_packages, pkgs_sorted) - def test_total_package_size(self) -> None: + def test_total_package_size(self, fixtures: Fixtures) -> None: for build in create_builds_and_packages( "babette", 3, 4, publisher.jenkins.artifact_builder ): @@ -170,7 +170,7 @@ def test_total_package_size(self) -> None: self.assertEqual(sc.total_package_size("babette"), 15941) self.assertEqual(sc.total_package_size("bogus"), 0) - def test_latest_build(self) -> None: + def test_latest_build(self, fixtures: Fixtures) -> None: build = None for build in create_builds_and_packages( "babette", 3, 4, publisher.jenkins.artifact_builder @@ -183,7 +183,7 @@ def test_latest_build(self) -> None: self.assertEqual(sc.latest_build("babette"), publisher.record(build)) self.assertEqual(sc.latest_build("bogus"), None) - def test_built_recently(self) -> None: + def test_built_recently(self, fixtures: Fixtures) -> None: day = dt.timedelta(days=1) now = timezone.localtime() b1 = publisher.save(BuildRecordFactory(machine="babette")) @@ -197,7 +197,7 @@ def test_built_recently(self) -> None: self.assertFalse(sc.built_recently(b2, now)) self.assertTrue(sc.built_recently(b3, now)) - def test_builds_by_day(self) -> None: + def test_builds_by_day(self, fixtures: Fixtures) -> None: for hour in range(2): publisher.save( BuildRecordFactory(machine="babette"), @@ -225,7 +225,7 @@ def test_builds_by_day(self) -> None: } self.assertEqual(bbd, expected) - def test_packages_by_day(self) -> None: + def test_packages_by_day(self, fixtures: Fixtures) -> None: d1 = dt.datetime(2021, 4, 13, 9, 5) publisher.jenkins.artifact_builder.timer = int(d1.timestamp()) [build] = create_builds_and_packages( @@ -274,9 +274,9 @@ def test_debug_is_true(self) -> None: self.assertEqual(response.status_code, 200) -@fixture.requires("publisher") +@given("publisher") class GetPackageURLTests(DjangoTestCase): - def test(self) -> None: + def test(self, fixtures: Fixtures) -> None: [build] = create_builds_and_packages( "babette", 1, 1, publisher.jenkins.artifact_builder ) diff --git a/tests/test_workers.py b/tests/test_workers.py index b375555..2075539 100644 --- a/tests/test_workers.py +++ b/tests/test_workers.py @@ -1,18 +1,16 @@ """Unit tests for the worker module""" -# pylint: disable=missing-docstring,no-value-for-parameter +# pylint: disable=missing-docstring,no-value-for-parameter,unused-argument import io import os from contextlib import redirect_stderr from pathlib import Path from typing import Callable, cast -from unittest import mock +from unittest import TestCase, mock import fakeredis -import unittest_fixtures as fixture -from gbp_testkit import TestCase from requests import HTTPError -from unittest_fixtures import parametrized +from unittest_fixtures import Fixtures, given, parametrized, where from gentoo_build_publisher import celery as celery_app from gentoo_build_publisher import publisher @@ -52,12 +50,12 @@ def params(*names) -> Callable: return parametrized(ifparams(*names)) -@fixture.requires("publisher") +@given("publisher") class PublishBuildTestCase(TestCase): """Unit tests for tasks.publish_build""" @params("celery", "rq", "sync", "thread") - def test_publishes_build(self, worker: WorkerInterface) -> None: + def test_publishes_build(self, worker: WorkerInterface, fixtures: Fixtures) -> None: """Should actually publish the build""" worker.run(tasks.publish_build, "babette.193") @@ -67,7 +65,7 @@ def test_publishes_build(self, worker: WorkerInterface) -> None: @params("celery", "rq", "sync", "thread") @mock.patch("gentoo_build_publisher.worker.logger.error") def test_should_give_up_when_pull_raises_httperror( - self, worker: WorkerInterface, log_error_mock: mock.Mock + self, worker: WorkerInterface, log_error_mock: mock.Mock, fixtures: Fixtures ) -> None: with mock.patch("gentoo_build_publisher.worker.tasks.pull_build") as apply_mock: apply_mock.side_effect = HTTPError @@ -89,12 +87,12 @@ def test(self, worker: WorkerInterface) -> None: purge_mock.assert_called_once_with("foo") -@fixture.requires("publisher") +@given("publisher") class PullBuildTestCase(TestCase): """Tests for the pull_build task""" @params("celery", "rq", "sync", "thread") - def test_pulls_build(self, worker: WorkerInterface) -> None: + def test_pulls_build(self, worker: WorkerInterface, fixtures: Fixtures) -> None: """Should actually pull the build""" worker.run(tasks.pull_build, "lima.1012", note=None, tags=None) @@ -102,7 +100,9 @@ def test_pulls_build(self, worker: WorkerInterface) -> None: self.assertIs(publisher.pulled(build), True) @params("celery", "rq", "sync", "thread") - def test_calls_purge_machine(self, worker: WorkerInterface) -> None: + def test_calls_purge_machine( + self, worker: WorkerInterface, fixtures: Fixtures + ) -> None: """Should issue the purge_machine task when setting is true""" with mock.patch( "gentoo_build_publisher.worker.tasks.purge_machine" @@ -113,7 +113,9 @@ def test_calls_purge_machine(self, worker: WorkerInterface) -> None: mock_purge_machine.assert_called_with("charlie") @params("celery", "rq", "sync", "thread") - def test_does_not_call_purge_machine(self, worker: WorkerInterface) -> None: + def test_does_not_call_purge_machine( + self, worker: WorkerInterface, fixtures: Fixtures + ) -> None: """Should not issue the purge_machine task when setting is false""" with mock.patch( "gentoo_build_publisher.worker.tasks.purge_machine" @@ -126,7 +128,7 @@ def test_does_not_call_purge_machine(self, worker: WorkerInterface) -> None: @params("celery", "rq", "sync", "thread") @mock.patch("gentoo_build_publisher.worker.logger.error", new=mock.Mock()) def test_should_delete_db_model_when_download_fails( - self, worker: WorkerInterface + self, worker: WorkerInterface, fixtures: Fixtures ) -> None: settings = Settings.from_environ() records = build_records(settings) @@ -190,29 +192,28 @@ def test_invalid(self) -> None: Worker(settings) -@fixture.requires("settings") +@given("settings") +@where( + environ={ + "BUILD_PUBLISHER_JENKINS_BASE_URL": "http://jenkins.invalid/", + "BUILD_PUBLISHER_WORKER_BACKEND": "rq", + "BUILD_PUBLISHER_WORKER_CELERY_CONCURRENCY": "55", + "BUILD_PUBLISHER_WORKER_CELERY_EVENTS": "True", + "BUILD_PUBLISHER_WORKER_CELERY_HOSTNAME": "gbp.invalid", + "BUILD_PUBLISHER_WORKER_CELERY_LOGLEVEL": "DEBUG", + "BUILD_PUBLISHER_WORKER_RQ_NAME": "test-worker", + "BUILD_PUBLISHER_WORKER_RQ_QUEUE_NAME": "test-queue", + "BUILD_PUBLISHER_WORKER_RQ_URL": "redis://localhost.invalid:6379", + "BUILD_PUBLISHER_STORAGE_PATH": "/dev/null", + } +) class WorkMethodTests(TestCase): """Tests for the WorkerInterface.work methods""" - options = { - "environ": { - "BUILD_PUBLISHER_JENKINS_BASE_URL": "http://jenkins.invalid/", - "BUILD_PUBLISHER_WORKER_BACKEND": "rq", - "BUILD_PUBLISHER_WORKER_CELERY_CONCURRENCY": "55", - "BUILD_PUBLISHER_WORKER_CELERY_EVENTS": "True", - "BUILD_PUBLISHER_WORKER_CELERY_HOSTNAME": "gbp.invalid", - "BUILD_PUBLISHER_WORKER_CELERY_LOGLEVEL": "DEBUG", - "BUILD_PUBLISHER_WORKER_RQ_NAME": "test-worker", - "BUILD_PUBLISHER_WORKER_RQ_QUEUE_NAME": "test-queue", - "BUILD_PUBLISHER_WORKER_RQ_URL": "redis://localhost.invalid:6379", - "BUILD_PUBLISHER_STORAGE_PATH": "/dev/null", - } - } - - def test_celery(self) -> None: + def test_celery(self, fixtures: Fixtures) -> None: path = "gentoo_build_publisher.worker.celery.Worker" with mock.patch(path) as mock_worker: - CeleryWorker.work(self.fixtures.settings) + CeleryWorker.work(fixtures.settings) mock_worker.assert_called_with( app=celery_app, @@ -223,18 +224,18 @@ def test_celery(self) -> None: ) mock_worker.return_value.start.assert_called_once_with() - def test_sync(self) -> None: + def test_sync(self, fixtures: Fixtures) -> None: stderr_path = "gentoo_build_publisher.worker.sync.sys.stderr" with ( self.assertRaises(SystemExit) as context, mock.patch(stderr_path) as mock_stderr, ): - SyncWorker.work(self.fixtures.settings) + SyncWorker.work(fixtures.settings) self.assertEqual(context.exception.args, (1,)) mock_stderr.write.assert_called_once_with("SyncWorker has no worker\n") - def test_rq(self) -> None: + def test_rq(self, fixtures: Fixtures) -> None: worker_path = "gentoo_build_publisher.worker.rq.Worker" redis_path = "gentoo_build_publisher.worker.rq.Redis" @@ -242,7 +243,7 @@ def test_rq(self) -> None: mock.patch(worker_path) as mock_worker, mock.patch(redis_path) as mock_redis, ): - RQWorker.work(self.fixtures.settings) + RQWorker.work(fixtures.settings) mock_redis.from_url.assert_called_once_with("redis://localhost.invalid:6379") connection = mock_redis.from_url.return_value