From 5879080d7aff27fd639e86ba7360d016b1c92643 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Tue, 21 May 2024 15:28:45 -0600 Subject: [PATCH] Update to pydantic 2 The pydantic usage here is pretty light, so the changes needed aren't that dramatic. * The dataclass `__post_init_post_parse__` method is no longer supported and simply `__post_init__` should be used. * `TypeError` is no longer converted to `ValidationError` in validators, so just use `ValueError`. * The `@validator` decorator has changed to `@field_decorator` with a minor change in parameters. * Validator error messages now include the error type, which means `Value error` for all of our validators. * The `ValidationError.errors()` detail list now has a custom `ErrorDetail` type. This exposes the fact that the `loc` attribute is actually a tuple of `str` and `int`. Mypy flags that as an issue if an `int` is passed to `str.join`. We don't actually have any cases where an `int` would occur, but copy a converter from the documentation so it's handled correctly in case that does happen. This also allows dropping the mypy upper version pin as updated Pydantic contains the necessary compatibility fix. https://docs.pydantic.dev/2.7/migration/ --- Pipfile | 4 +- Pipfile.lock | 193 ++++++++++++++------- azafea_metrics_proxy/config/__init__.py | 34 ++-- azafea_metrics_proxy/config/_validators.py | 6 +- azafea_metrics_proxy/tests/test_cli.py | 10 +- azafea_metrics_proxy/tests/test_config.py | 30 ++-- 6 files changed, 188 insertions(+), 89 deletions(-) diff --git a/Pipfile b/Pipfile index ae15401..28e1877 100644 --- a/Pipfile +++ b/Pipfile @@ -8,7 +8,7 @@ python_version = "3.11" flake8 = "*" flake8-bugbear = "*" freezegun = "*" -mypy = ">=0.720, < 0.920" +mypy = ">=0.720" pytest = "*" pytest-aiohttp = "*" pytest-asyncio = "*" @@ -18,7 +18,7 @@ types-toml = "*" [packages] aiohttp = ">= 3.5.0" aioredis = "~= 1.3" -pydantic = ">= 1.1, < 1.9" +pydantic = "~= 2.7" toml = "*" [scripts] diff --git a/Pipfile.lock b/Pipfile.lock index ce9d667..187ef1f 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "197fb4a955d6065806161b9c0fa63456286c79d6e5ad53cacc3b3e58271c7d49" + "sha256": "eae32f40beffca4cf98a9bb20da1a203ecdff7de1578ac67aba88bb5c33f3c1a" }, "pipfile-spec": 6, "requires": { @@ -115,6 +115,14 @@ "markers": "python_version >= '3.7'", "version": "==1.3.1" }, + "annotated-types": { + "hashes": [ + "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", + "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" + ], + "markers": "python_version >= '3.8'", + "version": "==0.7.0" + }, "async-timeout": { "hashes": [ "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", @@ -435,32 +443,97 @@ }, "pydantic": { "hashes": [ - "sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd", - "sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739", - "sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f", - "sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840", - "sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23", - "sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287", - "sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62", - "sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b", - "sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb", - "sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820", - "sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3", - "sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b", - "sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e", - "sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3", - "sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316", - "sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b", - "sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4", - "sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20", - "sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e", - "sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505", - "sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1", - "sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833" + "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5", + "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc" ], "index": "pypi", - "markers": "python_full_version >= '3.6.1'", - "version": "==1.8.2" + "markers": "python_version >= '3.8'", + "version": "==2.7.1" + }, + "pydantic-core": { + "hashes": [ + "sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b", + "sha256:042473b6280246b1dbf530559246f6842b56119c2926d1e52b631bdc46075f2a", + "sha256:05b7133a6e6aeb8df37d6f413f7705a37ab4031597f64ab56384c94d98fa0e90", + "sha256:0680b1f1f11fda801397de52c36ce38ef1c1dc841a0927a94f226dea29c3ae3d", + "sha256:0d69b4c2f6bb3e130dba60d34c0845ba31b69babdd3f78f7c0c8fae5021a253e", + "sha256:1404c69d6a676245199767ba4f633cce5f4ad4181f9d0ccb0577e1f66cf4c46d", + "sha256:182245ff6b0039e82b6bb585ed55a64d7c81c560715d1bad0cbad6dfa07b4027", + "sha256:1a388a77e629b9ec814c1b1e6b3b595fe521d2cdc625fcca26fbc2d44c816804", + "sha256:1d90c3265ae107f91a4f279f4d6f6f1d4907ac76c6868b27dc7fb33688cfb347", + "sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400", + "sha256:219da3f096d50a157f33645a1cf31c0ad1fe829a92181dd1311022f986e5fbe3", + "sha256:22057013c8c1e272eb8d0eebc796701167d8377441ec894a8fed1af64a0bf399", + "sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349", + "sha256:224c421235f6102e8737032483f43c1a8cfb1d2f45740c44166219599358c2cd", + "sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c", + "sha256:269322dcc3d8bdb69f054681edff86276b2ff972447863cf34c8b860f5188e2e", + "sha256:2728b01246a3bba6de144f9e3115b532ee44bd6cf39795194fb75491824a1413", + "sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3", + "sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e", + "sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3", + "sha256:390193c770399861d8df9670fb0d1874f330c79caaca4642332df7c682bf6b91", + "sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce", + "sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c", + "sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb", + "sha256:4456f2dca97c425231d7315737d45239b2b51a50dc2b6f0c2bb181fce6207664", + "sha256:470b94480bb5ee929f5acba6995251ada5e059a5ef3e0dfc63cca287283ebfa6", + "sha256:4774f3184d2ef3e14e8693194f661dea5a4d6ca4e3dc8e39786d33a94865cefd", + "sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3", + "sha256:553ef617b6836fc7e4df130bb851e32fe357ce36336d897fd6646d6058d980af", + "sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043", + "sha256:6a46e22a707e7ad4484ac9ee9f290f9d501df45954184e23fc29408dfad61350", + "sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7", + "sha256:75250dbc5290e3f1a0f4618db35e51a165186f9034eff158f3d490b3fed9f8a0", + "sha256:75f7e9488238e920ab6204399ded280dc4c307d034f3924cd7f90a38b1829563", + "sha256:78363590ef93d5d226ba21a90a03ea89a20738ee5b7da83d771d283fd8a56761", + "sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72", + "sha256:800d60565aec896f25bc3cfa56d2277d52d5182af08162f7954f938c06dc4ee3", + "sha256:82d5d4d78e4448683cb467897fe24e2b74bb7b973a541ea1dcfec1d3cbce39fb", + "sha256:852e966fbd035a6468fc0a3496589b45e2208ec7ca95c26470a54daed82a0788", + "sha256:868649da93e5a3d5eacc2b5b3b9235c98ccdbfd443832f31e075f54419e1b96b", + "sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c", + "sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038", + "sha256:95b9d5e72481d3780ba3442eac863eae92ae43a5f3adb5b4d0a1de89d42bb250", + "sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec", + "sha256:997abc4df705d1295a42f95b4eec4950a37ad8ae46d913caeee117b6b198811c", + "sha256:9b5155ff768083cb1d62f3e143b49a8a3432e6789a3abee8acd005c3c7af1c74", + "sha256:9e08e867b306f525802df7cd16c44ff5ebbe747ff0ca6cf3fde7f36c05a59a81", + "sha256:9fdad8e35f278b2c3eb77cbdc5c0a49dada440657bf738d6905ce106dc1de439", + "sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75", + "sha256:a8309f67285bdfe65c372ea3722b7a5642680f3dba538566340a9d36e920b5f0", + "sha256:ae0a8a797a5e56c053610fa7be147993fe50960fa43609ff2a9552b0e07013e8", + "sha256:b14d82cdb934e99dda6d9d60dc84a24379820176cc4a0d123f88df319ae9c150", + "sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438", + "sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae", + "sha256:b89ed9eb7d616ef5714e5590e6cf7f23b02d0d539767d33561e3675d6f9e3857", + "sha256:c4fcf5cd9c4b655ad666ca332b9a081112cd7a58a8b5a6ca7a3104bc950f2038", + "sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374", + "sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f", + "sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241", + "sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592", + "sha256:cc1cfd88a64e012b74e94cd00bbe0f9c6df57049c97f02bb07d39e9c852e19a4", + "sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d", + "sha256:cfeecd1ac6cc1fb2692c3d5110781c965aabd4ec5d32799773ca7b1456ac636b", + "sha256:d4d938ec0adf5167cb335acb25a4ee69a8107e4984f8fbd2e897021d9e4ca21b", + "sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182", + "sha256:d91cb5ea8b11607cc757675051f61b3d93f15eca3cefb3e6c704a5d6e8440f4e", + "sha256:d9319e499827271b09b4e411905b24a426b8fb69464dfa1696258f53a3334641", + "sha256:e0e8b1be28239fc64a88a8189d1df7fad8be8c1ae47fcc33e43d4be15f99cc70", + "sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9", + "sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a", + "sha256:e23ec367a948b6d812301afc1b13f8094ab7b2c280af66ef450efc357d2ae543", + "sha256:e25add29b8f3b233ae90ccef2d902d0ae0432eb0d45370fe315d1a5cf231004b", + "sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f", + "sha256:ef26c9e94a8c04a1b2924149a9cb081836913818e55681722d7f29af88fe7b38", + "sha256:eff2de745698eb46eeb51193a9f41d67d834d50e424aef27df2fcdee1b153845", + "sha256:f0a21cbaa69900cbe1a2e7cad2aa74ac3cf21b10c3efb0fa0b80305274c0e8a2", + "sha256:f459a5ce8434614dfd39bbebf1041952ae01da6bed9855008cb33b875cb024c0", + "sha256:f93a8a2e3938ff656a7c1bc57193b1319960ac015b6e87d76c76bf14fe0244b4", + "sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242" + ], + "markers": "python_version >= '3.8'", + "version": "==2.18.2" }, "toml": { "hashes": [ @@ -969,40 +1042,45 @@ }, "mypy": { "hashes": [ - "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9", - "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a", - "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9", - "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e", - "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2", - "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212", - "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b", - "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885", - "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150", - "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703", - "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072", - "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457", - "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e", - "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0", - "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb", - "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97", - "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8", - "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811", - "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6", - "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de", - "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504", - "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921", - "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d" + "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061", + "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99", + "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de", + "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a", + "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9", + "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec", + "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1", + "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131", + "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f", + "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821", + "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5", + "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee", + "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e", + "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746", + "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2", + "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0", + "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b", + "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53", + "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30", + "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda", + "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051", + "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2", + "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7", + "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee", + "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727", + "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976", + "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4" ], "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==0.910" + "markers": "python_version >= '3.8'", + "version": "==1.10.0" }, "mypy-extensions": { "hashes": [ - "sha256:c8b707883a96efe9b4bb3aaf0dcc07e7e217d7d8368eec4db4049ee9e142f4fd" + "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", + "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" ], - "markers": "python_version >= '2.7'", - "version": "==0.4.4" + "markers": "python_version >= '3.5'", + "version": "==1.0.0" }, "packaging": { "hashes": [ @@ -1088,15 +1166,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, - "toml": { - "hashes": [ - "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", - "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" - ], - "index": "pypi", - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.10.2" - }, "types-toml": { "hashes": [ "sha256:3d41501302972436a6b8b239c850b26689657e25281b48ff0ec06345b8830331", diff --git a/azafea_metrics_proxy/config/__init__.py b/azafea_metrics_proxy/config/__init__.py index b79f7b0..920223c 100644 --- a/azafea_metrics_proxy/config/__init__.py +++ b/azafea_metrics_proxy/config/__init__.py @@ -23,11 +23,11 @@ import dataclasses import logging import os -from typing import Any, Dict, List, MutableMapping +from typing import Any, List, MutableMapping -from pydantic.class_validators import validator +from pydantic import field_validator, ValidationError from pydantic.dataclasses import dataclass -from pydantic.error_wrappers import ValidationError +from pydantic_core import ErrorDetails import toml @@ -40,18 +40,32 @@ class InvalidConfigurationError(Exception): - def __init__(self, errors: List[Dict[str, Any]]) -> None: + def __init__(self, errors: List[ErrorDetails]) -> None: self.errors = errors def __str__(self) -> str: msg = ['Invalid configuration:'] for e in self.errors: - loc = e['loc'] - msg.append(f"* {'.'.join(loc)}: {e['msg']}") + loc = self._loc_str(e) + msg.append(f"* {loc}: {e['msg']}") return '\n'.join(msg) + # The loc field in ErrorDetails is a tuple of strings and ints. + # https://docs.pydantic.dev/latest/errors/errors/#customize-error-messages + @staticmethod + def _loc_str(details: ErrorDetails) -> str: + path = '' + for i, element in enumerate(details['loc']): + if isinstance(element, str): + if i > 0: + path += '.' + path += element + else: # pragma: no cover (our config does not use lists) + path += f'[{element}]' + return path + class NoSuchConfigurationError(AttributeError): pass @@ -66,7 +80,7 @@ def __getattr__(self, name: str) -> Any: class Main(_Base): verbose: bool = False - @validator('verbose', pre=True) + @field_validator('verbose', mode='before') def verbose_is_boolean(cls, value: Any) -> bool: return is_boolean(value) @@ -78,11 +92,11 @@ class Redis(_Base): password: str = DEFAULT_PASSWORD ssl: bool = False - @validator('host', pre=True) + @field_validator('host', mode='before') def host_is_non_empty_string(cls, value: Any) -> str: return is_non_empty_string(value) - @validator('port', pre=True) + @field_validator('port', mode='before') def port_is_strictly_positive_integer(cls, value: Any) -> int: return is_strictly_positive_integer(value) @@ -92,7 +106,7 @@ class Config(_Base): main: Main = dataclasses.field(default_factory=Main) redis: Redis = dataclasses.field(default_factory=Redis) - def __post_init_post_parse__(self) -> None: + def __post_init__(self) -> None: self.warn_about_default_passwords() @classmethod diff --git a/azafea_metrics_proxy/config/_validators.py b/azafea_metrics_proxy/config/_validators.py index bbff6f1..04f8d21 100644 --- a/azafea_metrics_proxy/config/_validators.py +++ b/azafea_metrics_proxy/config/_validators.py @@ -25,14 +25,14 @@ def is_boolean(value: Any) -> bool: if not isinstance(value, bool): - raise TypeError(f'{value!r} is not a boolean') + raise ValueError(f'{value!r} is not a boolean') return value def is_non_empty_string(value: Any) -> str: if not isinstance(value, str): - raise TypeError(f'{value!r} is not a string') + raise ValueError(f'{value!r} is not a string') if not value: raise ValueError(f'{value!r} is empty') @@ -42,7 +42,7 @@ def is_non_empty_string(value: Any) -> str: def is_strictly_positive_integer(value: Any) -> int: if type(value) is not int: - raise TypeError(f'{value!r} is not an integer') + raise ValueError(f'{value!r} is not an integer') if value < 1: raise ValueError(f'{value!r} is not a strictly positive integer') diff --git a/azafea_metrics_proxy/tests/test_cli.py b/azafea_metrics_proxy/tests/test_cli.py index 7411057..8fbf471 100644 --- a/azafea_metrics_proxy/tests/test_cli.py +++ b/azafea_metrics_proxy/tests/test_cli.py @@ -51,7 +51,10 @@ def test_print_invalid_config(capfd, make_config_file): azafea_metrics_proxy.cli.run_command('-c', str(config_file), 'print-config') capture = capfd.readouterr() - assert "Invalid configuration:\n* main.verbose: 'blah' is not a boolean" in capture.err + assert ( + "Invalid configuration:\n" + "* main.verbose: Value error, 'blah' is not a boolean" + ) in capture.err def test_run(capfd, monkeypatch, make_config_file): @@ -79,7 +82,10 @@ def test_run_invalid_config(capfd, make_config_file): azafea_metrics_proxy.cli.run_command('-c', str(config_file), 'run') capture = capfd.readouterr() - assert "Invalid configuration:\n* main.verbose: 'blah' is not a boolean" in capture.err + assert ( + "Invalid configuration:\n" + "* main.verbose: Value error, 'blah' is not a boolean" + ) in capture.err def test_run_redis_invalid_host(capfd, make_config_file): diff --git a/azafea_metrics_proxy/tests/test_config.py b/azafea_metrics_proxy/tests/test_config.py index bbef79b..1a19e27 100644 --- a/azafea_metrics_proxy/tests/test_config.py +++ b/azafea_metrics_proxy/tests/test_config.py @@ -87,8 +87,10 @@ def test_override_verbose_invalid(make_config, value): with pytest.raises(azafea_metrics_proxy.config.InvalidConfigurationError) as exc_info: make_config({'main': {'verbose': value}}) - assert ('Invalid configuration:\n' - f'* main.verbose: {value!r} is not a boolean') in str(exc_info.value) + assert ( + 'Invalid configuration:\n' + f'* main.verbose: Value error, {value!r} is not a boolean' + ) in str(exc_info.value) @pytest.mark.parametrize('value', [ @@ -100,16 +102,20 @@ def test_override_redis_host_invalid(make_config, value): with pytest.raises(azafea_metrics_proxy.config.InvalidConfigurationError) as exc_info: make_config({'redis': {'host': value}}) - assert ('Invalid configuration:\n' - f'* redis.host: {value!r} is not a string') in str(exc_info.value) + assert ( + 'Invalid configuration:\n' + f'* redis.host: Value error, {value!r} is not a string' + ) in str(exc_info.value) def test_override_redis_host_empty(make_config): with pytest.raises(azafea_metrics_proxy.config.InvalidConfigurationError) as exc_info: make_config({'redis': {'host': ''}}) - assert ('Invalid configuration:\n' - "* redis.host: '' is empty") in str(exc_info.value) + assert ( + 'Invalid configuration:\n' + "* redis.host: Value error, '' is empty" + ) in str(exc_info.value) @pytest.mark.parametrize('value', [ @@ -121,8 +127,10 @@ def test_override_redis_port_invalid(make_config, value): with pytest.raises(azafea_metrics_proxy.config.InvalidConfigurationError) as exc_info: make_config({'redis': {'port': value}}) - assert ('Invalid configuration:\n' - f'* redis.port: {value!r} is not an integer') in str(exc_info.value) + assert ( + 'Invalid configuration:\n' + f'* redis.port: Value error, {value!r} is not an integer' + ) in str(exc_info.value) @pytest.mark.parametrize('value', [ @@ -133,8 +141,10 @@ def test_override_redis_port_not_positive(make_config, value): with pytest.raises(azafea_metrics_proxy.config.InvalidConfigurationError) as exc_info: make_config({'redis': {'port': value}}) - assert ('Invalid configuration:\n' - f'* redis.port: {value!r} is not a strictly positive integer') in str(exc_info.value) + assert ( + 'Invalid configuration:\n' + f'* redis.port: Value error, {value!r} is not a strictly positive integer' + ) in str(exc_info.value) def test_default_passwords(capfd):